(1)共享内存是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间的数据传递不再涉及内核,即进程不再通过执行进入内核的系统调用来传递彼此的数据。
(2)共享内存的生命周期随内核。
(3)注意:共享内存未提供任何保护资源,即共享内存自身没有同步与互斥机制,但它是临界资源,所以我们需要利用其它机制来保证数据的正确性,Linux下就可以用信号量达到同步的目的。
(4)linux共享内存有两种方式(本文主要介绍shmget方式):
1)mmap方式,适用于父子进程之间,创建的内存非常大时;
2)shmget方式,适用于同一台电脑上不同进程之间,创建的内存相对较小。
(5)进程间利用共享内存实现消息队列的基本原理如下图
创建或者获取一个已经存在的信号量;
如果为全新创建,也就是不知道是否有人创建过,则IPC_CREATE|IPC_EXCEL,就是如果没
key:两个进程使用相同的key值,就可以使用同一个信号量;
nsems:创建几个信号量;
semflg:标志位;如果为创建:IPC_CREAT;
成功返回一个非负整数即该信号集的标识码;失败返回-1
对信号量进行改变,做P操作或者V操作;
semid:信号量的id号,也就是刚才semget的返回值;说明对哪个信号量进行操作;
sops:结构体指针,指向sembuf的结构体指针,sembuf结构体有三个成员变量:sem_num表
示信号量的编号 ( 即指定信号量集中的信号量下标 );nsops:表示是p还是v操作;1为v操作 (加1),-1为p操作(减1);sem_flg为标志位;
成功返回0;失败返回-1
unsigned short sem_num; /* semaphore number */第几个信号量
short sem_op; /* semaphore operation */p(-1)操作还是v操作(+1)
short sem_flg; /* operation flags */标志位
**注意**:联合体semun,这个联合体需要自己定义;
控制信号量集 对信号量进行控制:初始化/删除信号量
semid:信号量id; 由semget函数返回的信号量集标识码
semnum:信号量编号; 信号量集中信号量的序号
cmd:命令:SETVAL:初始化信号量; IPC_RMID:删除信号量; 将要采取的动作(有三个可取值)
成功返回0,失败返回-1
- #include
- #include
- #include
- #include
- #include
-
- union semun
- {
- int val;
- };
-
- void sem_init();
- void sem_p(int index);
- void sem_v(int index);
- void sem_destroy();
-
- #include "sem.h"
- #define SEM_NUM 2
- static int semid = -1;
- void sem_init()
- {
- semid = semget((key_t)1234,SEM_NUM,IPC_CREAT|IPC_EXCL|0600);//全新创建
- if (semid == -1 )
- {
- semid = semget((key_t)1234,SEM_NUM,0600);
- if ( semid == -1)
- {
- printf("semget err\n");
- return;
- }
- }
- else
- {
- int arr[SEM_NUM] = {1,0};
- for( int i = 0; i < SEM_NUM; i++ )
- {
- union semun a;
- a.val = arr[i];
- if ( semctl(semid,i,SETVAL,a) == -1 )//全新创建成功,就初始化
- {
- printf("semctl err\n");
- }
- }
- }
- }
- void sem_p(int index)
- {
- if ( index < 0 || index >= SEM_NUM )
- {
- return;
- }
- struct sembuf buf;
- buf.sem_num = index;
- buf.sem_op = -1;//p
- buf.sem_flg = SEM_UNDO;
- if ( semop(semid,&buf,1) == -1 )
- {
- printf("sem p err\n");
- }
- }
- void sem_v(int index)
- {
- if ( index < 0 || index >= SEM_NUM )
- {
- return;
- }
- struct sembuf buf;
- buf.sem_num = index;
- buf.sem_op = 1;//v
- buf.sem_flg = SEM_UNDO;
- if ( semop(semid,&buf,1) == -1 )
- {
- printf("sem v err\n");
- }
- }
- void sem_destroy()
- {
- if ( semctl(semid,0,IPC_RMID) == -1 )
- {
- printf("semctl del err\n");
- }
- }
- #include
- #include
- #include
- #include
- #include
- #include "sem.h"
- int main()
- {
- int shmid = shmget((key_t)1234,256,0600|IPC_CREAT);//创建/获取共享内存
- if ( shmid == -1 )
- {
- printf("shmget err\n");
- exit(0);
- }
-
- char* s = (char*)shmat(shmid,NULL,0);
- if ( s == (char*)-1 )
- {
- printf("shmat err\n");
- exit(0);
- }
-
- sem_init();//2 1,0
- while( 1 )
- {
- printf("input\n");
- char buff[128] = {0};
- fgets(buff,128,stdin);
- sem_p(0);
- strcpy(s,buff);
- sem_v(1);
- if ( strncmp(buff,"end",3) == 0 )
- {
- break;
- }
- }
-
- shmdt(s);
- exit(0);
- }
- #include
- #include
- #include
- #include
- #include
- #include "sem.h"
- int main()
- {
- int shmid = shmget((key_t)1234,256,0600|IPC_CREAT);//创建/获取共享内存
- if ( shmid == -1 )
- {
- printf("shmget err\n");
- exit(0);
- }
-
- char* s = (char*)shmat(shmid,NULL,0);
- if ( s == (char*)-1 )
- {
- printf("shmat err\n");
- exit(0);
- }
-
- sem_init();//2 1,0
- while( 1 )
- {
- printf("input\n");
- char buff[128] = {0};
- fgets(buff,128,stdin);
- sem_p(0);
- strcpy(s,buff);
- sem_v(1);
- if ( strncmp(buff,"end",3) == 0 )
- {
- break;
- }
- }
-
- shmdt(s);
- exit(0);
- }
只运行b.c,会阻塞