小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

Shell:管道與重定向

 520jefferson 2020-12-11

轉自:TOMORROW

鏈接:https:///A8vpQE

對shell有一定了解的人都知道,管道和重定向是 Linux 中非常實用的 IPC 機制。
在shell中,我們通常使用符合'|’來表示管道,符號'>’和'<’表示重定向。
那么管道和重定向的真實含義(定義)又是什么呢?

管道

管道的定義

管道就是一個進程與另一個進程之間通信的通道,它通常是用作把一個進程的輸出通過管道連接到另一個進程的輸入。

它是半雙工運作的,想要同時雙向傳輸需要使用兩個管道。

管道又可以分為匿名管道和命名管道,而shell中使用到的是匿名管道,所以本文僅描述匿名管道。

例如命令ls | grep main.c,使用了管道來連接了兩條命令來執(zhí)行,能夠快速地讓我們知道當前目錄下是否有 main.c 文件。

管道的本質(zhì)是內(nèi)存中的緩沖區(qū),可以看作是打開到內(nèi)存中的文件。

所以需要使用兩個文件描述符來索引它,一個表示讀端,一個表示寫端。

并且規(guī)定,數(shù)據(jù)只能從讀端讀取、只能往寫端寫入。

創(chuàng)建管道

使用函數(shù)pipe()可以創(chuàng)建匿名管道,需要包含頭文件 unistd.h,示例代碼:

int fd[2];
pipe(fd);

首先創(chuàng)建一個 2 個元素的整型數(shù)組,然后將該數(shù)組作為pipe()的參數(shù),pipe()執(zhí)行成功后,數(shù)組元素 fd[0]的值就會變成所創(chuàng)建的管道的讀端的文件描述符,fd[1]就會變成寫端的文件描述符。

至此管道就算創(chuàng)建成功了。

把管道作為標準輸入輸出

管道創(chuàng)建成功后,就可以直接使用 read()和 write()函數(shù)對管道進行數(shù)據(jù)的讀寫。

而因為shell中都是使用標準輸入輸出對管道進行讀寫的,例如ls | grep main.c就是將 ls 的標準輸出寫到了管道寫端,而 grep 的標準輸入則從管道讀端讀取,所以本文也只描述此方法。

示例代碼如下:

int fd[2];
pipe(fd);
pid=fork();

if(0==pid) //execute next command in child process
{
dup2(fd[0],0);//redirect standard input to pipe(read)
close(fd[0]);
close(fd[1]);

if(0!=execvp(cmd0[0],cmd0))
printf('No such command!\n');
exit(EXIT_SUCCESS);
}
else //execute current command in current process
{
dup2(fd[1],1);//redirect standard output to pipe(write)
close(fd[0]);
close(fd[1]);

if(0!=execvp(cmd1[0],cmd1))
printf('No such command!\n');

exit(EXIT_SUCCESS);
}
  • 首先是創(chuàng)建一個管道,然后創(chuàng)建子進程,子進程會繼承這一個管道,也就保證了父進程與子進程操作的是同一個管道(管道的繼承與普通變量不同)。

    如果我們希望在子進程中執(zhí)行管道的讀端的程序例如ls | grep main.c中的grep main.c;在父進程中執(zhí)行管道的寫端的程序,例如ls | grep main.c中的ls。

  • 在子進程中,先調(diào)用dup2(fd[0],0);此函數(shù)就是將標準輸入的文件描述符 0,指向了管道的讀端。

文件描述符,本質(zhì)是非負整數(shù),通常是小整數(shù);它是一個索引,通過該索引可以找到對應的文件。

例如,標準輸入、標準輸出、標準錯誤的文件描述符默認是 0、1、2 。當進程需要從標準輸入中讀取數(shù)據(jù)時,就會通過 0 索引找到標準輸入所對應的內(nèi)存緩沖區(qū)來讀取數(shù)據(jù)。

  • 假設此時管道讀端的文件描述符為 3、寫端文件描述符為 4 。

  • 調(diào)用dup2(fd[0],0),實際上就是將文件描述符 3 指向的文件表項賦值給了文件描述符 0,而文件描述符 0 正是進程默認的標準輸入。

    所以此時,當進程需要從標準輸入讀取數(shù)據(jù)時,進程就會通過文件描述符 0 來找到管道讀端所對應內(nèi)存緩沖區(qū)。

  • 從而實現(xiàn)了通過標準輸入來讀取管道的數(shù)據(jù),也可以說是,將管道的讀端重定向到了標準輸入。管道的寫端與標準輸入的關系也與此類似,此處不再贅述。

  • 調(diào)用dup2(fd[0],0)之后還需要調(diào)用close()函數(shù)將管道原有的文件描述符關閉,關閉的意思是文件描述符 3 和 4 不再索引到管道或者其他文件,也就是說此時使用 read 函數(shù)從文件描述符 3 中是讀取不到管道的數(shù)據(jù)的了,并不是說關閉管道的意思。

  • 完成管道的設置之后,就可以通過 exec 族函數(shù)來執(zhí)行外部命令了。

    需要注意的是,調(diào)用 exec 族函數(shù)并不會把管道這種 IPC 資源覆蓋或者重新初始化。

文件重定向

文件重定向其實與上面管道重定向到標準輸入輸出很類似,甚至可以直接采用上面所說的方法來實現(xiàn)。但是此處將講述一種更加簡潔的方法實現(xiàn)。

實例代碼如下:

char fileName[20]='out.txt';
freopen(fileName,'w',stdout);//redirect stdout to fileName

以上兩行簡單的代碼就實現(xiàn)了,將該進程的標準輸出重定向到了文件 out.txt ,甚至一行就可以實現(xiàn)。

執(zhí)行以上代碼后,當前進程的所有標準輸出,也就是 printf()之類的輸出全都會被寫到文件 out.txt,顯示屏將不會有輸出。

而將進程的標準輸入重定向到文件 in.txt 的代碼如下:

char fileName[20]='in.txt';
freopen(fileName,'r',stdin);//redirect stdin to fileName
其中的核心函數(shù)就是freopen()

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內(nèi)容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多