UNP(卷2:进程间通信)—— 第2,3章:Posix IPC 和 System V IPC


第二章Posix IPC

以下三种类型的IPC合成为“Posix IPC”:

  • Posix消息队列
  • Posix信号量
  • Posix共享内存区



IPC名字的移植问题:

mq_open、sem_open、shm_open这三个函数的第一个参数就是一个名字,可能是某个文件系统中的一个真正的路径。


为避免移植问题:

1、把Posix IPC名字的#define行放在一个便于修改的头文件中。

2、自己定义一个名为px_ipc_name的函数,它为定位Posix IPC名字而添加上正确的前缀目录。


2.3 创建与打开IPC通道



消息队列能以其中任何一种模式(只读、只写、读写)打开,

信号量的打开不指定任何模式(都需要读写访问权。)

共享内存区对象则不能以只写模式打开。


O_CREAT                    若不存在则创建对象。(同时检查O_EXCL标志)。mode参数指定权限位,如下图


这些常值定义在<sys/stat.h>头文件中。

创建新对象时,其用户ID被置为当前进程的有效用户ID。

信号量和共享内存区对象的组ID被置为当前进程的有效组ID或者某个系统默认组ID。

新的消息队列对象的组ID则被置为当前进程的有效组ID。


O_EXCL            如果该标志和 O_CREAT 一起指定,对象不存在时才创建新的对象。若存在,且指定 O_CREAT | O_EXCL,那么返回一个 EEXIST错误。检查是否存在以及创建,这两步必须是原子性(atomic)操作。

O_NONBLOCK              该标志使得一个消息队列在队列为空时的读 或  队列填满时的写   不被阻塞。

O_TRUNC                  如果以读写方式打开一个已存在的共享内存区对象,那么该标志将使得该对象的长度被截为 0。







2.4 IPC权限

当这三个函数打开已存在的对象,将基于如下信息执行权限测试:

(1)创建时赋予该IPC对象的权限位;

(2)所请求的访问类型。(O_RDONLY、O_WRONLY、O_RDWR)

(3)调用进程的有效用户ID、有效组ID、各个辅助组ID。


大多数内核按如下步骤执行权限测试:

(1)如果当前进程的有效用户ID 为 0(超级用户), 那就允许访问。

(2)在当前进程的有效用户ID等于对象的属主ID的前提下,如果相应的用户访问权限位已设置,那就允许访问。否则拒绝。

(3)在当前进程的有效组ID或它的某个辅助组ID等于该IPC对象的组ID的前提下,如果相应的组访问权限位已设置,那就允许访问。否则拒绝。

(4)如果相应的其他用户访问权限已设置,那就允许访问。否则拒绝。


第三章System V IPC

以下三种类型的IPC合成为“System V IPC”:

  • System V 消息队列
  • System V 信号量
  • System V 共享内存区


key_t 键 和 ftok函数:

三种类型的System V IPC 使用 key_t值作为它们的名字。<sys/types.h>定义了key_t类型,通常是32位整数。

函数ftok把一个已经存在的路径名和一个整数标识符转换成一个key_t值,称为IPC键

#include <sys/ipc.h>
key_t   ftok(const char *pathname, int id);
                              返回:若成功则为IPC键,若出错则为-1
该函数把从pathname导出的信息与id的低序 8 位组合成一个整数IPC键

ftok的典型实现:

(1)pathname 所在的文件系统的信息(stat结构的st_dev成员)

(2)该文件在本文件系统内的索引节点号(stat结构的st_ino成员)

(3)id的低序 8 位 (不能为0)。

这三个值的组合通常会产生一个32位键。


ipc_perm结构:内核给每个IPC对象维护一个信息结构,定义在<sys/ipc.h>

struct ipc_perm {
    uid_t    uid;    /* owner's user id */
    gid_t    gid;    /* owner's group id */
    uid_t    cuid;   /* creator's user id */
    gid_t    cgid;   /* creator's group id */
    mode_t   mode;   /* read-write permissions */
    ulong_t  seq;    /* slot usage sequence number */
    key_t    key;    /* IPC key */
};

创建与打开IPC通道:


oflag参数:它指定IPC对象的读写权限位(ipc_perm结构的mode成员),

设置IPC_CREAT 位但不设置 IPC_EXCL位是没有意义的。





IPC权限

每当使用get_XXX函数创建一个新的IPC对象时,以下信息就保存到该对象的ipc_perm结构中。

(1)oflag参数中某些位初始化ipc_perm结构中的mode成员。


(2)cuid 和 cgid 成员分别设置为调用进程的有效用户ID和有效组ID。

(3)ipc_perm结构的uid和gid成员也分别设置为调用进程的有效用户ID和有效组ID。这两个成员合称属主ID(owner ID)。

任意进程要访问一个IPC对象都需要经历两个层级的检查:一个在IPC对象被打开时(检查是否指定了未包含在ipc_perm结构中的模式,因为创建的IPC对象的权限是存在于ipc_perm结构中的),一个在IPC对象被使用时(过程类似于PosixIPC的权限检查)。


ipcs和ipcrm程序
     由于System V IPC的三种类型不是以文件系统中路径名标识的,因此使用标准的ls和rm程序无法看到它们,也无法删除他们。不过实现了这些类型IPC的任何系统都提供两个特殊的程序:ipcs和ipcrmipcs输出有关System V IPC特性的各种信息ipcrm则删除一个System V消息队列、信号量集或共享储存区。

内核限制
System V IPC的多数实现有内在的内核限制,例如消息队列的最大数目、每个信号量集的最大信号量数等。
另外还存在一些缺点:

  • IPC结构是在系统范围内起作用的,没有访问计数。例如,如果创建了一个消息队列,在该队列中放入了几则消息,然后终止,但是该消息队列及其内容并不被删除。它们余留在系统中直至:由某个进程调用msgrcv或msgctl读消息或删除消息队列,或某个进程执行ipcrm命令删除消息队列;或由正在再启动的系统删除消息队列。
  • 这些IPC结构并不按名字为文件系统所知。因此不能用常规的文件系统函数来存取它们或修改它们的特性。为了支持它们不得不增加了十多个全新的系统调用(msgget、semop、shmat等)。不能用ls命令见到它们,不能用rm命令删除它们,不能用chmod命令更改它们的存取权。于是,也不得不增加了全新的命令ipcs和ipcrm。
  • 这些IPC不使用文件描述符,所以不能对它们使用多路转接I/O函数:select和poll。










  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值