APUE编程:126---进程间通信(XSI IPC总体简介:消息队列、信号量、共享存储)

一、3种XSI  IPC

  • 有3种称作XSI IPC的IPC:消息队列、信号量、共享存储器
  • 它们之间有很多相似之处,本文章先介绍它们相类似的特征,后面3篇文章介绍这些IPC各自的特殊功能

二、IPC标识符和键

标识符:

  • 概念:每个内核中的IPC结构(消息队列、信号量、共享存储器)都用一个非负整数的标识符加以引用
  • 例如:要向一个消息队列发送消息或者从一个消息队列取消息,只需要知道其队列标识符

 特点:

  • 与文件描述符不同,IPC标识符不是小的整数
  • 当一个IPC结构被创建,然后又被删除时,与这种结构相关的标识符连续加1,直至达到一个整型数的最大正值,然后又会转到0

键:

  • 概念:标识符是IPC对象的内部名。为使多个合作进程能够在同一IPC对象上汇聚,需要提供一个外部命名方案。为此,每个IPC对象都与一个键(key)相关联,这个键作为该对象的外部名
  • 注意:无论何时创建IPC结构(通过msgget、semget、shmget创建),都应给IPC指定一个键
  • 键的数据类型:键的数据类型是基本系统数据类型key_t(在头文件<sys/types.h>中被定义为长整型)

三、键的创建(ftok函数)

  • 引言:键是使不同进程汇聚到同一IPC的方法,下面有3种方法使不同进程在同一IPC上汇聚
  • 下面我们以服务器进程和客户进程如何在同一IPC结构上汇聚为例(其他进程使用的原理相同)

方式一:

  • 服务器进程可以指定键IPC_PRIVATE创建一个新的IPC结构。当返回的标识符存放在某处(如一个文件)以便客户进程取用。键IPC_PRIVATE保证服务器进程创建一个新IPC结构
  • 键IPC_PRIVATE也可用于父进程子关系。父进程指定键IPC_PRIVATE创建一个新IPC结构,将返回的标识符可供fork后的子进程使用。接着,子进程又可将此标识符作为exec函数的一个参数传递给一个新的程序
  • 这种技术的缺点是:文件系统操作需要服务器进程将整型标识符写到文件中,以后客户进程又要读这个文件取得此标识符

方式二:

  • 可以在一个公用头文件中定义一个客户进程和服务器进程都认可的键。然后服务器进程指定此键创建一个新的IPC结构
  • 这种方法的问题是:该键可能已经与一个IPC结构相结合过了。此种情况下,get函数(msgget、semget、shmget)出错返回。服务器进程必须处理这一错误,可以通过删除已存在的IPC结构然后试着再创建它

方式三(ftok函数):

  • 客户进程和服务器进程可以通过一个路径名和项目ID(ID是0~255之间的字符值),接着调用函数ftok来将这两个值变换为一个键
#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);

//返回值:成功返回新生成的键值;出错返回-1(key_t类型)
  • 功能:通过一个路径名和项目ID生成一个新键值
  • pathname参数:必须引用一个现有的文件。proj_id参数:proj_id是0~255之间的字符值(当产生键时,只使用id参数的低8位)
  • ftok函数的实现原理:按给定的路径名取得其stat结构中的部分st_dev和st_ino字段,然后再将它们与项目ID组合起来。如果两个路径名引用的是两个不同的文件,那么ftok通常会为这两个路径名返回不同的键。但是,因为i节点编号和键通常都存放在长整型中,所以创建键时可能会丢失信息。重点:这意味着,对于不同文件的两个路径名,如果使用同一项目ID,那么可能产生相同的键

四、IPC的创建(msgget、semget、shmget

在创建IPC时,msgget、semget、shmget函数都有两个类似的参数:key与flag

  • IPC_CREAT:在创建新的IPC时,如果key参数是IPC_PRIVATE或者和当前某种类型的IPC结构无关,则需要指明flag参数的IPC_CREAT标志位,则用来创建一个新的IPC结构。(如果IPC结构已存在,并且指定了IPC_CREAT,则IPC_CREAT什么都不做,函数也不出错)
  • IPC_EXCL:此参数一般与IPC_CREAT配合使用来创建一个新的IPC结构。如果创建的IPC结构已存在函数就出错返回,返回EEXIST(这与open函数指定O_CREAT和O_EXCL标志原理相同)
  • 注意:key参数决不能用IPC_PRIVATE作为键来引用一个现有队列,因为这个特殊的键总是用于创建一个新的队列。为了引用一个用IPC_PRIVATE键创建的现有队列,一定要知道这个相关的标识符,然后在其他IPC调用中(如msgsnd、msgrcv)使用该标识符,这样可以绕过get函数
  • 如果上述get函数是为了引用一个现有队列:key必须等于队列创建时制定的key值,并且flag参数不能使用IPC_CREAT,flag可以填0
  • 在创建IPC结构时,还可以创建IPC结构的使用权限。例如:IPC_CREAT|IPC_EXCL|0666

备注:

  • 如果普通用户创建IPC结构时,有时候出现权限不足的情况,可以使用root权限执行权限,或者更改msgget、semget、shmget函数的flag参数,例如:IPC_CREAT|0666、IPC_CREAT|0777等

五、权限结构体(struct  ipc_perm)

  • 概念:XSI IPC为每一个IPC结构关联了一个ipc_perm结构体。该结构规定了权限和所有者
  • 每个系统的实现可能成员会不同。详情见头文件<sys/ipc.h>
struct ipc_perm {
    key_t          __key;   /* Key supplied to msgget(2) */
    uid_t          uid;     /* Effective UID of owner */
    gid_t          gid;     /* Effective GID of owner */
    uid_t          cuid;    /* Effective UID of creator */
    gid_t          cgid;    /* Effective GID of creator */
    unsigned short mode;    /* Permissions */
    unsigned short __seq;   /* Sequence number */
};

mode成员:

  • 成员的值如下图(对于任何IPC结构都不存在执行权限
  • 另外,消息队列和共享存储使用术语“读”和“写”,而信号量则使用术语“读”和“更改”

权限结构体的初始化赋值与更改:

  • 初始化:在创建IPC结构时,可以对所有的字段赋初始值
  • 更改:可以调用msgctl、semctl、sgmctl修改uid、gid、mode字段(注意事项:修改这些值,调用进程必须是IPC结构的创建者或超级用户)。修改这些字段类似于对文件调用chown、chmod

六、XSI  IPC结构体的限制

  • 3种形式的XSI  IPC都有内置限制。大多数限制可以通过重新配置内核来改变。在后面的文章分别介绍不同形式的IPC时,会指出他们不同的限制

七、XSI  IPC的优点和缺点

缺点:

  • ①IPC结构在系统范围内起作用。没有引用计数。例如,如果进程创建了一个消息队列,在该队列中放入了几则消息,然后终止,但是该消息队列及其内容不会被删除。它们会一直留在系统中直至发生下列动作为止:由某个进程调用msgrcv或msgctl读消息或删除消息队列;或某个进程执行ipcrm命令删除消息队列;或正在自举的系统删除消息队列。将此与管道相比,当最后一个引用管道的进程终止时,管道就完全被删除了。对于FIFO而言,在最后一个引用FIFO的进程终止时,虽然FIFO的名字仍保留在系统中,直至被显式地删除,但是留在FIFO中的数据已被删除
  • ②这些IPC结构在文件系统中没有名字。我们不能使用stat等系列函数访问和修改它们的特性。为了支持这些IPC对象,内核中增加了十几个全新的系统调用(msgget,semop,shmat等)。我们不能用ls命令查看IPC对象,不能用rm命令删除它们,也不能使用chmod等函数更改它们的访问权限。于是,又增加了两个新命令ipcs和ipcrm
  • ③IPC不使用文件描述符,所以不能对它们使用多路转换IO函数(select和poll)。这使得它很难一次使用一个以上这样的IPC结构,或者在文件或设备IO中使用这样的IPC结构。例如:如果没有某种形式的忙等循环(busy-wait loop),就不能使一个服务器进程等待将要放在两个消息队列中任意一个中的消息

优点:

  • ①可靠
  • ②流是受控的
  • ③面向记录
  • ④可以用非先进先出次序处理

八、不同形式的IPC的特征比较

  • 无连接是指:无需先调用某种形式的打开函数就能发送消息的能力。如前所述,因为需要有某种技术来获得队列标识符,所以我们并不认为消息队列是无连接的
  • 可靠:因为这些形式的IPC被限制在一台主机上,所以都是可靠的。当消息通过网络传送时,就要考虑丢失消息的可能性
  • 流控制是指:如果系统资源(缓冲区)短缺,或者如果接收进程不能再接收更多消息,则发送进程就要休眠。当流控制条件消失时,发送进程应自动唤醒
  • 上图没有显示的一个特征是:IPC设施能否自动地为每个客户进程创建一个到服务器进程的唯一连接。以后的文章会介绍UNIX流套接字可以提供这种能力
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

董哥的黑板报

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

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

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

打赏作者

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

抵扣说明:

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

余额充值