POSIX IPC基本概念

 

说明:只供学习交流,转载请注明出处

 

一,前言

使用信号和管道进行进程通信存在一定的限制。例如,使用信号传递的信息有限,使用管道虽然能够传输一定量的信息,但是只能传输无格式的字节流。为了解决这些问题,20世纪70年代,AT&T发行的system V版本的Unix中引入了3中新的进程间通信(IPC)机制,分别是:消息队列、共享内存和信号量。在POSIX标准中,这些进程间通信机制被编入POSIXXSI中。Linux系统支持POSIX标准,自然就支持这几种(IPC)机制。

 

二,基本概念

1、消息队列简介

顾名思义,消息队列指的是存放消息的队列。消息是指有消息类型和数据的信息,这些信息被存放在预先定义的消息结构中。消息类型可以是私有的(只用于创建消息队列的进程及其子进程访问),也可以是共有的(能够被系统中所有的进程访问)。要让系统中其他进程访问,必须通过一个唯一的标识,这个标识在消息队列中称为消息的Key。不同进程通过向消息队列中写入消息或读取消息来实现进程间的数据交换。

2、信号量简介

信号量用于多进程情况下的进程同步问题。信号量是一个含有整数值的资源,进程通过检测该整数值,来保证其他进程在某个时间不会进行类似的操作。

 

3、共享内存简介

Linux系统中,每个进程都运行在自己的虚拟地址空间中。进程之间是不能够访问其他进程的地址空间的。共享内存通过建立一段充许其他进程访问的内存空间,实现资源和数据的共享。进程可以对共享内存空间进行读写操作。当多个进程同时进行写操作时,需要使用信号量控制对资源的访问。

 

POSIX IPC提供的这3IPC通信机制都只能用于本机之间的进程通信。要实现不同主机之间的进程通信,可以使用socket套接字或RPC等方式。

 

 

三,IPC资源

消息队列、信号量和共享内存都是IPC资源,而在使用IPC资源前,需要创建该资源。与文件属性中有文件所有者、访问权限等信息类似,IPC资源也具体类似的属性。这些属性被保存在结构体ipc_perm中,包含IPC关键字、IPC资源的拥有者和同组用户等信息。

struct ipc_perm

{

      __kernel_key_t key;  //关键字

      __kernel_uid_t  uid;  //所有者ID

      __kernel_gid_t  gid;  //所有者所属组ID

      __kernel_uid_t  cuid; //创建者ID

      __kernel_gid_t  cgid; //创建者所属组ID

      __kernel_mode_t    mode;  //访问权限

      unsignedshort   seq;

};

 

 

四,IPC标识符与关键字

Linux内核中,为了标识IPC资源,使用了一个非负整数的标识符。只要通过该标识符就可以访问与标识符相关的IPC资源,如消息队列、信号量或共享内存。这一标识被称为IPC标识符。

要创建IPC标识符,需要指定一个关键字。IPC关键字(ipc_perm结构体中的__key)可以通过调用ftok函数获得。ftok函数的具体信息如下表所示:

 

ftok函数

 

头文件

#include <sys/types.h>

#include <sys/ipc.h>

函数原型

key_t ftok(const char *pathname, int  proj_id);

返回值

成功

失败

是否设置errno

产生的IPC关键字

-1

 

说明:ftok函数将给定的pathnameproj_id转换成IPC关键字。参数pathname必须指向文件系统中存在的文件或目录。

 

错误信息:

EACCES:无权限进入pathname中的目录。

ELOOP:解析pathname时存在循环。

ENAMETOOLONGpathname长度超过PATH_MAX限定,或路径中某个目录长度超过了NAME_MAX限定。

ENOENTpathname中的某个目录为空。

ENOTDIRpathname中含有非目录部分。

 

实例:

 

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>

int main(void)
{
    key_t key;
    int proj_id;
    char *pathname = "./program";
    
    proj_id = 1;
    
    key = ftok(pathname, proj_id);
    if ( key == -1 )
    {
        perror("Cannot generate the IPC key");
        return (1);
    }        
    
    printf("proj_id = %d pathname = %s IPC key = %d\n", proj_id, pathname, key);
    
    proj_id = 2;
    key = ftok(pathname, proj_id);
    if (key == -1)
    {
        perror("Cannot generate the IPC key");
        return (1);
    }
    
    printf("proj_id = %d pathname = %s IPC key = %d\n", proj_id, pathname, key);
    
    
    return (0);
        
}    
运行结果:
[root@localhost test]# ./ftok 
proj_id = 1 pathname = ./program IPC key = 16912503
proj_id = 2 pathname = ./program IPC key = 33689719


 

五,基本IPC命令

为了方便地使用IPC通信机制实现进程间的通信,在POSIX:XSI中还定义了查看和删除IPC资源的命令。ipcs命令提供了查看内核中存储的IPC资源的方法,而ipcrm用于从内核中删除指定的IPC资源。

 

1ipcs命令

ipcs命令用于显示系统中与POSIXXSI进程间通信相关的资源信息。ipcs命令常用的参数有q(显示消息队列信息)s(显示信号量信息)和m(显示共享内存信息)。如果不带任何参数执行ipcs命令,将会显示消息队列、信号量和共享内存三者的信息。

2ipcrm命令

POSIX标准还提供了从内核中删除IPC资源的系统调用,使用ipcrm可以手工移除IPC资源。

从帮助信息中可以了解到ipcrm的各种使用参数,如下表所示:

 

参数

说明

参数

说明

-q msqid

移除msqid为指定值的消息队列资源

-Q mskey

移除keymskey的消息队列资源

-m shmid

移除shmid为指定值的共享内存资源

-M shmkey

移除keyshmkey的共享内存资源

-s semid

移除semid为指定值的信号量资源

-S semkey

移除keysemkey的信号量资源

 

在实际使用中,往往需要将ipcsipcrm配合起来使用。删除系统中的消息队列资源的具体步骤如下:

1):使用ipcs查看系统中IPC资源的情况

2):根据显示的msqidkey信息,使用ipcrm删除指定的资源。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值