Unix/Linux操作系统-进程通信

一、基本概念

进程间通信(IPC):是指两个或多个进程之间交换数据的过程
目的:每个独立的进程个体(资源单位)为了协同工作,提高效率

进程间通信方式:

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

二、传统的进程间通信

管道:UNIX系统最古老的进程间通信方式(基本不再使用),通常为半双工(只允许单向数据流动),现在的系统大都可以全双工,数据可以双向流动。

有名管道

头文件#include<sys/types> / #include<sys/stat.h>
命令:mkfifo
函数int mkfifo(const char *pathname, mode_t mode);
功能:创建管道文件
pathname:文件路径
mode:权限
返回值:成功返回0,失败范湖-1
编程模型

进程A进程B
创建管道(mkfifo)
打开管道(open)打开管道
读/写管道(read/write)读/写管道
关闭管道(close)关闭管道
删除管道(unlink)
无名管道

头文件#include<unistd.h>
函数声明int pipe(int pipefd[2]);
功能:用于通过fork创建的父子进程间的通信
pipefd:用来存储内核返回的文件描述符
– pipefd[0] 用于读操作
– pipefd[1] 用于写操作


练习1:使用有名管道进行通信,管道创建者读,对方写。
练习2:使用无名管道进程通信,父进程读,子进程写。

三、XSI进程间通信

X/open组织为UNIX系统设计一套进程间通信机制。

IPC标识
  1. 内核会为每个XSI的进程间通信对象维护一个IPC对象。
  2. 该对象通过一个非负整数来引用,每用一个IPC标识符持续+1,达到最大值时从零开始。
  3. IPC标识需要程序员自己创建。(类似于创建文件
IPC键值
#include<sys/types.h>
#include<sys/ipc.h>

key_t ftok(const char *pathname,int proj_id);类似于创建文件的文件名
功能:创建IPC键值(非负整数),自动生成(项目路径,项目编号)
注意:项目路径一定是有效路径

IPC对象的创建

IPC_PRIVATE创建IPC对象时永远创建成功。
IPC_CREAT对象存在则获取,不存在则创建。
IPC_EXCL如果对象已经创建,则创建失败。

IPC对象销毁/控制用到的宏

IPC_STAT获取IPC对象的属性
IPC_SET设置IPC对象的属性
IPC_RMID删除IPC对象

四、共享内存

共享内存:内核中开辟一块由IPC对象管理的内存,进程A,B都用自己的虚拟地址与之映射,这样就形成了共享内存,完成通信

特点:
1、不需要复制信息,是最快的一种进程间 通信机制
2、需要考虑同步问题(必须截止其他的机制,如信号)

进程模型

进程A函数名进程B函数名
生成IPC键值ftok生成IPC键值ftok
创建共享内存shmget获取共享内存shmget
映射共享内存shmat映射共享内存shmat
使用共享内存*ptr使用共享内存*ptr
取消映射shmdt取消映射shmdt
删除共享内存shmctl

#include<sys/ipc.h> / #include<sys/shm.h>

函数声明int shmget(key_t key, size_t size, int shmflg);
功能:创建/获取共享内存
key:IPC键,由ftok函数生成
size:共享内存的大小,最好是4096的整数倍,获取共享内存时,此值无效。
shmflg:0 获取共享内存
– IPC_CREAT 创建
– IPC_EXCL 如果存在则创建失败
返回值:成功返回共享内存标识(IPC标识),失败返回-1。


#include<sys/types.h> / #include<sys/shm.h>

函数声明void* shmat(int shmid, const void *shmaddr, int shmflg);
功能:映射共享内存
shmid:共享内存标识符,shmget函数的返回值。
shmaddr:进程提供的虚拟地址,与内核中的内存映射用的,也可以是NULL(内核会自动选择一个地址映射)。
shmflg:0 自动分配
– SHM_RDONLY 只读权限
– SHM_RND 当shmaddr不为空时shmaddr向下取整页。
返回值:映射成功后的虚拟地址。


#include<sys/types.h> / #include<sys/shm.h>

函数声明int shmdt(const void *shmaddr);
功能:取消虚拟地址与共享内存的映射
shmaddr:被映射过的虚拟地址


#include<sys/ipc.h> / #include<sys/shm.h>

函数声明int shmctl(int shmid, int cmd, struct shmid_ds* buf);
功能:删除共享内存,获取/设置共享内存的属性
shmid:共享内存标识符shmget的返回值
cmd
– IPC_STAT 获取共享内存的属性
– IPC_SET 设置共享内存的的属性
– IPC_RMID 删除IPC共享内存

struct shmid_ds{        
	struct ipc_perm shm_perm;   // 内存所有者及权限        
	size_t          shm_segsz;  // 内存的大小        
	time_t          shm_atime;  // 最后的映射时间        
	time_t          shm_dtime;  // 最后的取消映射时间        
	time_t          shm_ctime;  // 最后修改时间        
	pid_t           shm_cpid;   // 创建者进程ID        
	pid_t           shm_lpid;   // 最后映射/取消映射的进程ID        
	shmatt_t        shm_nattch; // 映射的次数
}
struct ipc_perm{        
	key_t          __key;   // IPC键值        
	uid_t          uid;     // 有效用户ID         
	gid_t          gid;     // 有效组ID        
	uid_t          cuid;    // 创建者的用户ID        
	gid_t          cgid;    // 创建者组ID        
	unsigned short mode;    // 权限        
	unsigned short __seq;   // IPC标识
}

五、消息队列

消息队列:内核负责管理的一个管道
特点:按顺序发送消息包(消息类型+消息内容),全双工工作。

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

函数声明int msgget(key_t key, int msgflg);
功能:创建/获取消息队列
key:IPC键值,由ftok函数自动生成
msgflg:0 获取消息队列
– IPC_CREAT 创建消息队列
– IPC_EXCL 如果存在则创建失败
返回值:消息队列标识


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

函数声明int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
功能:向消息队列发送消息
msqid:消息队列标识,msgget函数的返回值
msgp:结构指针

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

msgsz:消息的长度,不包括消息类型,sizeof(msgbuf)-4。
msgflg:0 阻塞,当消息队列满时,等待。
– IPC_NOWAIT 不阻塞,当消息队列满时,不等待。
返回值:成功发送返回0,失败返回-1。


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

函数声明ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
功能:从消息队列中按类型获取消息
返回值:成功接收到消息的字节数
msqid:消息队列标识,msgget函数的返回值
msgp

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

msgsz:要接收一消息的长度,可以长一些。
msgtyp:要接收的消息类型
– 0 接收任意类型的消息(接收队列中第一个消息)。
– 大于0 只接收msgtyp类型的消息
– <0 接收消息队列中小于等于msgtyp绝对值的消息,取小的那个。
msgflg
– 0 阻塞,消息队列中是否有对应类型的消息,没有则等待。
– 1 不阻塞,消息队列中没有对应类型的消息,则返回。

MSG_NOERROR
消息类型正确,而消息的实际长度大于msgsz,则不接收消息并返回-1。
如果msgflg带MSG_NOERROR标志,则把多余的消息截取,成功接收。
IPC_NOWAIT
如果消息队列没有要接收的消息,则不等待,返回-1。
MSG_EXCEPT
接收消息队列中第一个消息类型不是msgtyp的消息,编译时添加-D_GNU_SOURCE参数。


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

函数声明int msgctl(int msqid, int cmd, struct msqid_ds *buf);
功能:删除消息队列,设置或获取消息队列属性
msqid:消息队列标识,msgget函数的返回值
cmd:
– IPC_STAT 获取消息队列的属性
– IPC_SET 设置消息队列的的属性
– IPC_RMID 删除消息队列
返回值:成功返回0,失败返回-1。

struct msqid_ds{        
	struct ipc_perm msg_perm;   // 权限        
	time_t          msg_stime;  // 最后一个消息发送时间        
	time_t          msg_rtime;  // 最后一次消息接收时间        
	time_t          msg_ctime;  // 最后一次修改时间        
	unsigned long __msg_cbytes; // 消息队列中的字节数        
	msgqnum_t       msg_qnum;   // 消息队列中消息的个数        
	msglen_t        msg_qbytes; // 消息队列中容纳的最大字节数        
	pid_t           msg_lspid;  // 最后一次发送消息进程        
	pid_t           msg_lrpid;  // 最后一次接收消息进程
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值