systerm-v IPC

消息队列、共享内存和信号量被统称为 system-V IPC

一般习惯称呼他们为 IPC 对象,这些对象的操作接口都比较类似,在系统中他们都使用一种叫做 key 的键值来唯一标识,而且他们都是“持续性”资源——即他们被创建之后,不会因为进程的退出而消失,而会持续地存在,除非调用特殊的函数或者命令删除他们

Linux 的 IPC 对象(包括消息队列、共享内存和信号量)在内核内部使用链表维护,不同的对象使用 IPC 标识符来标识,如消息队列标识符 msqid、共享内存标识符 shmid,信号量标识符 semid。对于用户来说,内核提供了简洁的接口,不同的进程通过 IPC 关键字(key) 即可访问具体的对象

查询系统当前的 IPC 对象
ipcs

查看当前消息队列
ipcs  -q


system-V ipc特点

1.独立于进程
2.没有文件名和文件描述符
3.IPC对象具有key和ID

消息队列

消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法。每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型的数据结构。我们可以通过发送消息来避免命名管道的同步和阻塞问题

消息队列与信号的对比:

信号承载的信息量少,而消息队列可以承载大量自定义的数据

消息队列与管道的对比:

1.命名管道和消息队列进行通信的进程可以是不相关的进程,同时它们都是通过发送	
和接收的方式来传递数据的

2.在命名管道中,发送数据用 write(),接收数据用 read(),则在消息队列中,发送数
据用 msgsnd(),接收数据用msgrcv(),消息队列对每个数据都有一个最大长度的限制。

3.消息队列也可以独立于发送和接收进程而存在,在进程终止时,消息队列及其内容	
并不会被删除。

4.消息队列是面向记录的,其中的消息具有特定的格式以及特定的优先级,接收程序
可以通过消息类型有选择地接收数据,而不是像命名管道中那样,只能默认地接收

5.消息队列可以实现消息的随机查询,消息不一定要以先进先出的顺序接收,也可以
按消息的类型接收。

消息队列的实现包括创建或打开消息队列、发送消息、接收消息和控制消息队列这 4 种操作

消息队列相关API

ftok函数
作用:获取一个key

key_t ftok(const char *path,int proj_id)
path:一个合法路径
proj_id:一个整数

msgget函数
功能:获取消息队列ID

int msgget(key_t key,int msgflg)
key:消息队列的键值
msgflg:
	IPC_CREAT:如果消息队列不存在,则创建
	mode:访问权限
返回值:消息队列的ID

msgsnd函数
作用:发送消息到消息队列

int msgsnd(int msqid,const void *msgp,size_t msgsz,int msgflg);

msqid:消息队列ID
msgp:消息缓存区(发送给队列的消息)
msgp 可以是任何类型的结构体,但第一个字段必须为 long 类型,
即表明此发送消息的类型, msgrcv() 函数则根据此接收消息。
	struct msgbuf
	{
    
    long mtype;	 //消息标识char mtext[1]; //消息内容
	}
msgsz:消息正文的字节数大小
msgflg:
	IPC_NOWAIT:非阻塞发送
	0:阻塞发送

msgrcv函数
功能:从消息队列读取消息

ssize_t msgrcv(int msqid,void *msgp,size_t msgsz,long msgtyp,int msgflg)

msqid:消息队列ID
msgp:消息缓存区
msgsz:消息正文的字节数
msgtyp:要接受消息的标识
msgflg:
	IPC_NOWAIT:非阻塞读取
	MSG_NOERROR:截断消息
	0:阻塞读取

msgctl函数
功能:设置或获取消息队列的相关属性(删除,设置或这获取相关消息信息

int msgctl(int msgqid,int cmd,struct maqid_ds *buf)
msgqid:消息队列的ID
cmd:
	IPC_STAT:获取消息队列的属性信息
	IPC_SET:设置消息队列的属性
	IPC_RMID:删除消息队列
buf:相关结构体缓冲区

信号量

信号量与信号、管道、 FIFO 以及消息列队不同。它本质上是一个计数器,用于协调多进程间对共享数据对象的读取,它不以传送数据为主要目的,它主要是用来保护共享资源(信号量也属于临界资源),使得该临界资源在一个时刻只有一个进程独享。

信号量的操作:PV操作

信号量只能进行两种操作:等待和发送信号,即 P 操作和 V 操作,锁行为就是 P 操作,解锁就是 V 操作,所以 P 操作是申请资源, V 操作是释放资源。

P 操作:
如果有可用的资源(信号量值大于 0),则占用一个资源
即给信号量值减去一,进入临界区代码
如果没有可用的资源(信号量值等于 0),则阻塞,直到系统将资源分配给该进程
(进入等待队列,一直等到资源轮到该进程)。

V 操作:
如果在该信号量的等待队列中有进程在等待资源,则唤醒一个阻塞的进程。	
如果没有进程等待它,则释放一个资源,即给信号量值加一

信号量的作用

保护共享资源
 互斥
 同步

信号量用法:

1.定义一个唯一key(ftok)
2.构造一个信号量(semget)
3.初始化信号量(semctl SETVA)
4.对信号量进行P/V操作(semop)
5.删除信号量(semctl RMID)

semget函数
功能:获取信号量的ID

int semget(key_t key,int nsems,int semflg)
key:信号量键值
nsems:信号量数量
semflg:
	IPC_CREATE:信号量不存在则创建
	mode:信号量的权限
返回值:信号量ID

semctl函数
功能:获取或设置信号量的相关属性(删除 ,设置,获取)

int semctl(int semid,int semnum,int cmd,union semun arg)
semid:信号量ID
semnum:信号量编号
cmd:
	IPC_STAT:获取信号量的属性信息
	IPC_SET:设置信号量的属性
	IPC_RMID:删除信号量
	IPC_SETVAL:设置信号量的值
arg:可选参数
	union semun
	{
    
    
		int val;
		struct semid_ds *buf;
	}

semop函数

int semop(int semid,struct sembuf *sops,size_t nsops)
semid:信号量ID
sops:信号量操作结构体数组
	struct sembuf
	{
    
    short sem_num;	//信号量编号 信号量的序号从 0 ~ nsems-1short sem_op;//信号量P/V操作 >0 0 <0short sem_flg;	//操作标识: 0, IPC_WAIT, SEM_UNDO
	}
	sem_num 用于标识信号量中的第几个信号量
	sem_op 标识对信号量的所进行的操作类型
		>0:
		表示进程对资源使用完毕,交回该资源,即对该信号量执行 V 操
		作,交回的资源数由 sem_op 决定,系统会把 sem_op 的值加到该信号量的信号量当前值 semval 上
		0:
		表示进程要阻塞等待,直至信号量当前值 semval 变为 0
		<0:
		表示进程希望使用资源,对该信号量执行 P 操作
nsops:信号量数量	

共享内存

共享内存就是将内存进行共享,它允许多个不相关的进程访问同一个逻辑内存,直接将一块裸露的内存放在需要数据传输的进程面前,让它们自己使用

共享内存的思想非常简单,进程与进程之间虚拟内存空间本来相互独立,不能互相访问的,但是可以通过某些方式,使得相同的一块物理内存多次映射到不同的进程虚拟空间之中,这样的效果就相当于多个进程的虚拟内存空间部分重叠在一起
在这里插入图片描述

特点:

1.共享内存是进程间通信中效率最高的方式之一

2.共享内存是系统出于多个进程之间通讯的考虑,而预留的的一块内存区,因此共享
内存是以传输数据为目的的

3.共享内存允许两个或更多进程访问同一块内存,当一个进程改变了这块地址中的内
容的时候,其它进程都会察觉到这个更改。

4.使用共享内存进行进程间的通信非常方便,数据的共享使
进程间的数据不用传送,而是直接访问内存,加快了程序的效率
不像匿名管道那样要求通信的进程有一定的“血缘”关系,只要是系统中的任意进程都
可以对共享内存进行读写操作

5.共享内存没有提供同步的机制,这使得我们在使用共享内存进行进程间通信时,往
往要借助其他的手段(如信号量、互斥量等)来进行进程间的同步工作

作用:高效率传输大量数据

共享内存用法

1.定义一个唯一key(ftok)
2.构造一个共享内存对象(shmget)
3.共享内存映射(shmat)
4.解除共享内存映射(shmdt)
5.删除共享内存(shmctl RMID)

shmget函数
功能:获取共享内存对象的ID

int shmget(key_t key,int size,int shmflg)
key:共享对象键值
size::要创建共享内存的大小
所有的内存分配操作都是以页为单位的,所以即使只申请只有一个字节的内存,内存也
会分配整整一页
shmflg:
	IPC_CREATE:共享内存不存在则创建
	mode:共享内存的权限
返回值:共享内存ID

shmat函数
功能:映射共享内存

int shmat(int shmid,const void *shmaddr,int shmflg)
shmid:共享内存ID
shmaddr:映射地址,NULL为自动分配
shmflg:
	SHM_RDONLY:只读方式映射
	0:可读可写
返回值:共享内存首地址
	

shmdt函数
功能:解除共享内存映射

int shmdt(const void *shmaddr)
shmaddr:映射地址

shmctl函数
功能:获取或设置共享内存的相关属性

int shmctl(int shmid,int cmd,struct shmid_ds *buf)
shmid:共享内存ID
cmd:
	IPC_STAT:获取共享内存的属性信息
	IPC_SET:设置共享内存的属性
	IPC_RMID:删除共享内存
buf:属性缓冲区

猜你喜欢

转载自blog.csdn.net/qq_53144843/article/details/120159425
IPC