您的位置:首页 > 运维架构 > Linux

Linux进程通信 -- 共享内存实战

2016-01-27 16:24 537 查看

共享内存原理及实现

system V IPC机制下的共享内存本质是一段特殊的内存区域,进程间需要共享的数据被放在该共享内存区域中,所有需要访问该共享区域的进程都要把该共享区域映射到本进程的地址空间中去。

这样一个使用共享内存的进程可以将信息写入该空间,而另一个使用共享内存的进程又可以通过简单的内存读操作获取刚才写入的信息,使得两个不同进程之间进行了一次信息交换,从而实现进程间的通信。

共享内存允许一个或多个进程通过同时出现在它们的虚拟地址空间的内存进行通信,而这块虚拟内存的页面被每个共享进程的页表条目所引用,同时并不需要在所有进程的虚拟内存都有相同的地址。

进程对象对于共享内存的访问通过key(键)来控制,同时通过key进行访问权限的检查。

相关函数

shmget
函数


功能:用来创建共享内存

函数原型:

#include  <sys/shm.h>

int shmget(key_t key, size_t size, int shmflag);


参数

key
:创建的内存id

szie
:内存大小

shmflag
:权限标志,类似文件权限mode

返回值:成功返回非负整数key;失败返回-1

shmat
函数


功能:将共享内存连接到进程地址空间

函数原型:

void *shmat(int shm_id, const void *shm_addr, int shmflg);


参数

shm_id
:共享内存标识

shm_addr
:指定连接的地址(一般选择NULL,由内核自动选一个地址)

shmflg
:它的两个可能取值是SHM_RND和SHM_RONLY

返回值:成功返回一个指向共享内存的第一个字节的指针;失败返回-1

shmctl
函数


功能:控制及操作共享内存

函数原型:

int shmctl(int shm_id, int command, struct shmid_ds *buf);


参数

第一个参数
shm_id
shmget
返回的共享内存标识符。

第二个参数
command
是要采取的动作,它可以取三个值,具体请见终端
man shmctl


第三个参数
shmid_ds
至少包含如下成员:

struct shmid_ds
{
uid_t shm_perm.uid;
uid_t shm_perm.gid;
mode_t shm_perm.mode;
};


shmdt函数

功能:用于将共享内存段与进程空间分离。

int shmdt(const void *shmaddr);


参数

shmaddr
通常为
shmat
的成功返回值。

返回值:成功返回0,失败时返回-1.

注意,将共享内存分离并没删除它,只是使得该共享内存对当前进程不在可用。

相关命令

查看共享内存
ipcs -m


删除共享内存
ipcrm -m shmid


父子进程使用共享内存通信的实现

//1.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
key_t key = ftok(".",1);
int shmid = shmget(key, 1024, 0666 | IPC_CREAT);
if(shmid == -1)
{
perror("create sm error\n");
exit(1);
}

if(fork() > 0)                            //父进程操作
{
char *p = (char*)shmat(shmid, NULL, 0); //将共享内存连接到进程地址空间
memset(p, '\0', 1024); //将地址字符串数据置为空
strncpy(p, " hey guys how are you here", 1024);//写入数据
printf("parent_pid = %d send data: %s\n", getpid(),p);
sleep(2);
wait(NULL);                            //防止僵尸进程
if(shmctl(shmid, IPC_RMID,0) == -1)    //删除共享内存
{
perror("shmctl");
exit(-1);
}
exit(0);
}
else                              //子进程操作
{
sleep(5);       //给父进程写数据的时间
char *sp = (char*)shmat(shmid, NULL, 0);//将共享内存连接到进程地址空间
printf("son_pid = %d, shmid = %d  read data: %s\n", getpid(), shmid, sp);
exit(0);
}
}


执行操作

yu@ubuntu:~/0126/gxnc$ gcc -o run 1.c
yu@ubuntu:~/0126/gxnc$ ./run
parent_pid = 7428 send data:  hey guys how are you here
son_pid = 7429, shmid = 2752523  read data:  hey guys how are you here


非亲缘关系两进程通信–使用共享内存案例

1、write.c

//1、write.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>

int main()
{
key_t key = ftok(".", 1);//以当前目录文件创建key
if(key == -1)
{
perror("ftok");
exit(-1);
}

int shmid = shmget(key, 4096, 0666 | IPC_CREAT);//创建共享内存,大小4096,权限0666
if(shmid == -1)
{
perror("shmget");
exit(-1);
}
char *pMap = (char*)shmat(shmid, NULL, 0); //将共享内存连接到进程地址空间
memset(pMap, '\0', 4096);//置为空
memcpy(pMap, "nihaoma guys", 4096);//写数据
if(shmdt(pMap) == -1)
{
perror("shmdt");
exit(-1);
}
}


执行操作

yu@ubuntu:~/0126/gxnc/feiqin$ gcc -o write write.c
yu@ubuntu:~/0126/gxnc/feiqin$ ./write


此时查看共享内存发现有一条刚创建的共享内存记录:

yu@ubuntu:~/0126/gxnc/feiqin$ ipcs -m
------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status
0x010197bd 2818059    yu         666        4096       0


2、read.c

//2、read.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>

int main()
{
key_t key = ftok(".", 1);
//获取当前目录的key
if(key == -1)
{
perror("ftok");
exit(-1);
}
int shmid = shmget(key, 4096, IPC_CREAT);
//shmid赋值
if(shmid == -1)
{
perror("shmid == -1");
exit(-1);
}
char *p = (char*)shmat(shmid, NULL, 0);//将共享内存连接到进程地址空间
printf("receive the data: %s\n", p);

if((ret = shmctl(shmid, IPC_RMID, 0)) == -1)//删除共享内存
{
perror("shmctl");
exit(-1);
}
}


执行操作

yu@ubuntu:~/0126/gxnc/feiqin$ ./read
receive the data: nihaoma guys
yu@ubuntu:~/0126/gxnc/feiqin$ ipcs -m
------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status


此时已经删除创建的共享内存,清理完毕
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: