(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;//pbuf.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;//vbuf.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,0while( 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,0while( 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,会阻塞