进程间通信(Linux面试干货)

进程间通信(IPC)

为什么操作系统要为用户提供进程间通信方式?

答:因为进程的独立性。每个进程都有自己的独立虚拟地址空间,操作的都是自己的地址,所以进程之间无法直接进行通信。

进程间通信方式

  1. 从Unix借鉴的:管道- - -资源传输;
  2. systemV标准的进程间通信方式:共享共存、消息队列、信号量

一、管道:传输资源- - -传输的是数据资源;

本质:内核中的一块缓冲区,若多个进程可以访问到同一个缓冲区,就可以实现通信。
分类:匿名管道/命名管道。
匿名管道:内核中的这块缓冲区没有具体的标识符,只能用于具有亲缘关系的进程间通信。多个进程只要通过子进程复制父进程的方式拿到同一个管道(缓冲区)的操作句柄就可以进行通信。
操作句柄:文件描述符。


在这里插入图片描述

创建匿名管道

int pipe(int pipefd[2]); pipefd[2] - - - 具有两个int型节点的数组的首地址,用于接收创建管道返回的操作句柄

pipefd[0] - - - 用于从管道中读取数据
pipefd[1] - - - 用于向管道中写入数据,要不然只能读,要不然只能写(单向传输);使用的时候如果不使用哪一段,关闭这一端就可以,管道是一个单向的资源传输,自身并不能限制资源的传输方向;管道是一个半双工通信(可以选择方向的单向传输)
在这里插入图片描述

管道的读写特性:
  1. 若管道中没有数据,则调用read读取数据会阻塞;
  2. 若管道中数据满了,则调用write写入数据会阻塞;管道是一块缓冲区(内存空间),并非无限制大。
    阻塞:为了完成一个功能,发起调用,若当前不具备完成条件,则一直等待。
  3. 若管道的所有读端pipefd[0]被关闭,则继续调用write会产生异常导致进程退出;
  4. 若管道的所有写端pipefd[1]被关闭,则继续调用read,read读完管道中你那个的数据后不再阻塞,而是返回0;

命令行中管道符的实现:ps -ef |grep ssh
ps -ef :默认将结果打印到标准输出
grep ssh :默认从标准输入读取数据进行过滤

ps进程如何将输出结果,并不写入标准输出而是写入到管道中呢?- - - -将标准输出重定向到管道写入端;
grep进程如何做到不从标准输入读取数据,而是从管道读取数据呢? - - - - 将标准输入重定向到管道读取端;
grep过滤了结果后并不会退出,循环读取数据进行过滤;因此ps进程退出后需要关闭所有写端,告诉grep没有人写了。

命名管道

命名管道是内核中的缓冲区,这块缓冲区具有标识符,(可用于同一主机上的任意进程间通信) 。这个标识符是一个可建于文件系统的管道文件,能够被其他进程找到并打开,管道文件则可以获取管道的操作句柄。
多个进程通过命名管道通信是通过打开命名管道文件访问同一块内核中的缓冲区实现通信。

创建管道文件:int mkfifo(char *filename,mode_t mode);

filename:管道文件名称;
mode:管道文件权限
返回值:成功则返回0,失败返回-1;
其余操作与文件IO操作相同

open 打开命名管道的特性
  • 若文件以只读打开,则会阻塞,直到文件被以写的方式打开;
  • 若文件以只写打开,则会阻塞,直到文件被以读的方式打开。

管道

本质:内核中的一块缓冲区;
分类

  • 匿名管道- - - - 只能用于具有亲缘关系的进程间通信;
  • 命名管道- - - - 可用于同一主机上的任意进程间通信;

特性

  • 管道是半双工通信(可以选择方向的单向传输);
  • 管道读写特性(不管匿名还是命名都是一样)
    若管道中没有数据则read会阻塞;若管道中数据满了则write会阻塞;
    若管道中所有读端关闭则write会触发异常;若管道所有写端关闭则read读完数据返回0不再阻塞;
  1. 管道生命周期随进程(打开管道的所有进程退出,管道就会被释放(命名管道也一样,本质都是缓冲区,文件只是标识符))。
  2. 管道提供字节流传输服务(可靠的、有序的,基于连接的一种灵活性比较高的传输服务);
  3. 命名管道额外有一个打开特性:只读打开则会则会阻塞直到文件以写方式打开;只写打开则会阻塞直至文件以读方式打开;
  4. 管道自带同步与互斥
    同步:通过条件判断实现临界资源操作的合理性;管道中没有数据则read会阻塞,管道中数据满了则write会阻塞。
    互斥:通过唯一访问实现临界资源操作的安全性;管道的读写操作在PIPE_BUF大小以保证操作的原子性。

临界资源:大家都能访问到的资源;
原子操作:不能被打断的操作,指的是一个操作要么一次完成,要么就不做。

二、共享内存

特性:1、共享内存是最快的进程间通信方式;2、生命周期随内核。
注意:共享内存并没有自带同步与互斥 - - - - - 多个进程进行访问的时候存在安全问题;
操作:代码操作流程/具体的接口 + 命令操作 ipcs/ipcrm。
本质原理
共享内存数据的写入,是一种针对地址指向空间的覆盖式写入。
在这里插入图片描述
共享内存的操作流程

  1. 创建共享内存- - - -在物理内存上开辟空间;
  2. 进程将共享内存映射到自己的虚拟地址空间;
  3. 基本的内存操作都可以对这块空间进行操作;
  4. 不玩了,解除虚拟地址空间与内存的映射关系;
  5. 释放共享内存资源。
int shmget(key_t key,size_t size,int shmflg); - - - - 创建共享内存

key:内核中共享内存的标识符 - - - - - 多个进程通过相同的标识符才能打开同一个共享内存;
size:共享内存的大小 - - - - - 以内存页为单位进行分配;
shmflg:IPC_CREAT存在则打开,不存在则创建 | IPC_EXCL 与 IPC_CREAT同时使用,若存在则报错,不存在则创建 | mode
返回值:返回一个非负整数- - - - - 共享内存的操作句柄;失败返回 -1;

key_t ftok(const char* pathname,int proj_id); - - - - -生成一个key值(通过inode节点号与proj_id合成一个key)
void *shmat(int shmid,const void *shmaddr,int shmflg)

shmid:shmget返回的共享内存操作句柄;
shmaddr:共享内存映射在虚拟地址空间的首地址 - - - - - 通常置为NULL;
shmflg:映射成功之后对共享内存可以进行的操作 , SHM_RDONLY用于只读(前提是有读的权限)/0(默认可读可写);
返回值:返回共享内存映射在虚拟地址空间中的首地址- - - - 通过这个首地址进行后续的内存操作,失败返回(void*)-1;

int shmdt(const void* shmaddr); - - - - - 解除映射关系

shmaddr:映射在虚拟地址空间的首地址;
返回值:成功返回0,失败返回-1;

shmct(int shmid, int cmd, struct shmid_ds *buf); - - - - - 删除共享内存

shmid:共享内存操作句柄;
cmd:对共享内存想要进行的操作 IPC_RMID (删除共享内存)
buf:用于获取/设置共享内存信息的结构,不使用则置NULL;
返回值:成功返回0,失败返回-1;
共享内存删除的时候,并不会立即被删除,只是将其状态置为被销毁状态,移除标识- - - - 为了不让这个共享内存继续被其他进程映射连接,然后等到当前共享内存映射连接数为0的时候,才会真正删除这块共享内存。

三、消息队列

内核中的一个优先级队列,多个进程通过访问同一个队列,进行添加节点或者获取节点实现通信。
特性:1、自带同步与互斥; 2、生命周期随内核。
在这里插入图片描述

  • 1、创建消息队列int msgget(key_t key,int msgflg); - - - (在内核中创建一个优先级队列)
  • 2、进程可以向队列中增加节点/获取节点
int msgsnd( int msqid, const void *msgp, size_t msgsz, int msgflg);
ssize_t msgrcv(int msqid, void *msgp,size_t msgsz,long msgtyp,int msgflg); - - - 指定获取什么类型的数据与mtype对应
struct msgbuf
{
//因为系统页不知道数据有多长,因此这个结构体由用户自己定义
long mtype;  //message type,must be>0
char mtext[1];  // message data
};
  • 3、删除消息队列
int msgct(int msqid, int cmd, struct msqid_ds *buf);

四、信号量

信号量用于实现进程间的同步与互斥的(共享内存本身是不提供同步与互斥的,操作存在安全问题,因此需要使用信号量保护对共享内存的操作)。
同步:通过条件判断实现临界资源访问的合理性;
互斥:通过同一时间的唯一访问实现临界资源访问的安全性;
本质:一个内核中的计数器 + pcb等待队列 + 使进程等待/唤醒的接口;
在这里插入图片描述
同步:资源能访问的时候,让你访问;不能访问的时候,让你等着;等到能访问了再去唤醒你去访问;
信号量组成:自身的计数器 + 等待队列 + 使一个进程等待以及唤醒一个进程的操作。
信号量实现互斥:保证同一时间只能有一个进程能够访问资源。
信号量实现互斥思想:所有资源只有一份,只有一个进程能够获取,用完了放回来,下一个进程再获取的思想。

ipcs命令

ipcs:查看进程间通信资源;
-m :查看共享内存;
-q:查看消息队列;
ipcrm:删除进程间通信资源;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值