System V IPC

简介:

1、概述

   System V IPC共有三种类型:System V消息队列、System V 信号量、System V 共享内存区。 System V IPC操作函数如下:

2、key_t键和ftok函数

  三种类型的IPC使用key_t值作为他们的名字,头文件<sys/types.h>把key_t定义为一个整数,通常是一个至少32位的整数,由ftok函数赋予的。函数ftok把一个已存的路径和一个整数标识符转换成一个key_t值,称为IPC键。函数原型如下:

#include <sys/types.h>#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);  //成功返回IPC键,出错返回-1

写个程序看看ftok是如何组合IPC键,程序如下:

复制代码
 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <unistd.h>
 4 #include <sys/types.h>
 5 #include <sys/ipc.h>
 6 #include <sys/stat.h>
 7 #include <errno.h>
 8 
 9 typedef unsigned long u_long;
10 
11 int main(int argc,char *argv[])
12 {
13     struct stat st;
14     key_t  key;
15     if(argc != 2)
16     {
17         printf("usage: ftok<pathname>");
18         exit(0);
19     }
20     //获取文件结构信息
21     if (stat(argv[1],&st) == -1)
22     {
23         perror("stat() error");
24         exit(EXIT_FAILURE);
25     }
26     printf("st_dev : %lx,st_ino: %lx ",(u_long)st.st_dev,(u_long)st.st_ino);
27     //产生IPC键
28     if((key = ftok(argv[1],0x57)) == -1)
29     {
30         perror("ftok() error");
31         exit(EXIT_FAILURE);
32     }
33     printf("key: %x\n",key);
34     exit(0);
35 }
复制代码

在Ubuntu上程序测试结果如下:

可以看出在Linux上面IPC键使用的是id低8位,st_dev的低8位以及st_ino的低16位构成的。

3、ipc_perm结构

  内核给每个IPC对象维护一个信息结构,内容跟内核给文件维护的信息类似。Unix下结构信息如下:

struct ipc_perm 
{
key_t       key;     /* Key supplied to semget(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 */
};

在Linux该结构信息如下:

参考http://linux.die.net/man/5/ipc

4、创建与打开IPC通道

  对于key值,有两种选择:

(1)调用fotk函数,给它传递pathname和id。

(2)指定key为IPC_PRIVATE,保证会创建一个新的、唯一的IPC对象。

5、IPC权限

For semaphores (from sys/sem.h)
#define SEM_A 0200 /* alter permission */
#define SEM_R 0400 /* read permission */

For message queues (from sys/msg.h)
#define MSG_R 0400 /* read permission */
#define MSG_W 0200 /* write permission */

For shared memory (from sys/shm.h)
#define SHM_R 0400 /* read permission */
#define SHM_W 0200 /* write permission */

6、标识符重用

  System V IPC 标识符是系统范围的,不是特定于进程的。ipc_perm结构含有一个名为seq的变量,是内核为系统每个潜在的IPC对象维护的计数器,每当删除一个IPC对象时,内核就递增相应的槽位号,若溢出则循环到0。这样避免短时间内重用System V IPC标识符,有助于确保过早终止的服务器重新启动后不会重用标识符。写个程序测试输出有megget返回的前10个标识符值,程序如下:

复制代码
 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <unistd.h>
 4 #include <sys/types.h>
 5 #include <sys/ipc.h>
 6 #include <sys/msg.h>
 7 
 8 #define MSG_R 0400 /* read permission */
 9 #define MSG_W 0200 /* write permission */
10 
11 #define SVMSG_MODE (MSG_R | MSG_W | MSG_R >>3 | MSG_R >>6)
12 
13 int main()
14 {
15     int i,msqid;
16     for(i=0;i<10;++i)
17     {
18         msqid = msgget(IPC_PRIVATE,SVMSG_MODE|IPC_CREAT);
19         printf("msqid = %d\n",msqid);
20         msgctl(msqid,IPC_RMID,NULL);
21     }
22     exit(0);
23 }
复制代码

在Ubuntu上面测试结果如下: 

7、ipcs和ipcrm程序

  System V IPC的三种类型不是以文件系统中的路径名标识的,不能使用ls和rm程序查看和删除。而是同ipcs程序输出System V IPC特性的各种信息,ipcrm则删除一个System V 消息队列、信号量或共享内存区。

ipcs - 分析消息队列、共享内存和信号量 
ipcs [-mqs] [-abcopt] [-C core] [-N namelist] 
-m 输出有关共享内存(shared memory)的信息
-q 输出有关信息队列(message queue)的信息
-s 输出信号量(semaphore)的信息

输出本机所有System V IPC消息如下:

ipcrm - 删除ipc(清除共享内存信息)
ipcrm -m|-q|-s shm_id
-m 输出有关共享内存(shared memory)的信息
-q 输出有关信息队列(message queue)的信息
-s 输出信号量(semaphore)的信息

8、内核限制

  System V IPC的多数实现在有内在的内核限制,如消息队列的最大数目、每个信号集的最大信号量数等等。

相关文章
|
5月前
|
网络协议 Windows
windows 80端口占用 system pid=4
windows 80端口占用 system pid=4
47 0
|
5月前
|
Ubuntu Docker 容器
System has not been booted with systemd as init system (PID 1). Can‘t operate.
System has not been booted with systemd as init system (PID 1). Can‘t operate.
|
5月前
System.exit(0)和System.exit(1)区别
System.exit(0)和System.exit(1)区别
|
11月前
IPC$访问与关闭IPC$访问
IPC$访问与关闭IPC$访问
121 0
|
10月前
|
消息中间件 Linux C语言
System V通信
System V通信
109 0
|
11月前
|
消息中间件 安全 Linux
【Linux】system V 消息队列 | system V 信号量(简单赘述)
【Linux】system V 消息队列 | system V 信号量(简单赘述)
140 0