【Linux】必须要掌握的进程间通信的方法

请添加图片描述

进程间通信

进程和进程之间的关系,即进程间通信IPC。

进程间通信的目的

Q:为什么要有进程间通信?进程间通信的目的?

  • 数据传输:一个进程需要将它的数据发送给另一个进程
  • 资源共享:多个进程之间共享相同的资源
  • 通知事件:一个进程需要向另一个或一组进程发送消息,通知进程发生事件
  • 进程控制:有些进程希望完全控制另一个进程的执行,希望获得进程的状态

进程间通信如何做到

Q:进程间通信如何做到?

进程运行的时候具有独立性,在数据层面上。

进程间通信,一般需要通过第三方(OS)资源。

通信的本质就是“数据的拷贝”,让不同的进程看到同一份资源(内存,文件内核缓冲等)

进程A -> 进程A将数据“拷贝”给OS -> OS将数据“拷贝”给进程B

所以操作系统需要提供一段内存区域,并且这一块内存区域可以让两个进程都可以看到。

其中看到的同一份资源的不同种类(由操作系统中不同的模块提供)就是不同的通信方式。

通信的发展

  • 管道
  • System V进程间通信
  • POSIX进程间通信

通信有标准(技术路径的发展方向,包括现存的技术)

进程间通信分类

管道

  • 匿名管道pipe
  • 命名管道

System V IPC

  • System V 消息队列
  • System V 共享内存
  • System V 信号量

POSIX IPC

  • 消息队列
  • 共享内存
  • 信号量
  • 互斥量
  • 条件变量
  • 读写锁

管道

^pipe

什么是管道

管道是Unix中最古来的进程间通信的形式,将从一个进程连接到另一个进程的数据流称为一个“管道”。

![[Pasted image 20220203220818.png]]

使用文件的方式,来进行数据共享就是管道通信。管道虽然用的是文件的方案,其实os不会把数据刷新到磁盘上。(如果刷新到磁盘上的话就涉及到IO了,就降低速度)

who用于查看当前Linux的登录用户。
who | wc -l统计行数

匿名管道

匿名管道,即没有文件名
管道只能进行单向通信,

匿名管道的使用

原型:
int pipe(int fd[2])
参数:
fd:文件描述符数组,其中fd[0]是读端,fd[1]是写端。
返回值:
成功返回0,失败返回错误代码

其中int fd[2]是输出型参数。

  1. 父进程创建管道
    ![[Pasted image 20220203221905.png]]

  2. 父进程fork创建子进程
    ![[Pasted image 20220203221952.png]]

本质是为了让父子进程看到同一份资源,通常是父子进程进行通信的方式。

下面需要确认谁读谁写,关闭对应的读写端。

  1. 父进程关闭fd[0],子进程关闭fd[1]
    ![[Pasted image 20220203222346.png]]

一开始父进程读写端都打开是为了让子进程继承,而因为管道只能单向通信所以必须要关闭进程对应的读写端。

一般情况下
fd[0]:保存读文件描述符
fd[1]:保存写文件描述符

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <stdlib.h>

// 子进程写入,父进程读取
int main()
{
   
	int fd[2] = {
   0};
	if (pipe(fd) < 0)
	{
   
		perror("pipe");
		return 1;
	}
	
	pid_t id = fork();
	// 子进程
	if (id == 0)
	{
   
		// 关闭读端
		close(fd[0]);	
		int count = 10;
		const char* msg = "I am child process";
		while (count --)
		{
   
			write(fd[1], msg, strlen(msg));
			sleep(1);
		}
		close(fd[1]);
		// 子进程退出
		exit(0);
	}
	// 父进程
	// 关闭写端
	close(fd[1]);
	
	char buff[64];
	while (1)
	{
   
		// size_t是unsigned int
		// ssize_t是int
		ssize_t s = read(fd[0], buff, sizeof(buff));	
		// s是从管道中实际读到的字节个数
		if (s > 0)
		{
   
			buff[s] = '\0';
			printf("child process send to father process# %s\n", buff);
		}
		else if (s == 0)
		{
   
			printf("read file end\n");	
		}
		else
		{
   
			perror("read");	
		}
	}	
		
	waitpid(id, NULL, 0);
	
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hyzhang_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值