linux进程共享内存通信,linux进程间通信之共享内存

共享存储允许两个或多个进程共享同一给定的存储区。因为数据不需要在客户进程和服务器进程之间复制,所以这是最快的一种IPC。使用共享存储时要注意多个进程之间对同一给定存储区的同步访问.

内核为每个共享存储段设置了一个shmid_ds结构

struct shmid_ds{

struct ipc_perm shm_perm; /*操作权限*/

int shm_segsz; /*段的大小(以字节为单位)*/

time_t shm_atime; /*最后一个进程附加到该段的时间*/

time_t shm_dtime; /*最后一个进程离开该段的时间*/

time_t shm_ctime; /*最后一个进程修改该段的时间*/

unsigned short shm_cpid; /*创建该段进程的pid*/

unsigned short shm_lpid; /*在该段上操作的最后1个进程的pid*/

short shm_nattch; /*当前附加到该段的进程的个数*/

unsigned short shm_npages; /*段的大小(以页为单位)*/

unsigned long *shm_pages; /*指向frames->SHMMAX的指针数组*/

struct vm_area_struct *attaches; /*对共享段的描述*/

};

在IPC中,我们经常用用key_t的值来创建或者打开信号量,共享内存和消息队列。通常情况下,该id值通过ftok函数得到

#include

#include

key_t ftok(const char *pathname, int proj_id);

返回值:成功返回key_t值,失败返回-1

1)pathname一定要在系统中存在并且进程能够访问的,一般使用当前目录,如:

key_t key;

key = ftok(".", 1); 这样就是将fname设为当前目录。

2)proj_id是一个1-255之间的一个整数值,典型的值是一个ASCII值。

调用函数shmget获得一个共享存储表示符

#include

#include

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

返回值:成功返回共享存储ID,出错返回-1参数size是共享存储段的长度.通常将其向上取为系统页长的整数倍。如果创建一个新段必须指定size,引用现存的段则size指定为0

注意:若指定的size值并非系统页长的整数倍,那么最后一页的余下部分是不可以使用的。

shmflg参数:

0:取共享内存标识符,若不存在则函数会报错

IPC_CREAT:当shmflg&IPC_CREAT为真时,如果内核中不存在键值与key相等的共享内存,则新建一个共享内存;如果存在这样的共享内存,返回此共享内存的标识符

IPC_CREAT|IPC_EXCL:如果内核中不存在键值 与key相等的共享内存,则新建一个共享内存;如果存在这样的共享内存则报错

用户读    0400

用户写    0200

组读        0040

组写        0020

其他读    0004

其他写    0002

一旦创建了一个共享存储段,进程就可调用shmat将其链接到它的地址空间,shmdt取消链接

#include

#include

void *shmat(int shmid, const void *shmaddr, int shmflg);

返回值:成功返回共享内存地址,出错返回-1

int shmdt(const void *shmaddr);

返回值:成功返回0,出错返回-1若addr为0,则由内核选择第一个可用地址

若addr非0,并且没有指定SHM_RND,则此段链接到addr所指定的地址上

shmflg参数若指定SHM_RDONLY位,则以只读方式链接,否则以读写方式链接

shmctl函数对共享存储段执行多种操作

#include

#include

int shmctl(int shmid, int cmd, struct shmid_ds *buf);

返回值:成功返回0,出错返回-1cmd参数指定下列5种命令中的一种,使其在shmid指定的段上执行

IPC_STAT 取此段的shmid_ds结构,并放在buf指向的结构中

IPC_SET 按buf指向的结构中的值设置与此段相关结构中下列三个段:shm_perm.uid shm_perm.gid shm_perm.mode

IPC_RMID从系统中删除共享存储段

Linux和Solaris提供了另外两种命令,此命令只能由超级用户执行

SHM_LOCK 将共享存储段锁在内存中。

SHM_UNLOCK 解锁共享存储段。

多进程通信简单示例:

进程A

#include

#include

#include

#include

#include

#include

#include

key_t key;

int shmid;

int *p;

int i=0;

void deal(int s)

{

if(s==SIGINT)

{

//4.卸载共享内存shmdt

shmdt(p);

//5.删除共享内存shctl

shmctl(shmid,IPC_RMID,0);

exit(0);

}

}

main()

{

signal(SIGINT,deal);

//1.创建共享内存shmget

key=ftok(".",255);

if(key==-1) printf("ftok error:%m\n"),exit(-1);

shmid=shmget(key,4,IPC_CREAT|IPC_EXCL|0666);

if(shmid==-1) printf("get error:%m\n"),exit(-1);

//2.挂载共享内存shmat

p=shmat(shmid,0,0);

if(p==(int*)-1) printf("at error:%m\n"),exit(-1);

//3.访问共享内存

while(1)

{

*p=i;

sleep(1);

i++;

}

}

进程B

#include

#include

#include

#include

#include

#include

#include

key_t key;

int shmid;

int *p;

void deal(int s)

{

if(s==2)

{

//4.卸载共享内存shmdt

shmdt(p);

exit(0);

}

}

main()

{

signal(SIGINT,deal);

//1.创建共享内存shmget

key=ftok(".",255);

if(key==-1) printf("ftok error:%m\n"),exit(-1);

shmid=shmget(key,4,0);

if(shmid==-1) printf("get error:%m\n"),exit(-1);

//2.挂载共享内存shmat

p=shmat(shmid,0,0);

if(p==(int*)-1) printf("at error:%m\n"),exit(-1);

//3.访问共享内存

while(1)

{

sleep(1);

printf("%d\n",*p);

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值