• 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
    ",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
    ",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的多数实现在有内在的内核限制,如消息队列的最大数目、每个信号集的最大信号量数等等。

  • 相关阅读:
    nginx利用image_filter动态生成缩略图
    uva 624 CD 01背包打印路径
    【剑指Offer学习】【全部面试题汇总】
    POJ2096-Collecting Bugs(概率DP)
    配置struts tags 输出HTML
    合并基因表达水平(merge gene expression levels, FPKM)
    设置MySQL自动增长从某个指定的数开始
    列联表(Crosstabs)
    mysql 实现行号的方法——如何获取当前记录所在行号
    shell 标出输入、标准输出、错误输出
  • 原文地址:https://www.cnblogs.com/alantu2018/p/8466220.html
Copyright © 2020-2023  润新知