利用传统进程通信——管道实现父子进程的信息传递


题目描述

编写一个程序,利用管道实现父子进程的通信,父进程向子进程发送信息,由子进程输出显示。

代码实现

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>  //管道功能所在的头文件
#include <sys/types.h>  //wait函数所在的头文件
#include <sys/wait.h>  //wait函数所在的头文件

#define MAXLINE 80

int main()
{
    
    
	int n;  //所发送消息的长度
	int fd[2];  //管道读写端口
	pid_t pid;  //进程号
	char line[MAXLINE];  //消息缓冲区
	if(pipe(fd) < 0) //建立管道不成功
	{
    
    
		perror("pipe");
		exit(1); //有错误型的退出
	}
	if((pid = fork()) < 0) //建立子进程不成功
	{
    
    
		perror("fork:");
		exit(1);
	}
	else  //成功建立子进程
	{
    
    	
		if(pid > 0)  //父进程
		{
    
    
			close(fd[0]);  //关闭读端
			write(fd[1],"I love CMY!\n", 12);  
			//把"I love CMY!\n"长度为12的字符送到管道写端口fd[1]
			close(fd[1]);   
			//关闭写端,老师是要求写完之后要关闭的,但是我试了试不写也没啥问题……
			wait(NULL);  //父进程等待子进程结束
		}
		else  //子进程
		{
    
    
			close(fd[1]);  //关闭写端
			n = read(fd[0], line, MAXLINE);  
			//从管道读端口fd[0]把长度为MAXLINE的字符送到line中
			write(STDOUT_FILENO, line, n);  
			//将line中长度为n的字符写到标准输出设备(即屏幕上)
			close(fd[0]);  
			//同上,关闭读端,老师是要求写完之后要关闭的,但是我试了试不写也没啥问题……
		}	
	}
	return 0;
}

关于pipe函数

功能:创建一个普通管道
在这里插入图片描述


关于读写操作

在这里插入图片描述

也就是说读/写操作的流程是:

  • 关闭读/写端
  • 进行写/读操作
  • 写/读完关闭写/读端

关于读写端口

为什么fd[0]是读,fd[1]是写,能不能颠倒过来?

一般来讲,我们常说:读写读写,不说写读写读,因为不顺口。所以0是读,1是写,你要是想颠倒也是可以的,只要你自己记得住就行。


关于wait函数

在这里插入图片描述
在这里插入图片描述

功能:

父进程一旦调用了wait就立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸的子进程,wait就会收集这个子进程的信息,并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。

注意:

当父进程没有用wait()函数等待已终止的子进程时,子进程就会进入一种无父进程的状态,此时子进程就是僵尸进程。
如果先终止父进程,子进程依然会继续正常进行,只是它将由init进程(PID 1)继承,当子进程终止时,init进程捕获这个状态。


关于本题

其实本题就是管道和父子进程的相结合,重点是理解fork()之后父子进程的并行执行,以老师PPT中的例题为例:在这里插入图片描述
在这里插入图片描述

子进程执行的是 val == 0 的内容,而父进程执行的是 val > 0 的内容,子进程创建的时候完全复制了父进程的资源,可以理解为自 val = fork() 之后,代码就被copy了一份一摸一样的,父进程执行被copy的,子进程执行copy的。而对于本题而言,从

if((pid = fork()) < 0) //建立子进程不成功

开始,子进程copy了后面的代码,而且继承了父进程之前的资源,如变量等,然后在接下来的代码中根据pid的不同进入不同的代码段。

值得注意的是,本题代码中先处理的是父进程的写操作,再处理的是子进程的读操作,那如果反过来先写子进程的读操作,再写父进程的写操作,代码还可以正常运行吗?

经过测试,答案是可以,因为我们刚讲过他们俩是并行执行嘛,但是根据先写进去再读出来比较符合人类的思维,所以我们本题就先写父进程的写操作,再处理子进程的读操作~

证据如下图:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Jormungand_V/article/details/109581638