在考研複習時候遇到的問題,很想寫下來,雖然時間已經很緊張,但是在我們師生的問答互助之間,學術似乎更顯神聖了,比起骯髒的考試製度來說……(請配合代碼看)
問題表述:
在minix裏面,使用如下命令會使系統在2個進程之間建立管道用來進行進程之間的通訊:
#cat file1 file2|sort
那麼它的作用顯而易見,列出file1和2的內容並排序放入另一文件。那麼在內核當中是如何實現的呢?道理很簡單,這條指令被shell接受以後會產生一個系統調用sys_call,名字是PIPE。調用的格式首先是使用庫函數(minix的系統調用使用庫函數)pipe(&fd[0]);其中fd[ ]這個數組的聲明是這樣子的:
int fd[2]
它是文件引用的數組,由於在2個進程當中,所以對文件使用2個引用定向到不同進程的輸入輸出就可以了。那麼pipe建好了,其內容就是一個內存塊m(實際上是消息機制的消息結構塊,m_i1,m_i2),m的2個域賦值給fd的2個cell,當然一讀一寫。好,然後我們開始fork系統調用,這次我們會得到2個進程,一對父子。下面我們假設從父親發出信息,兒子取消息。我們會怎麼做呢?
問題解決:
1.我們會關閉管道的讀寫,以備下面給父子分配讀寫引用
2.父子進程會由管道方向安排讀寫的放棄,例如,在這裏,父親放棄讀引用STD_OUTPUT,兒子自然放棄
STD_INPUT,注意,這個時候有一個關鍵問題,也是我誤解的問題,文件下面會使用dup函數重新連接2個
引用,機制是選擇文件描述符的整數值最低的1個。那麼文件描述符究竟是怎麼分配的呢?經過林老師的指點
發現在每個進程有3個文件引用0-stdin,1-stdout,2-stderr,那麼放棄1的父親和放棄0的兒子就會分別
將新的文件引用dup到1和0上面
3.自然就是dup掛接引用了。注意dup裏面使用了fcntl所以你將看到這個連接的方式就是從0開始找到最小的
空閒的描述連接他。至此pipe就建立了。特嫩鮑姆說他的minix的pipe最大時4096+3072,並且可以自行分配
空間大小,如果溢出,就會在loop當中死鎖,這是顯然的,呵呵。
#include STD_INPUT 0
#include STD_OUTPUT 1
pipeline(process1,porcess2)
char *process1,*process2;//舊的C標準參數聲明吧~~~~~
{
int fd[2]; //存儲讀寫的文件引用
pipe(&fd[0]);//create a pipe
if(fork()!=0){
//父進程的語句
close(fd[0]); //關閉管道讀
close(STD_OUTPUT);
dup(fd[1]); //標準輸出指向fd[1]
/*===============================================================================
/*這裏是dup的原形*/
PUBLIC int dup(fd)
{
return(fcntl(fd,F_DUPFD,0));
}
==============================================================================*/
close(fd[1]); //不再需要描述符
execl(process1,process1,0);
}
else
{
//子進程的代碼
close(fd[1]);
close(STD_INPUT);
dup(fd[0]);
close(fd[0]);
execl(process2,process2,0);
}
}
//===========================================================================================
copyright of all code used in this text belongs to Dr.Andrew S. Tanenbaum
thank you very much.
鳴謝:我的老師 林豐波先生,感謝他在百忙之中回答我的問題。
最後,祝願包括自己在內天下考研同學成功~~~~~