如何共享服务和用户进程间共享内存之间的内存

linux嵌入式方向(495)
作者:华清远见
一、进程间通信的方式
在程序的运行中,我们必定会有关于进程与进程间通信的问题。而我们的先辈早已为我们准备了关于解决这些问题的方法。这些方法主要有几种:无名管道,有名管道,信号,消息队列,共享内存以及信号灯(信号量)等几种方法。其中共享内存又是其中的翘楚。这篇文章讲解一下共享内存。
二、共享内存介绍
1、共享内存是一种最为高效的进程间通信方式,进程可以直接读写内存,而不需要任何数据的拷贝。
2、为了在多个进程间交换信息,内核专门留出了一块内存区,可以由需要访问的进程将其映射到自己的私有地址空间。进程就可以直接读写这一块内存而不需要进行数据的拷贝,从而大大提高效率。
3、由于多个进程共享一段内存,因此也需要依靠某种同步机制(信号灯)。
三、共享内存的同步
共享内存为在多个进程之间共享和传递数据提供了一种有效的方式。但是它并未提供同步机制,所以我们通常需要用其他的机制来同步对共享内存的访问。我们通常是用共享内存来提供对大块内存区域的有效访问,同时通过传递小消息来同步对该内存的访问。在第一个进程结束对共享内存的写操作之前,并无自动的机制可以阻止第二个进程开始对它进行读取。对共享内存访问的同步控制必须由程序员来负责。
四、共享内存的实现
共享内存的使用包括如下步骤:
1、创建/打开共享内存
2、映射共享内存,即把指定的共享内存映射到进程的地址空间用 于访问。
3、撤销共享内存的映射。
4、删除共享内存对象
五、共享内存使用的函数
int shmget(key_t key, size_t size, int shmflg);
void *shmat(int shm_id, const void *shm_addr, int shmflg);
int shmdt(const void *shm_addr);
int shmctl(int shm_id, int cmd, struct shmid_ds *buf);
1. shmget函数
int shmget(key_t key, size_t size, int shmflg);
该函数用来创建共享内存:
参数:key : 和信号量一样,程序需要提供一个参数key,它有效地为共享内存段命名。有一个特殊的键值IPC_PRIVATE,它用于创建一个只属于创建进程的共享内存,通常不会用到。
size: 以字节为单位指定需要共享的内存容量。
shmflag: 包含9个比特的权限标志,它们的作用与创建文件时使用的mode标志是一样由IPC_CREAT定义的一个特殊比特必须和权限标志按位或才能创建一个新的共享内存段。
NOTE:权限标志对共享内存非常有用,因为它允许一个进程创建的共享内存可以被共享内存的创建者所拥有的进程写入,同时其它用户创建的进程只能读取共享内存。我们可以利用这个功能来提供一种有效的对数据进行只读访问的方法,通过将数据放共享内存并设置它的权限,就可以避免数据被其他用户修改。
返回值:创建成功,则返回一个非负整数,即共享内存标识;如果失败,则返回-1。
2. shmat函数
第一次创建共享内存段时,它不能被任何进程访问。
要想启动对该内存的访问,
必须将其连接到一个进程的地址空间。
这个工作由shmat函数完成:
void *shmat(int shm_id, const void *shm_addr, int shmflg);
参数:shm_id : 由shmget返回的共享内存标识。shm_add: 指定共享内存连接到当前进程中的地址位置。它通常是一个空指针,表示让系统来选择共享内存出现的地址。
shmflg : 是一组标志。它的两个可能取值是:
SHM_RND, 和shm_add联合使用,用来控制共享内存连接的地址。
SHM_RDONLY, 它使连接的内存只读。
返回值:如果调用成功, 返回一个指向共享内存第一个字节的指针;
如果失败,返回-1。
共享内存的读写权限由它的属主(共享内存的创建者),它的访问权限和当前进程的属主决定。共享内存的访问权限类似于文件的访问权限。
将共享内存从当前进程中分离。
int shmdt(const void *shm_addr);
shm_addr: shmat返回的地址指针。
成功时,返回0,
失败时,返回-1.
NOTE:共享内存分离并未删除它,只是使得该共享内存对当前进程不再可用。
注意:当一个进程不再需要共享内存段时,它将调用shmdt()系统调用取消这个段,但是,这并不是从内核真正地删除这个段,而是把相关shmid_ds结构的shm_nattch域的值减1,当这个值为0时,内核才从物理上删除这个共享段。(每有一个进程映射到这段共享内存,这个值就会加1,每次调用shmctl删除,仅仅只是删掉这个标记)
用完共享存储段后,将进程和该共享存储段脱离。这并不是从系统中删除其标识符以及其数据结构,直到某个进程(一般是创建者server)调用shmctl(IPC_RMID)特地删除它。
共享内存的控制函数
int shmctl(int shm_id, int cmd, struct shmid_ds *buf);
shmid_ds结构至少包含以下成员:
struct shmid_ds {
uid_t shm_perm.
uid_t shm_perm.
mode_t shm_perm.
shm_id : 是shmget返回的共享内存标识符。
command: 是要采取的动作,
它可以取3个值:
IPC_STAT 把shmid_ds结构中的数据设置为共享内存的当前关联值。
IPC_SET 如果进程有足够的权限,就把共享内存的当前关联值设置为shmid_ds结构中给出的值。
IPC_RMID 删除共享内存段。
buf : 是一个指针,包含共享内存模式和访问权限的结构。
返回值:
成功时,返回0,
失败时,返回-1。
六、代码示例
说了这么多,又到了实战的时候了。下面我们就用代码来进一步了解。
#define BUFF_SIZE 1024
typedef struct {
sem_ /* sem for read */
sem_ /* sem for write */
char buf[BUFF_SIZE];
int do_read (SHM *pSHM);
int do_write(SHM *pSHM);
int main(int argc, char *argv[])
int shmid = -1;
int pid = -1;
SHM *pSHM;
int retval = 0;
/* create share memory
* IPC_PRIVATE for communication betweeen parent-child processes
* IPC_CREAT to indicate a new creation of IPC object
if ((shmid = shmget(IPC_PRIVATE, sizeof(SHM), 0666)) & 0) {
perror(&shmget error&);
return -1;
printf(&pid[%d] create new shmid = %d\n&, getpid(), shmid);
/* attach share memory */
if ((pSHM = (SHM *)shmat(shmid, NULL, 0)) == (void *)-1) {
perror(&shmat error&);
retval = -1;
goto _exit_
printf(&parent: shmaddr = %p\n&, pSHM);
/* set 3rd param of sem_init - pshared - as nonzero,
* then the semaphore is shared between processes
if (sem_init(&(pSHM-&rsem), 1, 0) & 0) { /* read sem is init as busy */
perror(&sem_init read error&);
retval = -1;
goto _exit_
if (sem_init(&(pSHM-&wsem), 1, 1) & 0) { /* write sem is init as free */
perror(&sem_init write error&);
retval = -1;
goto _exit_
if ((pid = fork()) & 0) {
perror(&fork error&);
retval = -1;
goto _exit_
}else if (pid == 0) { /* child */
/* After a fork the child inherits the attached
* shared memory segments.
retval = do_read(pSHM);
}else{ /* parent */
usleep(5000); /* just to make output looks better */
retval = do_write(pSHM);
/* detach the share memory */
if (shmdt(pSHM) & 0) {
perror(&shmdt error&);
retval = -1;
goto _exit_
/* wait child process */
wait(NULL);
_exit_point:
if (pid != 0) { /* child will not handle this */
if (shmid & 0) {
/* IPC_RMID just mark the share memory presented by
* the shmid should be deleted, but the deletion
* happens only when no proces is attached
if (shmctl(shmid, IPC_RMID, NULL) & 0) {
perror(&shmctl error&);
int do_write(SHM *pSHM)
while (1) {
/* try to lock for write */
if (sem_wait(&(pSHM-&wsem)) & 0) {
perror(&sem_wait error&);
printf(&&&);
/* access the share memory and write data which are got
* from stdin
fgets(pSHM-&buf, BUFF_SIZE, stdin);
/* eat the LF and complete the string */
pSHM-&buf[strlen(pSHM-&buf) - 1] = '\0';
/* allow read */
if (sem_post(&(pSHM-&rsem)) & 0) {
perror(&sem_post error&);
if (strncmp(pSHM-&buf, &quit&, 4) == 0) {
usleep(500);
int do_read(SHM *pSHM)
while(1) {
/* try to lock for read */
if (sem_wait(&(pSHM-&rsem)) & 0) {
perror(&sem_wait error&);
/* read the share memory buffer and print the content out */
printf(&read buf: %s\n&, pSHM-&buf);
/* test the buf inside read lock */
if (strncmp(pSHM-&buf, &quit&, 4) == 0) {
/* detach the share memory */
if(shmdt(pSHM) & 0) {
perror(&shmdt error&);
return -1;
/* allow write */
if (sem_post(&(pSHM-&wsem)) & 0) {
perror(&sem_post error&);
大家可以看到,在这个程序中加入了信号灯的代码。主要是因为两个进程在调用同一个内存空间所以需要加入信号灯以达到同步或互斥的目的。
七、共享内存的优缺点
1、优点:我们可以看到使用共享内存进行进程间的通信真的是非常方便,而且函数的接口也简单,数据的共享还使进程间的数据不用传送,而是直接访问内存,也加快了程序的效率。同时,它也不像匿名管道那样要求通信的进程有一定的父子关系。
2、缺点:共享内存没有提供同步的机制,这使得我们在使用共享内存进行进程间通信时,往往要借助其他的手段来进行进程间的同步工作。
文章选自华清远见嵌入式培训
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:917592次
积分:17788
积分:17788
排名:第431名
原创:841篇
评论:210条
(1)(33)(26)(18)(24)(23)(12)(13)(2)(1)(2)(1)(1)(7)(5)(3)(1)(2)(1)(2)(3)(1)(5)(2)(13)(4)(3)(4)(2)(3)(1)(2)(1)(6)(4)(5)(3)(4)(3)(3)(2)(4)(2)(4)(4)(4)(5)(3)(6)(4)(5)(5)(12)(10)(6)(6)(13)(2)(2)(9)(13)(3)(12)(20)(16)(10)(8)(15)(15)(13)(15)(17)(18)(12)(14)(20)(27)(6)(19)(23)(18)(22)(35)(30)(23)(34)(35)C语言中,两个程序间如何实现内存共享? - ITeye问答
C语言中,两个程序间如何实现内存共享?
情况是这样的,在机器上有两个独立的C语言程序,现在现个程序需要内存数据共享,如果实现,要求:不用使用数据库,不用Socket。由于我是JAVA程序员,对C不太熟悉,大家有什么办法,提点建议吧,谢谢!
问题补充:共享变量、数据值等,不用文件,要是用文件,不如使用数据库了。我就是为了提高性能效率。xiangjie88 写道你要共享啥,一般的数据用xml
问题补充:如何实现呀,能否给一个例子,谢谢亲兄弟!xiangjie88 写道可以试试消息队列
可以试试消息队列
不知道你说的2个独立的程序是啥意思,如果是2个独立的代码,一个集成另一个可以用动态库,2个已经跑起来的程序就不清楚了
你要共享啥,一般的数据用xml
已解决问题
未解决问题5011人阅读
本文转自:http://blog.csdn.net/fengrx/article/details/4069088
忘记是从哪里整理的一个类了,但非常好用,可以将其放在自己的项目中实现不同进程间数据的通信。
实现文件:
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:161254次
积分:1929
积分:1929
排名:第18028名
原创:33篇
转载:73篇
(2)(1)(1)(1)(1)(1)(2)(1)(1)(4)(2)(2)(2)(12)(1)(4)(9)(1)(2)(3)(7)(2)(3)(12)(5)(4)(1)(1)(1)(1)(6)(5)(5)}

我要回帖

更多关于 进程间共享内存 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信