管道实现父子进程的信息传递(一)【fork函数、pipe函数、write/read操作、wait函数】
文章目錄
- 題目描述
- 代碼實現(xiàn)
- 關(guān)于pipe函數(shù)
- 關(guān)于讀寫操作
- 關(guān)于讀寫端口
- 關(guān)于wait函數(shù)
- 功能:
- 注意:
- 關(guān)于fork函數(shù)
題目描述
編寫一個程序,利用管道實現(xiàn)父子進程的通信,父進程向子進程發(fā)送信息,由子進程輸出顯示。
代碼實現(xiàn)
#include <stdio.h> #include <stdlib.h> #include <unistd.h> //管道功能所在的頭文件 #include <sys/types.h> //wait函數(shù)所在的頭文件 #include <sys/wait.h> //wait函數(shù)所在的頭文件#define MAXLINE 80int main() {int n; //所發(fā)送消息的長度int fd[2]; //管道讀寫端口pid_t pid; //進程號char line[MAXLINE]; //消息緩沖區(qū)if(pipe(fd) < 0) //建立管道不成功{perror("pipe");exit(1); //有錯誤型的退出}if((pid = fork()) < 0) //建立子進程不成功{perror("fork:");exit(1);}else //成功建立子進程{ if(pid > 0) //父進程{close(fd[0]); //關(guān)閉讀端write(fd[1],"I love CMY!\n", 12); //把"I love CMY!\n"長度為12的字符送到管道寫端口fd[1]close(fd[1]); //關(guān)閉寫端,老師是要求寫完之后要關(guān)閉的,但是我試了試不寫也沒啥問題……wait(NULL); //父進程等待子進程結(jié)束}else //子進程{close(fd[1]); //關(guān)閉寫端n = read(fd[0], line, MAXLINE); //從管道讀端口fd[0]把長度為MAXLINE的字符送到line中write(STDOUT_FILENO, line, n); //將line中長度為n的字符寫到標(biāo)準(zhǔn)輸出設(shè)備(即屏幕上)close(fd[0]); //同上,關(guān)閉讀端,老師是要求寫完之后要關(guān)閉的,但是我試了試不寫也沒啥問題……} }return 0; }關(guān)于pipe函數(shù)
功能:創(chuàng)建一個普通管道
關(guān)于讀寫操作
也就是說讀/寫操作的流程是:
- 關(guān)閉讀/寫端
- 進行寫/讀操作
- 寫/讀完關(guān)閉寫/讀端
關(guān)于讀寫端口
為什么fd[0]是讀,fd[1]是寫,能不能顛倒過來?
一般來講,我們常說:讀寫讀寫,不說寫讀寫讀,因為不順口。所以0是讀,1是寫,你要是想顛倒也是可以的,只要你自己記得住就行。
關(guān)于wait函數(shù)
功能:
父進程一旦調(diào)用了wait就立即阻塞自己,由wait自動分析是否當(dāng)前進程的某個子進程已經(jīng)退出,如果讓它找到了這樣一個已經(jīng)變成僵尸的子進程,wait就會收集這個子進程的信息,并把它徹底銷毀后返回;如果沒有找到這樣一個子進程,wait就會一直阻塞在這里,直到有一個出現(xiàn)為止。
注意:
當(dāng)父進程沒有用wait()函數(shù)等待已終止的子進程時,子進程就會進入一種無父進程的狀態(tài),此時子進程就是僵尸進程。
如果先終止父進程,子進程依然會繼續(xù)正常進行,只是它將由init進程(PID 1)繼承,當(dāng)子進程終止時,init進程捕獲這個狀態(tài)。
關(guān)于fork函數(shù)
其實本題就是管道和父子進程的相結(jié)合,重點是理解fork()之后父子進程的并行執(zhí)行,以老師PPT中的例題為例:
子進程執(zhí)行的是 val == 0 的內(nèi)容,而父進程執(zhí)行的是 val > 0 的內(nèi)容,子進程創(chuàng)建的時候完全復(fù)制了父進程的資源,可以理解為自 val = fork() 之后,代碼就被copy了一份一摸一樣的,父進程執(zhí)行被copy的,子進程執(zhí)行copy的。而對于本題而言,從
if((pid = fork()) < 0) //建立子進程不成功開始,子進程copy了后面的代碼,而且繼承了父進程之前的資源,如變量等,然后在接下來的代碼中根據(jù)pid的不同進入不同的代碼段。
值得注意的是,本題代碼中先處理的是父進程的寫操作,再處理的是子進程的讀操作,那如果反過來先寫子進程的讀操作,再寫父進程的寫操作,代碼還可以正常運行嗎?
經(jīng)過測試,答案是可以,因為我們剛講過他們倆是并行執(zhí)行嘛,但是根據(jù)先寫進去再讀出來比較符合人類的思維,所以我們本題就先寫父進程的寫操作,再處理子進程的讀操作~
證據(jù)如下圖:
總結(jié)
以上是生活随笔為你收集整理的管道实现父子进程的信息传递(一)【fork函数、pipe函数、write/read操作、wait函数】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 是否记得儿时神作?《数码宝贝》第一部战力
- 下一篇: 【超级详细的小白教程】Hexo 搭建自己