进程间通信——管道

本文详细介绍了如何使用管道函数实现父子进程间的通信,包括函数原型、操作流程及示例代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

用管道来进行进程间通信是通过pipe函数,管道只能支持父子进程或有公共祖先的进程之间通信。

pipe函数原型:

#include <unistd.h>
int pipe (int fd[2]);
该函数被调用后,会通过fd数组传出两个文件描述符fd[0]和fd[1],其中fd[0]为读而打开,fd[1]为写而打开。从fd[0]中读的数据,就是往fd[1]中写的数据。

当父进程调用fork后,子进程继承了父进程的文件描述符fd[0]和fd[1]。这样就建立了父子进程之间的IPC通道。父进程往fd[1]中写数据时,子进程就可以通过fd[0]读到。

下面代码描述的是上图的流程

父进程

1:fork出自进程

2:从标准输入读入数据

3:将数据通过fd[1]写入管道

子进程

1:通过fd[0]从管道读入数据

2:将数据写到标准输出

#include <stdio.h>
#include <unistd.h>

int main () {
	int buflen;
	char* buffer[1024];
	pid_t pid;
	int fd[2];

	if (pipe(fd) < 0) {
		printf ("pipe error\n");
		return 1;
	}
	if ((pid = fork()) < 0) {
		printf ("pipe error\n");
		return 1;
	}
	if (pid > 0) {       //father
		close (fd[0]);
		while ((buflen = read (STDIN_FILENO, buffer, 1024)) > 0) {
			write (fd[1], buffer, buflen);
		}
		return 0;
	}
	else {
		close (fd[1]);
		while ((buflen = read (fd[0], buffer, 1024)) > 0) {
			write (STDOUT_FILENO, buffer, buflen);
		}
		return 0;
	}
}


 

图中1 2 3 4 5 6分别为:

1是父进程标准输入(STDIN_FILENO)

2是父进程的fd1[1]

3是子进程的fd1[0],同时也是子进程的标准输入

4是子进程的fd2[1],同时也是子进程的标准输出

5是父进程的fd2[0]

6是父进程的标准输出(STDOUT_FILENO)

父进程流程:

1:fork创建子进程

2:主循环中不断从标准输入中读取数据

3:通过fd1[1]将读入的数据写入管道

4:通过fd2[0]从管道中读入数据

5:将数据写到标准输出

子进程流程:

1:调用dup2函数复制文件描述符fd1[0]为标准输入

2:复制文件描述符fd2[1]为标准输出

3:调用execl函数执行新的程序coproces,进入coproces主循环,该程序由coproces.c编译而成,功能是英文字符大小写转换。

4:在coproces主循环中不断从标准输入读取数据

5:将数据中英文字符大小写转换后写入标准输出。

// coproces.c

#include <stdio.h>
#include <unistd.h>

int main () {
	char buffer[1024];
	int buflen;
	while ((buflen = read (STDIN_FILENO, buffer, 1024)) > 0) {
		int i  = 0;
		for (i = 0; i < buflen; ++i) {
			if (isupper (buffer[i])) {
				buffer[i] = tolower (buffer[i]);
			}
			else if (islower (buffer[i])) {
				buffer[i] = toupper (buffer[i]);
			}
		}
		write (STDOUT_FILENO, buffer, buflen);
	}
}


 // main.c

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main () {
	pid_t pid;
	int fd1[2], fd2[2];
	int buflen;
	char buffer[1024];
	
	if (pipe (fd1) < 0 || pipe (fd2) < 0) {
		printf ("pipe error!\n");
		exit (1);
	}
	if ((pid = fork()) < 0) {
		printf ("fork error !\n");
		exit (1);
	}
	
	if (!pid) {       // child process
		close (fd1[1]); // read only
		close (fd2[0]); // write only
		if (STDIN_FILENO != fd1[0]) {
			if(STDIN_FILENO !=dup2 (fd1[0], STDIN_FILENO)) {
				printf ("error!\n");
				exit (1);
			}
			close (fd1[0]);
		}
		if (STDOUT_FILENO != fd2[1]) {
			if(STDOUT_FILENO != dup2 (fd2[1], STDOUT_FILENO)) {
				printf ("error!\n");	
				exit (1);
			}
			close (fd2[1]);
		}
		if (execl ("./coproces", "coproces",(char*)0) < 0) {
			printf ("execl error\n");
			exit (1);
		}
	}
	// parent process
	close (fd1[0]);  //write only
	close (fd2[1]);  //read only
	while ((buflen = read (STDIN_FILENO, buffer, 1024)) > 0) {
		if (buflen != write (fd1[1], buffer, buflen)) {
			printf ("write to fd1 error!\n");
			exit (1);
		}
		buflen = read (fd2[0], buffer, 1024);
		write (STDOUT_FILENO, buffer, buflen);
	}
	exit (0);	
}


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值