本人的Linux作业
0.前情提要
Linux内核编译:
Linux kernel编译记录 | lnm011223の私密房间
查看内核版本:
1.系统调用
创建两个文件:
test.c
Makefile
并放在同一目录下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> MODULE_LICENSE("Dual BSD/GPL" ); static int init (void ) { printk(KERN_INFO "20192132039\nmodi\n" ); return 0 ; } static void clearup (void ) { printk(KERN_INFO "bye\n" ); } module_init(init); module_exit(clearup);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ifneq ($(KERNELRELEASE) ,)r mymodule-objs := test.o obj-m := test.o else PWD := $(shell pwd) KVER ?= $(shell uname -r) KDIR := /lib/modules/$(KVER) /build all: $(MAKE) -C $(KDIR) M=$(PWD) clean: rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions endif
然后打开终端输入以下命令来安装模块并查看信息
1 2 3 4 make insmod test.ko dmesg -c dmesg
卸载模块并查看信息
2.IPC
2.1.管道
无名管道应用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #include <stdlib.h> #include <string.h> main(){ int p1,fd[2 ]; char outpipe[50 ]; char inpipe[50 ]; pipe(fd); while ((p1=fork())==-1 ); if (p1==0 ){ strcpy (inpipe,"This is a message!" ); write(fd[1 ],inpipe,50 ); exit (0 ); } else { wait(0 ); read(fd[0 ],outpipe,50 ); printf ("%s\n" ,outpipe); exit (0 ); } }
改造:
父进程创建两个子进程P1、P2,P1向管道写数据,P2从管道读数据并显示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #include <stdlib.h> #include <string.h> main(){ int p1,p2,fd[2 ]; char outpipe[50 ]; char inpipe[50 ]; pipe(fd); while ((p1=fork())==-1 ); while ((p2=fork())==-1 ); if (p1==0 ){ strcpy (inpipe,"Pipe Message Test" ); write(fd[1 ],inpipe,50 ); exit (0 ); } if (p2==0 ){ read(fd[0 ],outpipe,50 ); printf ("%s\n" ,outpipe); exit (0 ); } if (p2!=0 and p1!=0 ){ wait(0 ); exit (0 ); } }
2.2.信号
2.2.1.软中断实验
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include <stdio.h> #include <stdlib.h> #include <signal.h> int k;void int_func (int sig) { k=0 ; printf ("int_func\n" ); } void main () { signal(SIGINT,int_func); k=1 ; while (k == 1 ){ printf ("Hello!\n" ); } printf ("OK!\n" ); exit (0 ); }
改造:要求按3次Ctrl+C后才结束
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include <stdio.h> #include <stdlib.h> #include <signal.h> int k;void int_func (int sig) { k=k-1 ; printf ("int_func\n" ); } void main () { signal(SIGINT,int_func); k=3 ; while (k>0 ){ printf ("Hello!\n" ); } printf ("OK!\n" ); exit (0 ); }
改造:将signal()语句和函数删除后重新编译看结果有何变化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include <stdio.h> #include <stdlib.h> #include <signal.h> int k;void int_func (int sig) { k=0 ; printf ("int_func\n" ); } void main () { k=1 ; while (k == 1 ){ printf ("Hello!\n" ); } printf ("OK!\n" ); exit (0 ); }
2.2.2.使用软中断实现父子进程同步
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 #include <stdio.h> #include <stdlib.h> #include <signal.h> int k1;void int_fun1 () { k1=0 ; } main() { int k,p1; while ((p1=fork())==-1 ); if (p1>0 ) { for (k=1 ;k<4 ;k++) { printf ("How are you!\n" ); sleep(1 ); } kill(p1,12 ); wait(0 ); printf ("OK!\n" ); exit (0 ); } else { signal(12 ,int_fun1); k1=1 ; while (k1==1 ) { printf ("I am child\n" ); sleep(1 ); } printf ("Child exited!\n" ); exit (0 ); } }
改造:一定要子进程先执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 #include <stdio.h> #include <stdlib.h> #include <signal.h> int k1;void int_fun1 () { k1=0 ; } main() { int k,p1; while ((p1=fork())==-1 ); if (p1>0 ) { for (k=1 ;k<4 ;k++) { sleep(1 ); printf ("How are you!\n" ); } kill(p1,12 ); wait(0 ); printf ("OK!\n" ); exit (0 ); } else { signal(12 ,int_fun1); k1=1 ; while (k1==1 ) { printf ("I am child\n" ); sleep(1 ); } printf ("Child exited!\n" ); exit (0 ); } }
把sleep(1)提到 printf 前面即可
2.3.消息传递
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 #Sndfile.c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <linux/msg.h> #define MAXMSG 512 struct my_msg { long int my_msg_type; int i; char some_text[MAXMSG]; }msg; main(){ int msgid; char buffer[BUFSIZ]; msgid=msgget(12 ,0666 |IPC_CREAT); while (1 ){ puts ("Enter some text:" ); fgets(buffer,BUFSIZ,stdin ); msg.i++; printf ("i=%d\n" ,msg.i); msg.my_msg_type=3 ; strcpy (msg.some_text,buffer); msgsnd(msgid,&msg,MAXMSG,0 ); if (strncmp (msg.some_text,"end" ,3 )==0 ) break ; } exit (0 ); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 Rcvfile.c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <linux/msg.h> #define MAXMSG 512 struct my_msg { long int my_msg_type; int i; char some_text[MAXMSG]; }msg; main(){ int msgid; msg.my_msg_type=3 ; msgid=msgget(12 ,0666 |IPC_CREAT); while (1 ){ msgrcv(msgid,&msg,BUFSIZ,msg.my_msg_type,0 ); printf ("You wrote:%s and i=%d\n" ,msg.some_text,msg.i); if (strncmp (msg.some_text,"end" ,3 )==0 ) break ; } msgctl(msgid,IPC_RMID,0 ); exit (0 ); }
2.4.共享内存
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/shm.h> main(){ int shmid; char *viraddr; char buffer[BUFSIZ]; shmid=shmget(1234 ,BUFSIZ,0666 |IPC_CREAT); viraddr=(char *)shmat(shmid,0 ,0 ); while (1 ){ puts ("Enter some text:" ); fgets(buffer,BUFSIZ,stdin ); strcat (viraddr,buffer); if (strncmp (buffer,"end" ,3 )==0 ) break ; } shmdt(viraddr); exit (0 ); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/shm.h> main(){ int shmid; char *viraddr; shmid=shmget(1234 ,BUFSIZ,0666 |IPC_CREAT); viraddr=(char *)shmat(shmid,0 ,0 ); printf ("Your message is :%s" ,viraddr); shmdt(viraddr); shmctl(shmid,IPC_RMID,0 ); exit (0 ); }
3.代码实践2
作业最复杂的一部分,先把代码放了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/shm.h> #define BUFSIZE 4096 char ask = 'D' ;char ans = 'R' ;#include <sys/msg.h> #define MAXMSG 512 struct my_msg { long int my_msg_type; char signalB; char signalA; int headM1; int sizeM1; }msg; int main () { int shmid,msgid; char *viraddrA; char *viraddrB; char bufferM1[BUFSIZE]; char bufferM2[BUFSIZE]; int cycle = 10 ; int i,count; msg.sizeM1 = 0 ; msg.headM1 = 0 ; msg.signalA = '\0' ; msg.signalB = '\0' ; msg.my_msg_type=5 ; printf ("Communication begins\n" ); while (cycle--){ shmid=shmget(5067 ,BUFSIZE,0666 |IPC_CREAT); viraddrA=(char *)shmat(shmid,0 ,0 ); unsigned int ra = rand(); ra = 1 + ra % 10 ; if (ra + msg.sizeM1 > 4096 ){ ra = 4096 - msg.sizeM1; } for (i=0 ;i<ra;i++){ count = (msg.headM1 + msg.sizeM1 + i)%4096 ; bufferM1[count] = ask; } msg.sizeM1 += ra; strcat (viraddrA,bufferM1); msgid=msgget(1 ,0666 |IPC_CREAT); msg.signalA = '?' ; msgsnd(msgid,&msg,sizeof (msg),0 ); printf ("M1 is ready.\n" ); sleep(10 ); msgrcv(msgid,&msg,sizeof (msg),msg.my_msg_type,0 ); if (msg.signalB == '!' ){ shmid=shmget(59474 ,BUFSIZE,0666 |IPC_CREAT); viraddrB=(char *)shmat(shmid,0 ,0 ); msg.signalB = '\0' ; for (i = 0 ;i<4096 ;i++){ bufferM2[i] = '\0' ; } printf ("M2 was consumed\n" ); msgsnd(msgid,&msg,sizeof (msg),0 ); strcat (viraddrB,bufferM2); shmdt(viraddrB); } else { printf ("Waiting B.\n" ); sleep(5 ); } shmdt(viraddrA); } printf ("Communication over." ); exit (0 ); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/shm.h> #include <sys/msg.h> #define BUFSIZE 4096 #define MAXMSG 512 struct my_msg { long int my_msg_type; char signalB; char signalA; int headM1; int sizeM1; }msg; char ask = 'D' ;char ans = 'R' ;int main () { int shmid,msgid; char *viraddrA; char *viraddrB; char bufferM1[BUFSIZE]; char bufferM2[BUFSIZE]; int cycle = 12 ; int headM2 = 0 ; int sizeM2 = 0 ; int i,count; msg.sizeM1 = 0 ; msg.headM1 = 0 ; msg.signalA = '\0' ; msg.signalB = '\0' ; msg.my_msg_type=5 ; printf ("Communication begins\n" ); while (cycle--){ shmid=shmget(59474 ,BUFSIZE,0666 |IPC_CREAT); viraddrB=(char *)shmat(shmid,0 ,0 ); unsigned int rb = rand(); rb = 1 + rb % 10 ; msgid=msgget(1 ,0666 |IPC_CREAT); msgrcv(msgid,&msg,sizeof (msg),msg.my_msg_type,0 ); if (msg.signalA == '?' ){ msg.signalB = '!' ; shmid=shmget(5067 ,BUFSIZE,0666 |IPC_CREAT); viraddrA=(char *)shmat(shmid,0 ,0 ); if (rb > msg.sizeM1){ rb = msg.sizeM1; } if ( rb + sizeM2 > 4096 ){ rb = 4096 - sizeM2; } for (i = 0 ;i<4096 ;i++){ bufferM1[i] = *(viraddrA+i); } for (i = 0 ;i<msg.sizeM1;i++){ count = sizeM2 + headM2 + i; bufferM2[count] = ans; count = msg.sizeM1 + msg.headM1 - i; bufferM1[count] = '\0' ; } printf ("M2 is ready.\n" ); sizeM2 += rb; msg.sizeM1 -= rb; if (msg.sizeM1 == 0 ){ printf ("M1 is empty.\n" ); msg.signalA = '\0' ; } msgsnd(msgid,&msg,sizeof (msg),0 ); strcat (viraddrB,bufferM2); strcat (viraddrA,bufferM1); shmdt(viraddrA); } else { printf ("Waiting A.\n" ); } sleep(10 ); shmdt(viraddrB); } printf ("Communication over." ); exit (0 ); }
基本的编码思想是开辟两个数组分别存储M1和M2,然后利用共享内存通信实现M1和M2的跨进程调用。调用的时机点切入则由消息缓冲通信实现。开发中发现把数组实现成环形作用不大(但我还是勉强实现了,方法是把起始下标和容量存起来),因为填入M1或M2的所有数据都是一样的,生产的时候下标递增而消费的时候下标递减即可(可能有必要实现先消费旧信息这个功能,只需要把M2的起始下标和容量也存起来即可,但我的代码没有呈现)。有一个问题是,A收到B的应答信息后的具体行动。我的做法是将M2中所有的应答信息消费完,而因为如此msg不用传sizeM2,因为A会一次性把整个M2消费完,直接遍历就完事了;此外就是A没收到B的应答信息时应不应该继续生产data。为了图省事我没有额外做一个判断,所以会继续生产直到buffer满。
需要注意的是mod运算对于实现循环非常必要,无论怎样实现都要注意这一点。
上面的代码写完之后我就没有review了,所以可能有很多不足之处(懒)