Linux环境编程08(进程间通信)

Linux环境编程08(进程间通信)

一、进程通信基本概念

什么是进程间通信:是指两个或多个进程之间交互数据的过程,因为进程之间是相互独立的,为了进程间协同工作就必须实现进程间交互数据。
进程间通信的分类:

  1. 简单的进程间通信:信号、普通文件、环境变量表、命令行参数
  2. 传统的进程间通信:管道文件
  3. XSI的进程间通信: 共享内存、消息队列、信号量
  4. 网络进程间通信:Socket套接字

二、传统的进程间通信-管道文件

管道是UNIX系统中最古老的进程间通信技术,古老意味着所有系统都支持,早期的管道是半双工通信,现有的系统管道是全双工通信。
管道就是一种特殊的文件,数据在文件中是流动的,读取之后就自动消失,如果文件中没有数据则会阻塞,其中,管道又细分为有名管道和无名管道。
有名管道:顾名思义就是基于有文件名的管道文件的通信。

        编程模型
            进程A              进程B
          创建管道             
          打开管道              打开管道
          写数据                读数据
          关闭管道              关闭管道 
          删除管道

创建有名管道文件:

  1. 命令 mkfifo
  2. 函数
    int mkfifo(const char *pathname,mode_t mode);
    功能:创建有名管道
    pathname:管道文件路径
    mode:管道文件权限 0664

匿名管道
只适合通过fork创建父子进程之间使用
int pipe(int pipefd[2]);
功能:创建一个匿名管道文件,通过pipefd返回该匿名管道文件的读权限fd和写权限的fd。
pipefd[0] 用于读匿名管道
pipefd[1] 用于写匿名管道

编程模型:
父进程             子进程
获取一对fd
创建子进程          拷贝\共享一对fd
关闭读              关闭写
写数据              读数据
关闭写              关闭读

三、XSI进程间通信

XSI通信:X/open公司制定的用于进程间通信的系统(S)接口(I)
XSI进程间通信都需要借助系统内核完成,需要创建内核对象,内核对象会以整数形式返回给用户态,类似于文件描述符,也叫做IPC标识符。
文件的创建打开需要借助文件名,IPC内核对象需要借助IPC键值(整数),必须要确保IPC键值是独一无二的。

key_t ftok(const char *pathname, int proj_id);
功能:计算出一个独一无二的IPC键值
pathname:项目路径
proj_id:项目标号
返回值:计算出来的IPC键值
注意:项目路径必须真实存在,否则计算出来的key永远相同

XSI进程通信之共享内存:

基础特点:两个或多个进程之间共享一块由内核负责统一管理内存,该内存可以与多个进程的虚拟内存进行映射。

优点:不需要复制信息,直接读写内存,是最快的一种IPC机制
缺点:需要考虑同步访问问题,一般使用信号

int shmget(key_t key,size_t size,int shmflg);
功能:创建\获取一块共享内存
key:IPC键值
size:共享内存的大小,获取共享内存时此参数无意义,一般给0
shmflg

IPC_CREAT创建共享内存,如已存在直接获取
IPC_EXCL共享内存已存在,返回失败
若只需要获取共享内存则直接给0

注意:如果是创建共享内存还需要额外提供共享内存的权限 例如:IPC_CREAT|0664

返回值:IPC标识符,失败-1

void *shmat(int shmid,const void *shmaddr, int shmflg);
功能:让虚拟内存与共享内存进行映射
shmid:IPC标识符 shmget的返回值
shmaddr:想要映射的虚拟内存首地址,为NULL时系统会自动分配地址
shmflg

  • SHM_RDONLY 以只读方式映射共享内存
  • SHM_RND:只有shmaddr参数不为NULL时才有有效,表示从shmaddr开始向下以整数页方式映射

返回值:与共享内存映射成功后的虚拟内存首地址,失败返回(void *) -1

int shmdt(const void *shmaddr);
功能:取消映射
shmaddr:映射成功后的虚拟内存首地址

int shmctl(int shmid,int cmd,struct shmid_ds *buf);
功能:删除/控制共享内存
shmid:IPC标识符
cmd

IPC_STAT获取共享内存属性buf输出型参数
IPC_SET设置共享内存属性buf输入型参数
IPC_RMID删除共享内存NULL
    编程模型:
    进程A               进程B
    创建共享内存        获取共享内存
    映射共享内存        映射共享内存
    写数据并通知其他进程 收到通知并读数据
    收到通知并读数据    写数据并通知其他进程
    取消映射            取消映射
    删除共享内存        

XSI进程通信之消息队列:

基本特点:是由内核负责维护管理的链式数据队列,不是根据先后顺序出队,而是根据消息类型进行收发数据
int msgget(key_t key, int msgflg);
功能:创建\获取消息队列
key:IPC键值
msgflg

IPC_CREAT消息队列已存在则获取,否则创建
IPC_EXCL消息队列已存在则返回错误
注意:如果创建需要提供权限

返回值:IPC标识符,失败-1

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
功能:向消息队列发送消息包
msqid:IPC标识符
msgp:要发送的消息包的首地址

struct msgbuf {
    long mtype;      //  消息类型
    char mtext[n];   //  数据
};

msgsz:数据的字节数,不包含消息类型
msgflg

  • 阻塞发送一般给0
  • IPC_NOWAIT 不阻塞立即返回

返回值:0成功 -1失败

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
功能:从消息队列中接收对应消息包的数据
msqid:IPC标识符
msgp:存储消息包的内存首地址
msgsz:存储数据的内存字节数(尽量大些)
msgtyp:消息类型(按照类型获取,不按照顺序)

  • >0 读取消息类型=msgtyp的消息
  • =0 读取消息队列中第一条消息
  • <0 读取消息类型小于abs(msgtyp)的消息,如果有多个则读值最小的

msgflg:

  • IPC_NOWAIT 消息队列都不符合时不阻塞,立即返回
  • MSG_EXCEPT 如果msgtyp>0,则读取第一条不等于msgtyp的消息
  • MSG_NOERROR 如果不包含此标志,如果实际发送过来的数据字节数>接收的字节数,则返回失败,如果包含此标志,那么就只读取接收的字节数,一定会成功

返回值:成功读取到数据的字节数

int msgctl(int msqid,int cmd,struct msqid_ds *buf);
功能:获取\修改消息队列的属性、删除队列
msqid:IPC标识符
cmd

IPC_STAT获取消息队列属性buf输出型参数
IPC_SET设置消息队列属性buf输入型参数
IPC_RMID删除消息队列NULL
    编程模型:
        进程A                   进程B
      创建消息队列             获取消息队列
      发送消息                  获取消息
      获取消息                  发送消息
      删除消息队列
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值