linux编程之pipe()函数

14 篇文章 1 订阅

以下内容是简摘自:https://blog.csdn.net/bit_clearoff/article/details/55105816

作者:_stark 原文章很棒。

一、管道的创建

#include<unistd.h>
pipe(int fd[2]);

它由输出型参数fd返回两个文件描述符,fd[0]为读而打开,fd[1]为写而打开,fd[1]的输出是fd[0]的输入,当管道创建成功后pipe函数返回0,如果创建失败则返回-1,fd[0]和fd[1]之间的关系如下图:
在这里插入图片描述


二、如何通过pipe进行通信

上面我们在单个进程中建立了管道,但是实际上,单个进程中的管道是没有什么用的,通常,进程会先调用pipe函数产生管道,接着调用fork()函数,fork函数会将父进程的相关数据结构继承到子进程中,这样就使子进程中的文件描述符表中的fd[0]和fd[1]指向父进程所指向的管道文件,这样就能实现两个进程之间的通信了。上面的过程如下图:
在这里插入图片描述


三、利用pipe通信的相关规则

对于一个从子进程到父进程的管道(子进程写,父进程读),父进程关闭fd[1],子进程关闭fd[0],当管道的一段被关闭后(在上面的基础上关闭管道的一端)下列规则起作用:

1、当读一个写端已经被关闭的管道时
在所有的数据都被读取后,read返回0(read返回0表示已经读到文件结束符);

2、如果写一个读端已经被关闭的管道
则会产生相关信号对写段的进程进行终止,如果忽略该信号或捕捉该信号并从处理程序返回,则write会返回-1,errno会设置为EPIPE;

3、如果管道的读端和写端都没有关闭,但是管道的写端没有再向管道写数据了
这时如果管道中没有数据了,那么在此read进程会产生阻塞,直到管道中有数据了才读取数据并返回。

4、如果有指向管道读端的文件描述符没有关闭,而持有管道读端的没有从管道中读数据, 这时有进程向管道中写数据,如果管道被写满再向管道写数据是,再次write会导致进程阻塞,直到管道中有空间了才会继续向管道中写数据并返回。


四、测试代码雏形

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

int main()
{
	int fd[2];	//creat pipe
	if(pipe(fd) != 0)
	{
		perror("pipe");
		exit(1);
	}

	pid_t id = fork();

	if(id == 0)
	{
		printf("Child\n");
		sleep(2);

		const char* msg = "Hello.\n";
		close(fd[0]);
		int count = 3;
		while(count --)
		{
			printf("child is writing...\n");
			ssize_t size = write(fd[1], msg, strlen(msg));
			printf("size: %ld\n", size);
			sleep(1);
		}
		close(fd[1]);
		exit(0);
	}

	else
	{
		//father ---> read fd[0]
		printf("Father\n");
		sleep(2);
		close(fd[1]);
		char buf[1024];
		int count = 3;
		while(1)
		{
			printf("Father is reading...\n");
			ssize_t len = read(fd[0], buf, 1024);
			if(len > 0)
			{
				buf[len] = '\0';
				printf("child say : %s", buf);
			}
			else if(len == 0)
			{
				printf("Read the end of pipe\n");
				break;
			}
			else 
			{
				perror("read");
				exit(1);
			}
		}
		close(fd[0]);
		int status = 0;
		pid_t _pid = waitpid(id, &status, 0);
		if(_pid == id)
		{
			printf("Wait sucess for child\n");
			printf("Exit code: %d, Exit signal: %d\n", (status>>8)&0xff, status&0xff);
		}
		else
			perror("wait");
		exit(0);
	}
	return 0;
}

运行结果:
在这里插入图片描述

  • 0
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值