Linux14 -- 进程间通信、管道

一、进程间通信

前言

进程间通信

进程间通信的方法

(1)管道
(2)信号量
(3)共享内存
(4)消息队列
(5)套接字

你了解的IPC机制都有哪些?

二、管道

1、管道简介

| 命令:
举例:ps -ef | grep “sleep”
两个进程通信,比如a,b进程,a向管道中写入数据,b读取数据;
在这里插入图片描述
管道的分类:有名管道和无名管道
区别
有名管道在任意两个进程间通信,
无名管道在父子进程间通信;

2、有名管道的创建

创建的命令:mkfifo
打开管道:open();
读数据:read();
写入数据:write();
关闭管道:close();

3、相关思考

如果进程 a 要将从键盘获取的数据传递给另一个进程 b, 用已具备的知识思考应该如何完成 ?

创建管道之后,它会在内存上分配一块空间,表面上看把数据写入管道中了,实际上是把数据写入内存中了。另外一个程序是从内存中读取数据的,所以效率是比较高的。

管道文件:大小永远为0;

4、有名管道实现进程间通信

又名命名管道;

代码实现:

a.c
//a.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <fcntl.h>
int main()
{
	int fd=open("fifi",O_WRONLY);
	assert(fd!=-1);
	printf("fd=%d\n",fd);
	write(fd,"hello",5);
	close(fd);
}

b.c
//b.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <fcntl.h>
int main()
{
	int fd=open("./fifi",O_RDONLY);
	assert(fd!=-1);
	printf("fd=%d\n",fd);
	char buff[128]={0};
	read(fd,buff,127);
	printf("read:%s\n",buff);
	close(fd);
}

5、管道的特点:

(1)管道必须读,写进程同时open,否则会阻塞;
(2)如果管道中没有数据,那么read就会阻塞;
(3)管道的写端关闭,读read返回值为0;
(4)管道打开的时候只有只读和只写方式,读写方式是未定义的;

6、将上面的代码改为循环

a.c

//a.c
#include <string.h>
#include <assert.h>
#include <fcntl.h>
int main()
{
	int fd=open("fifi",O_WRONLY);
	assert(fd!=-1);
	while(1)
	{
		printf("input:\n");
		char buff[128]={0};
		fgets(buff,128,stdin);
		if(strncmp(buff,"end",3)==0)
		{
			break;
		}
		write(fd,buff,strlen(buff));
	}
	close(fd);
}

b.c

//b.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <fcntl.h>
int main()
{
	int fd=open("./fifi",O_RDONLY);
	assert(fd!=-1);
	printf("fd=%d\n",fd);
	while(1)
	{
		char buff[128]={0};
		if( read(fd,buff,127)==0)
		{
			break;
		}
		printf("read:%s\n",buff);
	}
	close(fd);
}

7、无名管道的介绍

使用pipe创建无名管道,只能进行父子间的通信;

pipe是一个系统调用

int pipe(int fds[2]);
//pipe()成功返回 0,失败返回-1
//fds[0]是管道读端的描述符
// fds[1]是管道写端的描述符
//规定

代码演示:

父进程写入数据,子进程读取数据;

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
int main()
{
	int fd[2];
	assert(pipe(fd)!=-1);
	pid_t pid=fork();//先open,再frok,父子进程共享打开的文件描述符
	assert(pid!=-1);
	if(pid==0)
	{
		close(fd[1]);
		char buff[128]={0};
		read(fd[0],buff,127);
		printf("child read:%s\n",buff);
		close(fd[0]);
	}
	else
	{
		close(fd[0]);
		write(fd[1],"hello",5);
		close(fd[1]);
	}
	exit(0);
}

8、管道的特点:

(1)管道必须读,写进程同时open,否则会阻塞;
(2)如果管道中没有数据,那么read就会阻塞;
(3)管道的写端关闭,读read返回值为0;
(4)管道打开的时候只有只读和只写方式,读写方式是未定义的;
(5)管道是半双工的(某一时刻只能选择一个方向)(面试重点)、(通信方式有单工,半双工,全双工)
(6)无论有名还是无名,写入管道的数据都在内存中(面试重点)
(7)有名管道和无名管道的区别:(面试重点)
有名可以在任意进程间通信
无名主要在父子进程间通信
(8)管道的读端关闭,写会产生异常(发送信号SIGPIPE)(可以改变信号的响应方式验证一下)

9、管道的实现

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值