💘作者:泠沫
💘博客主页:泠沫的博客
💘专栏:Linux系统编程,文件认识与理解,Linux进程学习…
💘觉得博主写的不错的话,希望大家三连(✌关注,✌点赞,✌评论),多多支持一下!!
目录
🏠进程间通信
本次介绍进程通信主要是讲解如何让两个进程看到同一份资源,而不是来进行通信的。
🚀 通信目的
-
数据传输:一个进程需要将它的数据发送给另一个进程。
-
资源共享:多个进程之间共享同样的资源。
-
通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止
时要通知父进程)。 -
进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另
一个进程的所有陷入和异常,并能够及时知道它的状态改变。
总的来说,Linux进程进行通信的目的是为了协调多个进程之间的操作,共享资源和信息,提高应用程序的可靠性和强大性。
🚀 通信发展
-
管道
-
System V进程间通信
-
POSIX进程间通信
🚀 通信分类
-
管道
匿名管道
命名管道 -
System V IPC
System V 消息队列
System V 共享内存
System V 信号量 -
POSIX IPC
消息队列
共享内存
信号量
互斥量
条件变量
读写锁
🏠 匿名管道
🚀 匿名管道原理
匿名管道是一种在进程间进行数据传递的机制,其本质基于操作系统内核提供的缓冲区来实现。通过使用类似于文件的方式进行读写,管道可以将一个进程生成的数据传递给另一个进程,而不需要将数据写入到实际的物理文件中,这样就避免了IO操作,从而提高效率。
- 匿名管道的创建是由操作系统来执行的,我们可以使用一个系统调用接口pipe,让操作系统创建一个匿名管道,当成功创建管道文件后,调用该接口的进程就会拿到管道的读写端文件描述符fds[2]。
- 然后再调用fork接口创建子进程,子进程是以父进程的进程控制块为模板进行创建的,所以子进程的进程控制块指向的文件描述符表中的文件描述符数组和父进程一样,都保存了管道的读写端。
- 最后,假设我们让父进程调用close系统接口关闭写端,子进程关闭读端。仅由子进程进行写操作,父进程进行读操作。那么匿名管道就可以实现两个具有血缘关系的进程进行通信。
下面介绍创建匿名管道的系统调用接口pipe():
该系统接口的参数是一个输出型参数,需要我们自己传入一个整型数组,如果创建匿名管道成功,该数组保存的是管道的读写端文件描述符。pipefd[0]存放的是读取端的文件描述符,pipefd[1]存放的是写入端的文件描述符。
该系统接口调用成功返回0,调用失败返回-1,且错误码被设置。
接下来用代码展示如何创建匿名管道,并且实现两个父子进程进行通信。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cassert>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
using namespace std;
int main()
{
int fds[2];
int n = pipe(fds);
assert(n != -1);
pid_t id = fork();
assert(id >= 0);
if(id == 0)
{
close(fds[0]);
int cnt = 0;
while(true)
{
char buffer[1024];
snprintf(buffer, sizeof(buffer), "child -> parent say: 我是子进程[%d],pid:%d", ++cnt, getpid());
write(fds[1], buffer, strlen(buffer));
//sleep(100);
sleep(1);
if(cnt == 10)
break;
}
close(fds[1]);
exit(0);
}
close(fds[1]);
while(true)
{
//sleep(100);
char buffer[1024];
ssize_t num = read(fds[0], buffer, sizeof(buffer) - 1);
if(num == -1)
{
perror("read failed");
break;
}
if(num > 0)
{
buffer[num] = 0;
cout << "Get messge: " << buffer << endl;
}
if(num == 0