IPC 基本结构 简述
IPC通信包括:共享内存,消息队列,信号灯
共享内存 打开或创建一个共享内存对象,共享内核在内核是什么样子的? 一块缓存,变类似于用户空间的数组或malloc函数分配的空间一样。
查看IPC对象:ipcs -m【查看共享内存】| -q【队列】| -s【信号灯】 删除IPC对象:ipcrm -m | -q | -s id【IPC的ID】
共享内存可以通过memcpy写入,也可以通过键盘输入stdin
利用键盘输入读取共享内存 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 #include <stdio.h> #include <sys/types.h> #include <sys/shm.h> #include <signal.h> #include <sys/ipc.h> #include <unistd.h> #include <stdlib.h> int main () { int shmid; int key; char *p; key = ftok("./myfifo" ,'b' ); if (key < 0 ) { printf ("create key failure\n" ); return -1 ; } printf ("create key sucess key = %X\n" ,key); shmid = shmget(key,128 ,IPC_CREAT | 0777 ); if (shmid<0 ) { printf ("create share memory failure\n" ); return -2 ; } printf ("create share memory sucess shmid = %X\n" ,shmid); system("ipcs -m" ); p = (char *)shmat(shmid,NULL ,0 ); if (p==NULL ) { printf ("shmat func failure\n" ); return -3 ; } fgets(p,128 ,stdin ); printf ("share memory data: %s\n" ,p); return 0 ; }
**共享内存特点 **:
共享内存创建之后,一直存在于内核中,直到被删除或系统关闭:
共享内存和管道不一样,读取后,内容仍在其共享内存中。
1 2 3 4 5 6 7 8 9 10 printf ("share memory data: %s\n" ,p); printf ("second read :%s\n" ,p); shmdt(p); system("ipcs -m" ); memcpy (p,"abcd" ,4 ); return 0 ;
1 2 3 4 5 6 7 8 9 shmdt(p); shmctl(shmid,IPC_RMID,NULL ); printf ("have delete share memory\n" ); system("ipcs -m" ); return 0 ;
不同进程之间的通信
宏IPC_PRIVATE:只可以打开亲属之间的共享内存,不同进程之间的需要ftok来获取shmid。
服务端代码,进程通过kill发送SIGUSR1给客户端进程告知已写入share memory。同时接收SIGUSR2信号。
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 #include <stdio.h> #include <sys/types.h> #include <string.h> #include <sys/shm.h> #include <signal.h> #include <sys/ipc.h> #include <unistd.h> #include <stdlib.h> struct mybuf { int pid; char buf[124 ]; }; void myfun () { printf ("myfun\n" ); } int main () { int shmid; int key; struct mybuf *p ; int pid; key = ftok("./myfifo" ,'b' ); if (key < 0 ) { printf ("create key failure\n" ); return -1 ; } printf ("create key sucess key = %X\n" ,key); shmid = shmget(key,128 ,IPC_CREAT | 0777 ); if (shmid<0 ) { printf ("create share memory failure\n" ); return -2 ; } printf ("create share memory sucess shmid = %X\n" ,shmid); signal(SIGUSR2,myfun); p = (struct mybuf *)shmat(shmid,NULL ,0 ); if (p==NULL ) { printf ("shmat func failure\n" ); return -3 ; } p->pid = getpid(); pause(); pid = p->pid; while (1 ) { printf ("parent process start write share memory!\n" ); fgets(p->buf,128 ,stdin ); kill(pid,SIGUSR1); pause(); } shmdt(p); shmctl(shmid,IPC_RMID,NULL ); return 0 ; }
客户端代码,进程通过kill发送SIGUSR2给服务端进程告知已读取share memory。同时接收SIGUSR1信号,进行读取。
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 #include <stdio.h> #include <sys/types.h> #include <string.h> #include <sys/shm.h> #include <signal.h> #include <sys/ipc.h> #include <unistd.h> #include <stdlib.h> struct mybuf { int pid; char buf[124 ]; }; void myfun () { printf ("myfun\n" ); } int main () { int shmid; int key; struct mybuf *p ; int pid; key = ftok("./myfifo" ,'b' ); if (key < 0 ) { printf ("create key failure\n" ); return -1 ; } printf ("create key sucess key = %X\n" ,key); shmid = shmget(key,128 ,IPC_CREAT | 0777 ); if (shmid<0 ) { printf ("create share memory failure\n" ); return -2 ; } printf ("create share memory sucess shmid = %X\n" ,shmid); signal(SIGUSR1,myfun); p = (struct mybuf *)shmat(shmid,NULL ,0 ); if (p==NULL ) { printf ("shmat func failure\n" ); return -3 ; } pid = p->pid; p->pid = getpid(); kill(pid,SIGUSR2); while (1 ) { pause(); printf ("client has read: %s\n" ,p->buf); kill(pid,SIGUSR2); } shmdt(p); shmctl(shmid,IPC_RMID,NULL ); return 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 #include <stdio.h> #include <sys/types.h> #include <sys/msg.h> #include <unistd.h> #include <signal.h> #include <string.h> #include <stdlib.h> struct msgbuf { long type; char msg[124 ]; char next[4 ]; }; int main () { int msgid; int readret; int key; struct msgbuf sendbuf ,readbuf ; key = ftok("./myfifo" ,'a' ); if (key<0 ) { printf ("create key failure!\n" ); return -1 ; } msgid = msgget(key,IPC_CREAT|0777 ); if (msgid<0 ) { printf ("create msgid failure!\n" ); return -1 ; } system("ipcs -q" ); sendbuf.type = 100 ; while (1 ) { memset (sendbuf.msg,0 ,124 ); printf ("PLZ inout msg: " ); fgets(sendbuf.msg,124 ,stdin ); msgsnd(msgid,(void *)&sendbuf,strlen (sendbuf.msg),0 ); } msgctl(msgid,IPC_RMID,NULL ); system("ipcs -q" ); return 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 #include <stdio.h> #include <sys/types.h> #include <sys/msg.h> #include <unistd.h> #include <signal.h> #include <string.h> #include <stdlib.h> struct msgbuf { long type; char msg[124 ]; char next[4 ]; }; int main () { int msgid; int readret; int key; struct msgbuf sendbuf ,readbuf ; key = ftok("./myfifo" ,'a' ); if (key<0 ) { printf ("create key failure!\n" ); return -1 ; } msgid = msgget(key,IPC_CREAT|0777 ); if (msgid<0 ) { printf ("create msgid failure!\n" ); return -1 ; } system("ipcs -q" ); sendbuf.type = 100 ; while (1 ) { memset (readbuf.msg,0 ,124 ); msgrcv(msgid,(void *)&readbuf,124 ,100 ,0 ); printf ("recv msg : %s\n" ,readbuf.msg); } msgctl(msgid,IPC_RMID,NULL ); system("ipcs -q" ); return 0 ; }
信号灯 概念 信号灯 :信号灯集合(可以包含多个信号灯)PC对象是一个信号灯集(多个信号量)
利用信号灯进行通信
利用ftok创建key,然后构建信号灯。首先运行客户端,信号量初始化在客户端上,并进行V操作,所以信号量资源被释放,无法利用。下一步执行服务端,服务端先执行任务,然后发送P操作信息,由此分配资源给客户端。
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 #include <stdio.h> #include <unistd.h> #include <pthread.h> #include <stdlib.h> #include <sys/ipc.h> #include <sys/sem.h> union semun { int val; struct semid_ds *buf ; unsigned short *array ; struct seminfo *_buf ; }; int semid;union semun mysemun ;struct sembuf mysembuf ;int main () { int i; int key; key = ftok("./myfifo" ,'a' ); if (key<0 ) { printf ("create key failure!" ); return -1 ; } printf ("create key sucess! key=%d\n" ,key); semid = semget(key,3 ,IPC_CREAT|0777 ); if (semid<0 ) { printf ("create semid failure!" ); return -1 ; } printf ("create semid sucess! semid = %d\n" ,semid); system("ipcs -s" ); mysembuf.sem_num = 0 ; mysembuf.sem_flg = 0 ; for (i=0 ; i<10 ; i++) { usleep(100 ); printf ("this is main func i=%d\n" ,i); } mysembuf.sem_op =1 ; semop(semid,&mysembuf,1 ); while (1 ); return 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 #include <stdio.h> #include <unistd.h> #include <pthread.h> #include <stdlib.h> #include <sys/ipc.h> #include <sys/sem.h> union semun { int val; struct semid_ds *buf ; unsigned short *array ; struct seminfo *_buf ; }; int semid;union semun mysemun ;struct sembuf mysembuf ;int main () { int i; int key; key = ftok("./myfifo" ,'a' ); if (key<0 ) { printf ("create key failure!" ); return -1 ; } printf ("create key sucess\n" ); semid = semget(key,3 ,IPC_CREAT|0777 ); if (semid<0 ) { printf ("create semid failure!" ); return -1 ; } printf ("create semid sucess\n" ); system("ipcs -s" ); mysemun.val = 0 ; semctl(semid,0 ,SETVAL,mysemun); mysembuf.sem_num = 0 ; mysembuf.sem_flg = 0 ; mysembuf.sem_op=-1 ; semop(semid,&mysembuf,1 ); for (i=0 ; i<10 ; i++) { usleep(100 ); printf ("this is main func i=%d\n" ,i); } while (1 ); return 0 ; }