linux详细入门教程(十七)------进程间通信(3)

一、共享内存

 

简介
共享内存允许两个或多个进程访问同一块存储区,是最快的IPC机制。
使用共享内存必须注意多个进程之间对同一内存段的同步存取。一般使用信号量进行互斥访问。

 

              使用一块共享内存的过程:

由一个进程分配;

需要访问这个共享内存段的每一个进程都将这个共享内存绑定到自己的地址空间中;

完成通信后,所有进程则将共享内存与自己的地址空间分离开来;

由一个进程释放该共享内存段。

Linux每个进程都维护一个从物理页面地址到虚拟页面地址之间的映射。

分配共享内存就是由内核分配一或多个新的内存页面。一个进程如需使用这个共享内存段,则必须建立进程本身的虚拟地址到共享内存页面地址之间的映射,该过程称为绑定。当对共享内存的使用结束之后,解除这个映射关系,该过程称为分离

 

内核为每个共享内存段设置了一个shmid_ds结构用以管理共享内存

 shmatt_t是一个至少比unsigned short更大的整数类型.

1、shmget函数 

 分配一个共享内存段.

 

key  用于标识一个共享内存的键,通常为一整数。

size  共享内存的字节数,常向上取整到PAGE_SIZE的整数倍。

shmflg  标志位,低9位用于指定访问权限。IPC_CREAT表示创建信号  量集,可按位或IPC_EXCL。

返回值  成功时,返回共享内存的标识符(一个非负整数)。出错时,  返回-1并设置errno。常见的错误值如下:

EACCES   无访问权限

EEXIST   在同时指定IPC_CREAT和IPC_EXCL时,具有指定键的信号量集  已存在.

EINVAL  size小于SHMMIN或大于SHMMAX,或key所指共享内存已存在,  但size比已存在的共享内存更大.

ENOENT   键不存在.

 2、shmat函数

 将共享内存绑定到当前进程的内存空间.

 

shmid  由shmget返回的标识符.

shmaddr  绑定的地址(本进程地址空间的地址).

shmflg  标志位,常用的值为SHM_RND和SHM_RDONLY.

返回值  对于shmat,成功时返回共享内存的地址;出错时,返回  (void*)-1并设置errno。

说明

如果shmaddr指定为NULL,系统将选择一个合适的地址来绑定共享内存。这是推荐的做法。

如果shmaddr不为NULL,shmflg指定了SHM_RND,则实际绑定地址为shmaddr 向下舍入到最近的SHMLBA(=PAGE_SIZE)的倍数的位置。目前,Linux下SHMLBA等于PAGE_SIZE(内存页面大小)。

如果shmaddr不为NULL,shmflg未指定了SHM_RND,shmaddr必须为一页对齐(即页面大小的整数倍)的地址。

如果shmflg指定了SHM_RDONLY,则共享内存以只读的方式绑定到本进程的地址空间,否则为“读写”方式。

shmat成功时更改与共享内存关联的shmid_ds 结构,将其shm_atime成员 设置为当前时间,shm_lpid成员设置为当前进程的PID,shm_nattch成员的值则增1。

3、shmdt函数 

 将已绑定的共享内存与当前进程的内存空间相分离。

 

 

shmaddr  绑定的地址(本进程地址空间的地址)

返回值  成功时返回0,失败时返回-1并设置errno

说明

shmdt如果成功也会更改与共享内存关联的shmid_ds 结构,将其shm_dtime成员设置为当前时间,shm_lpid成员设置为当前进程的PID,shm_nattch成员的值则减1。

如果shm_nattch的值变成了0,且共享内存段标记为删除,则相应的共享内存段被删除。

用fork创建的子进程将继承已绑定的共享内存段。但在子进程中调用exec系列函数后,所有已绑定的共享内存段会与新进程分离。

当进程调用_exit函数退出的时候,所有已绑定的共享内存段也会自动从进程分离出去。

 4、shmctl函数

 可对共享内存进行多种类型的控制。

 

shmid  由shmget返回的标识符

cmd  要执行的动作

buf  用于设置(cmd为IPC_SET)或获取(cmd为IPC_STAT)  共享内存段的信息

返回值  成功时返回非负数,失败时返回-1并设置errno

 

说明

常用的cmd命令是IPC_RMID,用于删除一个共享内存段。

在进程中调用 exit 和 exec 会使进程分离共享内存段,但不会删除这个内存段。在结束使用每个共享内存段的时候都应当使用 shmctl的IPC_RMID命令进行释放。

 

 

 

 

 

 

二、消息队列 

简介
消息队列是消息的链接表,存放在内核中并由消息队列标识符标识。
使用消息队列可以从一个进程向另一个进程发送数据块。每个数据块有一个最大长度的限制MSGMAX,所有队列的全部数据块的总长度也有一个上限值MSGMNB。

              消息队列独立于发送和接收进程而存在。消息队列和队列中的内容保留在文件系统中。

               内核为每个消息队列设置了一个shmid_ds结构用以管理消息队列。

 

 1、msgget函数

 创建或获取一个消息队列.

 

key  用于标识一个消息队列的键,通常为一整数。

msgflg  标志位,低9位用于指定访问权限。IPC_CREAT表示创建信  号量集,可按位或IPC_EXCL。

返回值  成功时,返回消息队列的标识符(一个非负整数)。出错时,  返回-1并设置errno。常见的错误值如下:

EACCES   无访问权限.

EEXIST   在同时指定IPC_CREAT和IPC_EXCL时,具有指定键的消息队列  已存在.

ENOENT   键不存在.

说明

调用msgget函数时,参数msgflg指定IPC_CREAT而未指定IPC_EXCL,如果具有指定键的消息队列已存在,则只是忽略创建动作,而不会出错。

 2、msgsnd函数

 一条消息添加到消息队列中。

 

msqid  由msgget返回的消息队列标识符

msgp  指向要发送的消息的缓冲区的指针

 

msgsz  消息长度。这个长度不包括长整形成员变量的长度。

msgflg  标志。指定IPC_NOWAIT时,表示当队列满或达到系统限制  时,函数立即返回(返回值为-1 ),不发送消息。

返回值  成功时返回0;失败时返回-1,并设置errno变量。

说明

未指定IPC_NOWAIT时, 如果队列满或达到系统限制,函数返回-1,错误为EAGAIN。

 

 3、msgrcv函数

 从一个消息队列获取消息

 

msqid  由msgget返回的消息队列标识符

msgp  指向准备接收消息的缓冲区的指针

 

msgsz  消息长度。这个长度不包括长整形成员变量的长度。msgp所  指向的缓冲区应大于或等于此长度。

msgtyp  一个长整数,可能情况:

若值为0,获取队列中的第一个可用消息;

若值大于0,获取具有相同类型的第一个消息;

若小于0,获取消息类型小于或等于其绝对值的第一个消息。

msgflg  标志。指定IPC_NOWAIT时,表示当没有相应类型消息时,函数立即返回(返回值为-1 ),不接收消息,errno设置为:ENOMSG

返回值  成功时返回0;失败时返回-1,并设置errno变量。

 4、msgctl函数

 直接控制消息队列,可对消息队列做多种操作.

 

msqid  由msgget返回的消息队列标识符.

cmd  要采取的动作,常取以下值:

IPC_STAT      将内核所管理的消息队列的当前属性值复制到buf(msqid_ds结  构)中.

IPC_SET       如果进程有足够的权限,就把内核所管理的消息队列的当前属性  值设置为buf(msgqid_ds结构)各成员的值

IPC_RMID      删除消息队列.

 

buf  缓冲区,作用视cmd而定.

return value  成功时返回0;失败时返回-1,并设置errno变量。

说明

如果在进程正阻塞于msgsnd或msgrcv中等待时删除消息队列,则这两个函数将以失败返回。

 

 

 

 

 

 

 

 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

重生之我是泰勒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值