linux 內核實驗六實現


構造新內核同步機制實驗

實驗目的:
實驗問題A
分析以上進程同步機制的功能和工作過程,通過重新定義struct __myevent結構來模擬一個信號量同步機制,並編寫測試程序檢測它的功能。
實驗問題B
在2.6節實驗問題B中我們加入了一個缺頁計數器每當調用缺頁處理函數則對其加一,並利用自定義系統調用返回該值。考慮一個併發控制方
案,利用實驗A實現的信號量控制多個進程與缺頁處理器互斥的訪問缺頁計數器。(可編一個shell批處理命令併發啓動多個進程訪問缺頁計
數)。
程序完整源代碼:
增加新的系統調用
step 1:/usr/src/linux../arch/x86/kernel/syscall_tabel32.S
.long sys_lightbluetest
.long sys_lightbluecall
.long sys_lightbluetime
.long sys_myevent_open
.long sys_myevent_wait
.long sys_myevent_signal
.long sys_myevent_close
.long sys_modifytimes
step 2:/usr/src/linux../arch/x86/include/asm/unistd_32.h
#/usr/src/linux../include/asm-generic/unistd.h
#define __NR_lightbluetest 347
#define __NR_lightbluecall 348
#define __NR_lightbluetime 349
#define __NR_myevent_open 340
#define __NR_myevent_wait 351
#define __NR_myevent_signal 352
#define __NR_myevent_close 353
#define __NR_modifytimes 354
and modify the __NR_syscall 355
become
#define __NR_lightbluetest 347
#define __NR_lightbluecall 348
#define __NR_lightbluetime 349
#define __NR_myevent_open 350
#define __NR_myevent_wait 351
#define __NR_myevent_signal 352
#define __NR_myevent_close 353
#define __NR_modifytimes 354
#ifdef __KERNEL__
#define __NR_syscall 355
step 3:/usr/src/linux../include/linux/syscall.h
add the function statements as below
asmlinkage long sys_lightbluetest(void);
asmlinkage long sys_lightbluecall(struct timeval* v_time,struct timespec *s_time);
asmlinkage long sys_lightbluetime(struct timeval* v_time,struct timespec * s_time,unsigned long *times) ;
asmlinkage long sys_myevent_open(int eventNum,int count);
asmlinkage long sys_myevent_wait(int eventNum);
asmlinkage long sys_myevent_signal(int eventNum);
asmlinkage long sys_myevent_close(int eventNum);
asmlinkage long sys_modifytimes(unsigned long times);

step 4:/usr/src/linux../kernel/sys.c
#include <linux/time.h>
#include <linux/wait.h>
#include <linux/lightblue.h>
#include <linux/lightbluesema.h>
myevent_t * scheventNum(int eventNum,myevent_t **prev){
myevent_t *tmp=lpmyevent_head;
*prev=NULL;
while(tmp){
if(tmp->eventNum==eventNum)
return tmp;
*prev = tmp;
tmp=tmp->next;
}
return NULL;
}
asmlinkage long sys_lightbluetest(){
printk("lightblue test\n");
return 222;
}
asmlinkage long sys_lightbluecall(struct timeval* v_time,struct timespec *s_time){
printk("hello call\n");
*s_time=current_kernel_time();
do_gettimeofday(v_time);
return 17;
}
asmlinkage long sys_lightbluetime(struct timeval* v_time,struct timespec * s_time,unsigned long *times) {
printk("hello call\n");
*times=lightbluetimes;
*s_time=current_kernel_time();
do_gettimeofday(v_time);
return 17;
}
asmlinkage long sys_myevent_open(int eventNum,int count){
printk("open it\n");
myevent_t * new;
myevent_t *prev;
int result;
if(eventNum)
if(!scheventNum(eventNum,&prev))
result=0;
else
result=eventNum;
else{
new=(myevent_t *)kmalloc(sizeof(myevent_t),GFP_KERNEL);
init_waitqueue_head(&new->p);
new->next=NULL;
new->p.task_list.next=&new->p.task_list;
new->p.task_list.prev=&new->p.task_list;
if(!lpmyevent_head){
new->eventNum=2;
lpmyevent_head =lpmyevent_end=new;
}
else{
new->eventNum=lpmyevent_end->eventNum+2;
lpmyevent_end->next=new;
lpmyevent_end=new;
}
result=new->eventNum;
new->count=count;
}
return result;
//return 18;
}
asmlinkage long sys_myevent_wait(int eventNum){
printk("wait it\n");
myevent_t *tmp;
myevent_t *prev=NULL;

if((tmp=scheventNum(eventNum,&prev))!=NULL){
spin_lock(&tmp->p.lock);
tmp->count--;
spin_unlock(&tmp->p.lock);
if(tmp->count<0){
DEFINE_WAIT(wait);
prepare_to_wait_exclusive(&tmp->p,&wait,TASK_INTERRUPTIBLE);
schedule();
finish_wait(&tmp->p,&wait);
}
return eventNum;
}
return 0;
}
asmlinkage long sys_myevent_signal(int eventNum){
printk("signal it\n");
myevent_t *tmp=NULL;
myevent_t *prev=NULL;
if((tmp=scheventNum(eventNum,&prev))!=NULL){
spin_lock(&tmp->p.lock);
tmp->count++;
spin_unlock(&tmp->p.lock);
if(tmp->count<=0){
wake_up(&tmp->p);
return eventNum;
}
}
return 0;
}
asmlinkage long sys_myevent_close(int eventNum){
printk("close it\n");
myevent_t *prev=NULL;
myevent_t *releaseItem;
if((releaseItem=scheventNum(eventNum,&prev))!=NULL){
if(releaseItem==lpmyevent_end)
lpmyevent_end=prev;
else if(releaseItem==lpmyevent_head)
lpmyevent_head=lpmyevent_head->next;
else
prev->next=releaseItem->next;
sys_myevent_signal(eventNum);
kfree(releaseItem);
return eventNum;
}
return 0;
}
asmlinkage long sys_modifytimes(unsigned long times){
lightbluetimes=times;
return 22;
}
step 5:
/usr/src/linux../include/linux/
vim lightblue.h
extern unsigned long lightbluetimes;
vim lightbluesema.h
add the below codes:
#include <linux/wait.h>
typedef struct __myevent{
int count;
int eventNum;
wait_queue_head_t p;
struct __myevent *next;
}myevent_t;
myevent_t * lpmyevent_head =NULL;
myevent_t * lpmyevent_end=NULL;
step 6:

/usr/src/linux../arch/x86/mm/
vim fault.c
#include <linux/lightblue.h>
before the function 'do_page_fault()' ,add unsigned long lightbluetimes=0;
in the function add :
lightbluetimes++;
測試程序:
mysemaphore.h
int lightblueopen(int num,int count);
int lightblueup(int num);
int lightbluedown(int num);
int lightblueclose(int num);
unsigned long lightbluereadtimes();
int lightbluewritetimes(int times);
mysemaphore.c
#include "mysemaphore.h"
#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>
#include <linux/unistd.h>
#include <sys/syscall.h>
int lightblueopen(int num,int count){
return syscall(350,num,count);
}
int lightblueup(int num){
return syscall(351,num);
}
int lightbluedown(int num){
return syscall(352,num);
}
int lightblueclose(int num){
return syscall(353,num);
}
unsigned long lightbluereadtimes(){
struct timespec *s_time=(struct timespec *)malloc(20);
struct timeval *v_time=(struct timeval*)malloc(20);
unsigned long times=0;
syscall(349,v_time,s_time,×);
free(s_time);
free(v_time);
return times;
}
int lightbluewritetimes(int times){
return syscall(354,times);
}
readandwrite.c
#include "mysemaphore.h"
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
int semanum=0;
int main(){
semanum=lightblueopen(0,2);
int pid;
pid=fork();
if(pid==0){//father process write
int pid2=fork();

if(pid2==0){//father
while(1){
lightblueup(semanum);
printf("father process write \n");
lightbluewritetimes(1);
lightbluedown(semanum);
}
}
else{//child 1 read
while(1){
lightblueup(semanum);
printf("child 1 read page fault times is:%lu\n",lightbluereadtimes());
lightbluedown(semanum);
}
}
}
else{//child 2 read
while(1){
lightblueup(semanum);
printf("child 2 read page fault times is:%lu\n",lightbluereadtimes());
lightbluedown(semanum);
}
}
return 0;
}
myread.c
#include <linux/unistd.h>
#include <sys/syscall.h>
#include <stdio.h>
#include <stdlib.h>
#include "mysemaphore.h"
/*
*read paga fault times
*/
int main(int argc,char *argv[]){
int num=0;
//if(argc>1)
// {
// printf("create new semaphore\n");
// num=atoi(argv[1]);
// printf("semaphore num is:%d\n",num);
// }
// lightblueopen(num,2);//open a new semaphore and its value is 2
int index=3;
unsigned long times=0;
for(index=0;index<4;index++ ){
// lightblueup(num);
times=lightbluereadtimes();
printf("page fault times is:%d\n",times);
}
}
mywrite.c
#include <linux/unistd.h>
#include <sys/syscall.h>
#include <stdio.h>
#include <stdlib.h>
#include "mysemaphore.h"
int main(int argc,char *argv[]){
if(argc==1){
printf("input init times\n");
return 1;
}
int times=atoi(argv[1]);
int index=0;
for(index=0;index<2;index++){
lightbluewritetimes(times);
}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章