Linux下进程间通信——管道

一、进程间通信

  • 进程间通信的方式(ipc机制):管道、信号量、消息队列、共享内存、套接字。
  • 利用我们学过的知识完成进程间通信用到的操作:一个程序像文件中写数据,用另一个文件来读取。
    在这里插入图片描述
    由此,如果我们能将数据写入内存中,效率将会高很多。所以我们可以用管道的方式来进行进程间通信。

1.进程间通信——管道

优点

  • 管道是一种直接想内存中写入数据和读取数据的工具。
  • 管道是可以让读写数据进行同步控制的一种工具。

注意

  1. 管道分为有名管道和无名管道。
  2. 写入管道的数据存储在内存中。
  3. 有名管道和无名管道的区别:有名管道可以在任意两个进程间通信,无名管道只能在父子进程间通信。
  4. 管道是一个半双工的通信方式。

(1)有名管道的创建

管道的创建有两种方式:命令式和函数式。
命令式创建管道的方式:mkfifo+管道名mkfifo fifo
在这里插入图片描述
图中可以看到管道文件的大小为0,无论管道中写没写数据,管道文件的大小都是0。因为管道是向内存中写数据的。

(2)有名管道的操作

管道的操作和文件的操作是相似的,都可以用读写操作对管道进行操作。

写操作
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<assert.h>
#include<fcntl.h>

int main()
{
	int fdw=open("fifo",O_ERONLY);   
	assert(fdw!=-1);//正常情况下,fdr=3;
	printf("dfw=%d\n",fdw);

	while(1)
	{
		char buff[128]={0};
		fgets(buff,128,stdin);
		if((strncmp(buff,"end",3)==0)
		{
			break;
		}
		write(fdw,buff,strlen(buff));
	}
	close(fdw);
}
读操作
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<assert.h>
#include<fcntl.h>

int main()
{
	int fdr=open("fifo",O_RDONLY);   //有可能阻塞住;
	assert(fdr!=-1);//正常情况下,fdr=3;
	printf("dfr=%d\n",fdr);

	while(1)
	{
		char buff[128]={0};
		int n=read(fdr,buff,127);
		if(n==0)
		{
			break;
		}
		printf("buff=%s\n",buff);
	}
	close(fdr);
}
发生阻塞和关闭程序的几种情况
  1. 正常情况下打开文件fdr和fdw的值都为3,因为0代表标准输入,1代表标准输出,2代表标准错误输出。
  2. 有名管道在读端打开的过程中有可能发生阻塞,因为有名管道是要两个进程同时打开的,并且一个进程以写的方式,一个进程以读的方式,如果只读取的话没有意义。
  3. 在读文件过程中,如果没有数据也会发生阻塞。
  4. 当管道满时,写端也会发生阻塞,等待数据读取之后再进行写入。
  5. 如果写端关闭,读端的返回值为0,读端也会关闭。

几种异常情况

  • 当正在通过管道执行的读写程序中,写程序强制退出程序之后,读程序也会退出。
  • 当正在通过管道执行的读写程序中,读程序强制退出程序之后,写程序写入数据时,也会直接退出。因为出现异常,接受SIGPIGE信号,关闭了写端。

2.无名管道的创建

通过命令:pipe(int pipefd[2]) //pipefd[0]是读端,pipefd[1]是写端这是规定。
无名管道的图解:
在这里插入图片描述

(1)无名管道的操作

注意:fork和获得描述符操作不可更改顺序,因为只有在有了读写描述符之后fork,子进程才也有权限。

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<assert.h>
#include<fcntl.h>

int main()
{
	int fd[2];
	int rse=pipe(fd);    //此操作之后获得读写描述符;
	assert(rse!=-1);

	pid_t pid=fork();
	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);
}

3.管道读取数据图

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值