进程间通信之信号量semaphore--linux内核剖析( 六 )

其中ipc_perm 结构是内核给每个进程间通信对象维护的一个信息结构 , 其成员包含所有者用户id , 所有者组id、创建者及其组id , 以及访问模式等;semid_ds结构体中的sem结构是内核用于维护某个给定信号量的一组值的内部结构 , 其结构定义:
struct sem {ushort semval; /* 信号量的当前值 */short sempid; /* 最后一次返回该信号量的进程ID 号 */ushort semncnt; /* 等待semval大于当前值的进程个数 */ushort semzcnt; /* 等待semval变成0的进程个数 */};常见的SYSTEM V信号量函数关键字和描述符SYSTEM V信号量是SYSTEM V IPC(即SYSTEM V进程间通信)的组成部分 , 其他的有SYSTEM V消息队列 , SYSTEM V共享内存 。 而关键字和IPC描述符无疑是它们的共同点 , 也使用它们 , 就不得不先对它们进行熟悉 。 这里只对SYSTEM V信号量进行讨论 。
IPC描述符相当于引用ID号 , 要想使用SYSTEM V信号量(或MSG、SHM) , 就必须用IPC描述符来调用信号量 。 而IPC描述符是内核动态提供的(通过semget来获取) , 用户无法让服务器和客户事先认可共同使用哪个描述符 , 所以有时候就需要到关键字KEY来定位描述符 。
某个KEY只会固定对应一个描述符(这项转换工作由内核完成) , 这样假如服务器和
客户事先认可共同使用某个KEY , 那么大家就都能定位到同一个描述符 , 也就能定位到同一个信号量 , 这样就达到了SYSTEM V信号量在进程间共享的目的 。
创建和打开信号量创建一个信号量或访问一个已经存在的信号量集 。
int semget(key_t key, int nsems, int oflag)该函数执行成功返回信号量标示符 , 失败返回-1
参数描述key通过调用ftok函数得到的键值nsems代表创建信号量的个数 , 如果只是访问而不创建则可以指定该参数为0 , 我们一旦创建了该信号量 , 就不能更改其信号量个数 , 只要你不删除该信号量 , 你就是重新调用该函数创建该键值的信号量 , 该函数只是返回以前创建的值 , 不会重新创建;semflg指定该信号量的读写权限 , 当创建信号量时不许加IPC_CREAT, 若指定IPC_CREAT
semget函数执行成功后 , 就产生了一个由内核维持的类型为semid_ds结构体的信号量集 , 返回semid就是指向该信号量集的引索 。

  • nsems>0 : 创建一个信的信号量集 , 指定集合中信号量的数量 , 一旦创建就不能更改 。
  • nsems==0 : 访问一个已存在的集合
  • 返回的是一个称为信号量标识符的整数 , semop和semctl函数将使用它 。
  • 创建成功后信号量结构被设置:
.sem_perm 的uid和gid成员被设置成的调用进程的有效用户ID和有效组ID.oflag 参数中的读写权限位存入sem_perm.mode.sem_otime 被置为0,sem_ctime被设置为当前时间.sem_nsems 被置为nsems参数的值1234该集合中的每个信号量不初始化 , 这些结构是在semctl , 用参数SET_VAL , SETALL初始化的 。
#include #include #include #include #include #define SEM_R0400//用户(属主)读#define SEM_A0200//用户(属主)写#define SVSEM_MODE (SEM_R | SEM_A | SEM_R>>3 | SEM_R>>6)int main(int argc,char *argv[]){intc, oflag, semid, nsems;oflag = SVSEM_MODE | IPC_CREAT;//设置创建模式//根据命令行参数e判断是否制定了IPC_EXCL模式while((c = getopt(argc,argv,"e")) != -1){switch(c){case 'e':oflag |= IPC_EXCL;break;}}//判断命令行参数是否合法if (optind != argc -2){printf("usage: semcreate [-e]");exit(-1);}//获取信号量集合中的信号量个数nsems = atoi(argv[optind+1]);//创建信号量 , 通过ftok函数创建一个key , 返回信号量 标识符semid = semget(ftok(argv[optind],0),nsems,oflag);return EXIT_SUCCESS;}关键字的获取有多种方法使客户机和服务器在同一IPC结构上会合: * 服务器可以指定关键字IPC_PRIVATE创建一个新IPC结构 , 将返回的标识符存放在某处(例如一个文件)以便客户机取用 。 关键字 IPC_PRIVATE保证服务器创建一个新IPC结构 。 这种技术的缺点是:服务器要将整型标识符写到文件中 , 然后客户机在此后又要读文件取得此标识符 。
IPC_PRIVATE关键字也可用于父、子关系进程 。 父进程指定 IPC_PRIVATE创建一个新IPC结构 , 所返回的标识符在fork后可由子进程使用 。 子进程可将此标识符作为exec函数的一个参数传给一个新程序 。