青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

C++ Coder

HCP高性能計(jì)算架構(gòu),實(shí)現(xiàn),編譯器指令優(yōu)化,算法優(yōu)化, LLVM CLANG OpenCL CUDA OpenACC C++AMP OpenMP MPI

C++博客 首頁(yè) 新隨筆 聯(lián)系 聚合 管理
  98 Posts :: 0 Stories :: 0 Comments :: 0 Trackbacks

http://www.pcdog.com/edu/linux/13/11/y237288.html

管道技術(shù)是Linux的一種基本的進(jìn)程間通信技術(shù)。在本文中,我們將為讀者介紹管道技術(shù)的模型,匿名管道和命名管道技術(shù)的定義和區(qū)別,以及這兩種管道的創(chuàng)建方法。同時(shí),闡述如何在應(yīng)用程序和命令行中通過(guò)管道進(jìn)行通信的詳細(xì)方法。

    一、管道技術(shù)模型 

    管道技術(shù)是Linux操作系統(tǒng)中歷來(lái)已久的一種進(jìn)程間通信機(jī)制。所有的管道技術(shù),無(wú)論是半雙工的匿名管道,還是命名管道,它們都是利用FIFO排隊(duì)模型來(lái)指揮進(jìn)程間的通信。對(duì)于管道,我們可以形象地把它們當(dāng)作是連接兩個(gè)實(shí)體的一個(gè)單向連接器。例如,請(qǐng)看下面的命令:
  

ls -1 | wc -l


    該命令首先創(chuàng)建兩個(gè)進(jìn)程,一個(gè)對(duì)應(yīng)于ls –1,另一個(gè)對(duì)應(yīng)于wc –l。然后,把第一個(gè)進(jìn)程的標(biāo)準(zhǔn)輸出設(shè)為第二個(gè)進(jìn)程的標(biāo)準(zhǔn)輸入(如圖1所示)。它的作用是計(jì)算當(dāng)前目錄下的文件數(shù)量。

Linux下的管道編程技術(shù)(圖一)

點(diǎn)擊查看大圖

 

圖1:管道示意圖 



    如上圖所示,前面的例子實(shí)際上就是在兩個(gè)命令之間建立了一根管道(有時(shí)我們也將之稱為命令的流水線操作)。第一個(gè)命令ls執(zhí)行后產(chǎn)生的輸出作為了第二個(gè)命令wc的輸入。這是一個(gè)半雙工通信,因?yàn)橥ㄐ攀菃蜗虻摹蓚€(gè)命令之間的連接的具體工作,是由內(nèi)核來(lái)完成的。下面我們將會(huì)看到,除了命令之外,應(yīng)用程序也可以使用管道進(jìn)行連接。

二、信號(hào)和消息的區(qū)別

    我們知道,進(jìn)程間的信號(hào)通信機(jī)制在傳遞信息時(shí)是以信號(hào)為載體的,但管道通信機(jī)制的信息載體是消息。那么信號(hào)和消息之間的區(qū)別在哪里呢? 

    首先,在數(shù)據(jù)內(nèi)容方面,信號(hào)只是一些預(yù)定義的代碼,用于表示系統(tǒng)發(fā)生的某一狀況;消息則為一組連續(xù)語(yǔ)句或符號(hào),不過(guò)量也不會(huì)太大。在作用方面,信號(hào)擔(dān)任進(jìn)程間少量信息的傳送,一般為內(nèi)核程序用來(lái)通知用戶進(jìn)程一些異常情況的發(fā)生;消息則用于進(jìn)程間交換彼此的數(shù)據(jù)。 

    在發(fā)送時(shí)機(jī)方面,信號(hào)可以在任何時(shí)候發(fā)送;信息則不可以在任何時(shí)刻發(fā)送。在發(fā)送者方面,信號(hào)不能確定發(fā)送者是誰(shuí);信息則知道發(fā)送者是誰(shuí)。在發(fā)送對(duì)象方面,信號(hào)是發(fā)給某個(gè)進(jìn)程;消息則是發(fā)給消息隊(duì)列。在處理方式上,信號(hào)可以不予理會(huì);消息則是必須處理的。在數(shù)據(jù)傳輸效率方面,信號(hào)不適合進(jìn)大量的信息傳輸,因?yàn)樗男什桓撸幌㈦m然不適合大量的數(shù)據(jù)傳送,但它的效率比信號(hào)強(qiáng),因此適于中等數(shù)量的數(shù)據(jù)傳送。 

    三、管道和命名管道的區(qū)別 

    我們知道,命名管道和管道都可以在進(jìn)程間傳送消息,但它們也是有區(qū)別的。 

    管道技術(shù)只能用于連接具有共同祖先的進(jìn)程,例如父子進(jìn)程間的通信,它無(wú)法實(shí)現(xiàn)不同用戶的進(jìn)程間的信息共享。再者,管道不能常設(shè),當(dāng)訪問(wèn)管道的進(jìn)程終止時(shí),管道也就撤銷。這些限制給它的使用帶來(lái)不少限制,但是命名管道卻克服了這些限制。 

    命名管道也稱為FIFO,是一種永久性的機(jī)構(gòu)。FIFO文件也具有文件名、文件長(zhǎng)度、訪問(wèn)許可權(quán)等屬性,它也能像其它Linux文件那樣被打開(kāi)、關(guān)閉和刪除,所以任何進(jìn)程都能找到它。換句話說(shuō),即使是不同祖先的進(jìn)程,也可以利用命名管道進(jìn)行通信。 

    如果想要全雙工通信,那最好使用Sockets API。下面我們分別介紹這兩種管道,然后詳細(xì)說(shuō)明用來(lái)進(jìn)行管道編程的編程接口和系統(tǒng)級(jí)命令。

四、管道編程技術(shù) 

    在程序中利用管道進(jìn)行通信時(shí),根據(jù)通信主體大體可以分為兩種情況:一種是具有共同祖先的進(jìn)程間的通信,比較簡(jiǎn)單;另一種是任意進(jìn)程間通信,相對(duì)較為復(fù)雜。下面我們先從較為簡(jiǎn)單的進(jìn)程內(nèi)通信開(kāi)始介紹。 

    1. 具有共同祖先的進(jìn)程間通信管道編程 

    為了了解管道編程技術(shù),我們先舉一個(gè)例子。在這個(gè)例中,我們將在進(jìn)程中新建一個(gè)管道,然后向它寫(xiě)入一個(gè)消息,管道讀取消息后將其發(fā)出。代碼如下所示: 

    示例代碼1:管道程序示例 

1: #include <unistd.h> 2: #include <stdio.h> 3: #include <string.h> 4: 5: #define MAX_LINE 80 6: #define PIPE_STDIN 0 7: #define PIPE_STDOUT 1 8: 9: int main() 10: ...{ 11: const char *string=...{"A sample message."}; 12: int ret, myPipe[2]; 13: char buffer[MAX_LINE+1]; 14: 15: /**//* 建立管道 */ 16: ret = pipe( myPipe ); 17: 18: if (ret == 0) ...{ 19: 20: /**//* 將消息寫(xiě)入管道 */ 21: write( myPipe[PIPE_STDOUT], string, strlen(string) ); 22: 23: /**//* 從管道讀取消息 */ 24: ret = read( myPipe[PIPE_STDIN], buffer, MAX_LINE ); 25: 26: /**//* 利用Null結(jié)束字符串 */ 27: buffer[ ret ] = 0; 28: 29: printf("%s\n", buffer); 30: 31: } 32: 33: return 0; 34: }

   
    上面的示例代碼中,我們利用pipe調(diào)用新建了一個(gè)管道,參見(jiàn)第16行代碼。 我們還建立了一個(gè)由兩個(gè)元素組成的數(shù)組,用來(lái)描述我們的管道。我們的管道被定義為兩個(gè)單獨(dú)的文件描述符,一個(gè)用來(lái)輸入,一個(gè)用來(lái)輸出。我們能從管道的一端輸入,然后從另一端讀出。如果調(diào)用成功,pipe函數(shù)返回值為0。返回后,數(shù)組myPipe中存放的是兩個(gè)新的文件描述符,其中元素myPipe[1]包含的文件描述符用于管道的輸入,元素myPipe[0] 包含的文件描述符用于管道的輸出。

    在第21行代碼,我們利用write函數(shù)把消息寫(xiě)入管道。站在應(yīng)用程序的角度,它是在向stdout輸出。現(xiàn)在,該管道存有我們的消息,我們可以利用第24行的read函數(shù)來(lái)讀它。對(duì)于應(yīng)用程序來(lái)說(shuō),我們是利用stdin描述符從管道讀取消息的。read函數(shù)把從管道讀取的數(shù)據(jù)存放到buffer變量中。然后在buffer變量的末尾添加一個(gè)NULL,這樣就能利用printf函數(shù)正確的輸出它了。在本例中的管道可以利用下圖解釋:

Linux下的管道編程技術(shù)(圖二)

點(diǎn)擊查看大圖

 

圖2:示例代碼1中半雙工管道的示意圖

    這個(gè)例子中,通信是在具有共同祖先的進(jìn)程間發(fā)生的,即父進(jìn)程和子進(jìn)程通信。這樣做局限性太大,但我們只是用它來(lái)給讀者一個(gè)感性的認(rèn)識(shí)。接下來(lái),我們將介紹更為高級(jí)的進(jìn)程間的管道通信。

 2.進(jìn)程間通信管道編程 

    在利用管道技術(shù)進(jìn)行編程時(shí),處理要用到上面介紹的pipe函數(shù)外,還用到另外三個(gè)函數(shù),如下所示。

? pipe函數(shù):該函數(shù)用于創(chuàng)建一個(gè)新的匿名管道。

? dup函數(shù):該函數(shù)用于拷貝文件描述符。

? mkfifo函數(shù):該函數(shù)用于創(chuàng)建一個(gè)命名管道(fifo)。 

    當(dāng)然,在管道通信過(guò)程中還用到其它函數(shù),到時(shí)我們會(huì)加以介紹。需要注意的是,說(shuō)到底,管道無(wú)非就是一對(duì)文件描述符,因此任何能夠操作文件操作符的函數(shù)都可以使用管道。這包括但不限于這些函數(shù):select、read、write、 fcntl、freopen,等等。 

    2.1函數(shù)pipe 

    函數(shù)pipe用來(lái)建立一個(gè)新的管道,該管道用兩個(gè)文件描述符進(jìn)行描述。函數(shù)pipe的原型如下所示:

#include <unistd.h> int pipe( int fds[2] );

    當(dāng)調(diào)用成功時(shí),函數(shù)pipe返回值為0,否則返回值為-1。成功返回時(shí),數(shù)組fds被填入兩個(gè)有效的文件描述符。數(shù)組的第一個(gè)元素中的文件描述符供應(yīng)用程序讀取之用,數(shù)組的第二個(gè)元素中的文件描述符可以用來(lái)供應(yīng)用程序?qū)懭搿?nbsp;

    下面我們考察在一個(gè)包含多個(gè)進(jìn)程的應(yīng)用程序中的管道示例。在該程序中(見(jiàn)示例代碼2),第14行用于創(chuàng)建一個(gè)管道,然后進(jìn)程在第16行分叉,變成一個(gè)父進(jìn)程和一個(gè)子進(jìn)程。在子進(jìn)程中,我們嘗試從(在第18行建立的)管道的輸入描述符讀取,這時(shí)該進(jìn)程將被掛起,直到管道中有可以讀取的內(nèi)容為止。 

    讀完后,我們用NULL作為讀取的內(nèi)容的結(jié)束符,這樣的話,讀的這些內(nèi)容就能使用printf函數(shù)正確打印輸出了。父進(jìn)程先是利用存放在thePipe[1]中的“寫(xiě)文件標(biāo)識(shí)符”向管道寫(xiě)入測(cè)試字符串,然后就使用wait函數(shù)來(lái)等待子進(jìn)程退出。 

    在我們的這個(gè)程序中需要加以注意的是,我們的子進(jìn)程是如何繼承父進(jìn)程利用pipe函數(shù)建立的文件描述符的,以及如何利用該文件描述符進(jìn)行通信的。函數(shù)fork一旦執(zhí)行,子進(jìn)程會(huì)繼承父進(jìn)程的功能和管道的文件描述符,但對(duì)于內(nèi)核來(lái)說(shuō),父進(jìn)程和子進(jìn)程是平等的,它們是獨(dú)立運(yùn)行的。也就是說(shuō),兩個(gè)進(jìn)程分別具有單獨(dú)的內(nèi)存空間,它們正是通過(guò)pipe函數(shù)來(lái)互通有無(wú)的。

示例代碼2:演示兩個(gè)進(jìn)程間的管道模型的代碼 1: #include <stdio.h> 2: #include <unistd.h> 3: #include <string.h> 4: #include <wait.h> 5: 6: #define MAX_LINE 80 7: 8: int main() 9: ...{ 10: int thePipe[2], ret; 11: char buf[MAX_LINE+1]; 12: const char *testbuf=...{"a test string."}; 13: 14: if ( pipe( thePipe ) == 0 ) ...{ 15: 16: if (fork() == 0) ...{ 17: 18: ret = read( thePipe[0], buf, MAX_LINE ); 19: buf[ret] = 0; 20: printf( "Child read %s\n", buf ); 21: 22: } else ...{ 23: 24: ret = write( thePipe[1], testbuf, strlen(testbuf) ); 25: ret = wait( NULL ); 26: 27: } 28: 29: } 30: 31: return 0; 32: }



    需要注意的是,在這個(gè)示例程序中我們沒(méi)有說(shuō)明如何關(guān)閉管道,因?yàn)橐坏┻M(jìn)程結(jié)束,與管道有關(guān)的資源將被自動(dòng)釋放。盡管如此,為了養(yǎng)成一種良好的編程習(xí)慣,最好利用close調(diào)用來(lái)關(guān)閉管道的描述符,如下所示: 

ret = pipe( myPipe ); ... close( myPipe[0] ); close( myPipe[1] );


    如果管道的寫(xiě)入端關(guān)閉,但是還有進(jìn)程嘗試從管道讀取的話,將被返回0,用來(lái)指出管道已不可用,并且應(yīng)當(dāng)關(guān)閉它。如果管道的讀出端關(guān)閉,但是還有進(jìn)程嘗試向管道寫(xiě)入的話,試圖寫(xiě)入的進(jìn)程將收到一個(gè)SIGPIPE信號(hào),至于信號(hào)的具體處理則要視其信號(hào)處理程序而定了。

2.2 dup函數(shù)和dup2函數(shù)

    dup和dup2也是兩個(gè)非常有用的調(diào)用,它們的作用都是用來(lái)復(fù)制一個(gè)文件的描述符。它們經(jīng)常用來(lái)重定向進(jìn)程的stdin、stdout和stderr。這兩個(gè)函數(shù)的原型如下所示:

#include <unistd.h> int dup( int oldfd ); int dup2( int oldfd, int targetfd )

    利用函數(shù)dup,我們可以復(fù)制一個(gè)描述符。傳給該函數(shù)一個(gè)既有的描述符,它就會(huì)返回一個(gè)新的描述符,這個(gè)新的描述符是傳給它的描述符的拷貝。這意味著,這兩個(gè)描述符共享同一個(gè)數(shù)據(jù)結(jié)構(gòu)。例如,如果我們對(duì)一個(gè)文件描述符執(zhí)行l(wèi)seek操作,得到的第一個(gè)文件的位置和第二個(gè)是一樣的。下面是用來(lái)說(shuō)明dup函數(shù)使用方法的代碼片段:

int fd1, fd2; ... fd2 = dup( fd1 );

    需要注意的是,我們可以在調(diào)用fork之前建立一個(gè)描述符,這與調(diào)用dup建立描述符的效果是一樣的,子進(jìn)程也同樣會(huì)收到一個(gè)復(fù)制出來(lái)的描述符。

    dup2函數(shù)跟dup函數(shù)相似,但dup2函數(shù)允許調(diào)用者規(guī)定一個(gè)有效描述符和目標(biāo)描述符的id。dup2函數(shù)成功返回時(shí),目標(biāo)描述符(dup2函數(shù)的第二個(gè)參數(shù))將變成源描述符(dup2函數(shù)的第一個(gè)參數(shù))的復(fù)制品,換句話說(shuō),兩個(gè)文件描述符現(xiàn)在都指向同一個(gè)文件,并且是函數(shù)第一個(gè)參數(shù)指向的文件。下面我們用一段代碼加以說(shuō)明:

int oldfd; oldfd = open("app_log", (O_RDWR | O_CREATE), 0644 ); dup2( oldfd, 1 ); close( oldfd );

    本例中,我們打開(kāi)了一個(gè)新文件,稱為“app_log”,并收到一個(gè)文件描述符,該描述符叫做fd1。我們調(diào)用dup2函數(shù),參數(shù)為oldfd和1,這會(huì)導(dǎo)致用我們新打開(kāi)的文件描述符替換掉由1代表的文件描述符(即stdout,因?yàn)闃?biāo)準(zhǔn)輸出文件的id為1)。任何寫(xiě)到stdout的東西,現(xiàn)在都將改為寫(xiě)入名為“app_log”的文件中。需要注意的是,dup2函數(shù)在復(fù)制了oldfd之后,會(huì)立即將其關(guān)閉,但不會(huì)關(guān)掉新近打開(kāi)的文件描述符,因?yàn)槲募枋龇?現(xiàn)在也指向它。 

    下面我們介紹一個(gè)更加深入的示例代碼。回憶一下本文前面講的命令行管道,在那里,我們將ls –1命令的標(biāo)準(zhǔn)輸出作為標(biāo)準(zhǔn)輸入連接到wc –l命令。接下來(lái),我們就用一個(gè)C程序來(lái)加以說(shuō)明這個(gè)過(guò)程的實(shí)現(xiàn)。代碼如下面的示例代碼3所示。 

    在示例代碼3中,首先在第9行代碼中建立一個(gè)管道,然后將應(yīng)用程序分成兩個(gè)進(jìn)程:一個(gè)子進(jìn)程(第13–16行)和一個(gè)父進(jìn)程(第20–23行)。接下來(lái),在子進(jìn)程中首先關(guān)閉stdout描述符(第13行),然后提供了ls –1命令功能,不過(guò)它不是寫(xiě)到stdout(第13行),而是寫(xiě)到我們建立的管道的輸入端,這是通過(guò)dup函數(shù)來(lái)完成重定向的。在第14行,使用dup2函數(shù)把stdout重定向到管道(pfds[1])。之后,馬上關(guān)掉管道的輸入端。然后,使用execlp函數(shù)把子進(jìn)程的映像替換為命令ls –1的進(jìn)程映像,一旦該命令執(zhí)行,它的任何輸出都將發(fā)給管道的輸入端。 

    現(xiàn)在來(lái)研究一下管道的接收端。從代碼中可以看出,管道的接收端是由父進(jìn)程來(lái)?yè)?dān)當(dāng)?shù)摹J紫汝P(guān)閉stdin描述符(第20行),因?yàn)槲覀儾粫?huì)從機(jī)器的鍵盤(pán)等標(biāo)準(zhǔn)設(shè)備文件來(lái)接收數(shù)據(jù)的輸入,而是從其它程序的輸出中接收數(shù)據(jù)。然后,再一次用到dup2函數(shù)(第21行),讓stdin變成管道的輸出端,這是通過(guò)讓文件描述符0(即常規(guī)的stdin)等于pfds[0]來(lái)實(shí)現(xiàn)的。關(guān)閉管道的stdout端(pfds[1]),因?yàn)樵谶@里用不到它。最后,使用execlp函數(shù)把父進(jìn)程的映像替換為命令wc -1的進(jìn)程映像,命令wc -1把管道的內(nèi)容作為它的輸入(第23行)。

示例代碼3:利用C實(shí)現(xiàn)命令的流水線操作的代碼 1: #include <stdio.h> 2: #include <stdlib.h> 3: #include <unistd.h> 4: 5: int main() 6: ...{ 7: int pfds[2]; 8: 9: if ( pipe(pfds) == 0 ) ...{ 10: 11: if ( fork() == 0 ) ...{ 12: 13: close(1); 14: dup2( pfds[1], 1 ); 15: close( pfds[0] ); 16: execlp( "ls", "ls", "-1", NULL ); 17: 18: } else ...{ 19: 20: close(0); 21: dup2( pfds[0], 0 ); 22: close( pfds[1] ); 23: execlp( "wc", "wc", "-l", NULL ); 24: 25: } 26: 27: } 28: 29: return 0; 30: }


     在該程序中,需要格外關(guān)注的是,我們的子進(jìn)程把它的輸出重定向的管道的輸入,然后,父進(jìn)程將它的輸入重定向到管道的輸出。這在實(shí)際的應(yīng)用程序開(kāi)發(fā)中是非常有用的一種技術(shù)。

  2.3 mkfifo函數(shù)

    mkfifo函數(shù)的作用是在文件系統(tǒng)中創(chuàng)建一個(gè)文件,該文件用于提供FIFO功能,即命名管道。前邊講的那些管道都沒(méi)有名字,因此它們被稱為匿名管道,或簡(jiǎn)稱管道。對(duì)文件系統(tǒng)來(lái)說(shuō),匿名管道是不可見(jiàn)的,它的作用僅限于在父進(jìn)程和子進(jìn)程兩個(gè)進(jìn)程間進(jìn)行通信。而命名管道是一個(gè)可見(jiàn)的文件,因此,它可以用于任何兩個(gè)進(jìn)程之間的通信,不管這兩個(gè)進(jìn)程是不是父子進(jìn)程,也不管這兩個(gè)進(jìn)程之間有沒(méi)有關(guān)系。Mkfifo函數(shù)的原型如下所示:

#include <sys/types.h> #include <sys/stat.h> int mkfifo( const char *pathname, mode_t mode );

     mkfifo函數(shù)需要兩個(gè)參數(shù),第一個(gè)參數(shù)(pathname)是將要在文件系統(tǒng)中創(chuàng)建的一個(gè)專用文件。第二個(gè)參數(shù)(mode)用來(lái)規(guī)定FIFO的讀寫(xiě)權(quán)限。Mkfifo函數(shù)如果調(diào)用成功的話,返回值為0;如果調(diào)用失敗返回值為-1。下面我們以一個(gè)實(shí)例來(lái)說(shuō)明如何使用mkfifo函數(shù)建一個(gè)fifo,具體代碼如下所示:

int ret; ... ret = mkfifo( "/tmp/cmd_pipe", S_IFIFO | 0666 ); if (ret == 0) ...{ // 成功建立命名管道 } else ...{ // 創(chuàng)建命名管道失敗 }

    在這個(gè)例子中,利用/tmp目錄中的cmd_pipe文件建立了一個(gè)命名管道(即fifo)。之后,就可以打開(kāi)這個(gè)文件進(jìn)行讀寫(xiě)操作,并以此進(jìn)行通信了。命名管道一旦打開(kāi),就可以利用典型的輸入輸出函數(shù)從中讀取內(nèi)容。舉例來(lái)說(shuō),下面的代碼段向我們展示了如何通過(guò)fgets函數(shù)來(lái)從管道中讀取內(nèi)容:

pfp = fopen( "/tmp/cmd_pipe", "r" ); ... ret = fgets( buffer, MAX_LINE, pfp );

    我們還能向管道中寫(xiě)入內(nèi)容,下面的代碼段向我們展示了利用fprintf函數(shù)向管道寫(xiě)入的具體方法:

pfp = fopen( "/tmp/cmd_pipe", "w+ ); ... ret = fprintf( pfp, "Here’s a test string!\n" );


    對(duì)命名管道來(lái)說(shuō),除非寫(xiě)入方主動(dòng)打開(kāi)管道的讀取端,否則讀取方是無(wú)法打開(kāi)命名管道的。Open調(diào)用執(zhí)行后,讀取方將被鎖住,直到寫(xiě)入方出現(xiàn)為止。盡管命名管道有這樣的局限性,但它仍不失為一種有效的進(jìn)程間通信工具。

    上面介紹的是與管道有關(guān)的一些系統(tǒng)調(diào)用,下面介紹管道命令相關(guān)的系統(tǒng)命令。
五、與管道相關(guān)的系統(tǒng)命令

    現(xiàn)在開(kāi)始,我們來(lái)研究與進(jìn)程間通信密切相關(guān)的一些系統(tǒng)命令。首先介紹的是mkfifo命令,它的功能與mkfifo系統(tǒng)調(diào)用相似,只不過(guò)它是用來(lái)在命令行中建立一個(gè)命名管道。

    在命令行下建立fifo的專用文件,即命名管道的常用方法有兩個(gè),mkfifo命令便是其中之一。mkfifo命令的一般用法如下所示:

mkfifo [options] name

 

    這里的options一般為-m,即模式,用以指出讀寫(xiě)權(quán)限;name是要?jiǎng)?chuàng)建的管道的名稱,必要時(shí)可以加上路徑。如果我們沒(méi)有規(guī)定權(quán)限,該命令會(huì)采取默認(rèn)值0644。這里以一個(gè)具體實(shí)例來(lái)說(shuō)明如何在/tmp目錄下面建立一個(gè)稱為cmd_pipe的命名管道:

 

$ mkfifo /tmp/cmd_pipe

 

    下面用例子說(shuō)明如何給命名管道指定讀寫(xiě)權(quán)限。這里我們先將前面建立的管道刪掉,然后重新建立管道,并指定管道的權(quán)限為0644,當(dāng)然您也可以指定其他權(quán)限:

 

$ rm cmd_pipe $ mkfifo -m 0644 /tmp/cmd_pipe

 

    上面的權(quán)限一經(jīng)建立,就能夠在命令行行下通過(guò)此管道進(jìn)行通信了。比如,可以在一個(gè)終端上,利用cat命令來(lái)讀取管道:

 

$ cat cmd_pipe

 

    當(dāng)輸入該命令后,我們的進(jìn)程就會(huì)被掛起,等待寫(xiě)入程序打開(kāi)此管道。現(xiàn)在,在另一個(gè)終端上利用echo命令向這個(gè)命名管道寫(xiě)入:

 

$ echo Hi > cmd_pipe

 

    這個(gè)命令結(jié)束后,要讀取該管道的程序(即cat)將被喚醒,然后結(jié)束。為醒目起見(jiàn),這里列出完整的讀取方(也就是讀取管道的程序)輸入的命令和得到的結(jié)果:

 

$ cat cmd_pipe Hi $

 

    由此看來(lái),命名管道不僅在C程序中非常有用,而且在腳本中作用也很大。當(dāng)然,如果組合使用,效果也是很好的。

    除了mkfifo命令外,mknod命令也可以用來(lái)創(chuàng)建命名管道,其用法如下所示:

 

$ mknod cmd_pipe p

 


    該命令執(zhí)行后,將在當(dāng)前目錄下創(chuàng)建一個(gè)命名管道cmd_pipe,p用于指出建立的是命名管道。

    六、小結(jié)

    在這篇文章中,我們介紹了管道和命名管道的概念,詳細(xì)的說(shuō)明了應(yīng)用程序和命令行創(chuàng)建管道的方法,以及通過(guò)它們進(jìn)行通信的I/O機(jī)制。然后,討論了如何利用dup和 dup2命令來(lái)進(jìn)行輸入輸出重定向。我們希望本文能夠幫您更好的了解Linux下的管道技術(shù)。

 


posted on 2013-01-07 10:05 jackdong 閱讀(3001) 評(píng)論(0)  編輯 收藏 引用 所屬分類: Linux_Unix編程
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            国产欧美精品| 久久午夜国产精品| 久久先锋影音av| 亚洲欧美在线磁力| 午夜国产精品影院在线观看| 亚洲视频欧美视频| 亚洲欧美日韩精品久久亚洲区 | 国产一区二区黄| 国语精品一区| 最新高清无码专区| 日韩手机在线导航| 欧美专区日韩视频| 欧美承认网站| 亚洲视频欧美在线| 久久夜色精品国产亚洲aⅴ| 免费日韩精品中文字幕视频在线| 欧美激情一区二区三区| 国产精品极品美女粉嫩高清在线| 国产日韩亚洲欧美精品| 在线日韩av片| 欧美一区在线看| 亚洲国产高清aⅴ视频| 99视频精品在线| 欧美一级专区免费大片| 蘑菇福利视频一区播放| 国产精品视频久久| 亚洲国产高清自拍| 香港久久久电影| 91久久精品一区二区三区| 亚洲女ⅴideoshd黑人| 欧美成人一区二区三区| 国产乱码精品一区二区三区忘忧草| 在线观看国产欧美| 香蕉av777xxx色综合一区| 亚洲国产高清自拍| 久久久av水蜜桃| 国产精品亚洲综合久久| 亚洲免费播放| 欧美成人情趣视频| 久久国内精品视频| 国产精品毛片在线| 亚洲精品国精品久久99热一| 欧美一区视频| 亚洲一区二区精品| 欧美另类变人与禽xxxxx| 精品成人免费| 久久久精彩视频| 亚洲一区在线看| 欧美视频免费在线| 亚洲精品一区二区三区99| 玖玖视频精品| 欧美一区二区在线免费观看| 国产精品久久午夜夜伦鲁鲁| 日韩视频在线观看| 亚洲国产精品一区二区久| 久久综合久久综合久久| 悠悠资源网久久精品| 久久久久久久一区二区三区| 亚洲欧美自拍偷拍| 欧美一区二区福利在线| 国产精品盗摄一区二区三区| 夜夜嗨一区二区| 亚洲欧洲日夜超级视频| 欧美www视频| 亚洲精品国久久99热| 亚洲精品久久嫩草网站秘色| 欧美激情影音先锋| 在线亚洲国产精品网站| 一本久道久久综合狠狠爱| 欧美日韩一区二区国产| 亚洲欧美久久久| 欧美一区二区三区播放老司机 | 欧美一区二区三区啪啪| 国产欧美一区二区三区在线看蜜臀| 亚洲午夜久久久久久久久电影院| 99日韩精品| 国产日本欧美视频| 奶水喷射视频一区| 欧美国产欧美亚洲国产日韩mv天天看完整| 亚洲欧洲日韩女同| 日韩亚洲欧美成人| 国产欧美精品在线观看| 久久福利毛片| 欧美大片在线影院| 香蕉av福利精品导航| 久久一日本道色综合久久| 亚洲老司机av| 羞羞视频在线观看欧美| 亚洲二区免费| 亚洲小说欧美另类社区| 亚洲三级国产| 国产精品久久影院| 久久乐国产精品| 欧美日本在线观看| 久久精品在线| 欧美日韩视频在线观看一区二区三区| 亚洲欧美激情诱惑| 久久亚洲精品伦理| 亚洲专区在线| 免费观看在线综合| 久久久国产一区二区| 欧美精品色网| 久久人人97超碰国产公开结果| 欧美激情视频一区二区三区在线播放| 午夜精品一区二区三区在线播放 | 国产精品久久影院| 亚洲欧洲一区二区三区久久| 国产精品一区二区女厕厕| 亚洲福利视频一区| 国产视频在线观看一区二区三区| 亚洲国产精品高清久久久| 国产日本欧美视频| 亚洲精品一区二区在线观看| 欧美中文字幕视频| 亚洲高清不卡在线| 亚洲一区精彩视频| 亚洲乱码国产乱码精品精可以看 | 亚洲成人在线网| 亚洲一区在线播放| 99国产精品久久久久久久| 午夜精品一区二区在线观看 | 欧美成黄导航| 蜜乳av另类精品一区二区| 国产精品亚洲一区| 亚洲视频一区二区| 一区二区三区四区国产精品| 麻豆成人在线观看| 乱码第一页成人| 国产一区在线播放| 性欧美videos另类喷潮| 午夜在线a亚洲v天堂网2018| 欧美日韩一区二区免费视频| 亚洲精品一区在线观看香蕉| 亚洲三级免费电影| 欧美成人a∨高清免费观看| 男男成人高潮片免费网站| 激情自拍一区| 久久亚洲国产精品一区二区| 美女爽到呻吟久久久久| 影音先锋亚洲视频| 老司机成人在线视频| 欧美96在线丨欧| 亚洲人成久久| 欧美精品一区二区三区在线看午夜 | 欧美视频免费在线| 一区二区三区国产| 午夜精品久久久久久久99热浪潮| 国产精品成人午夜| 欧美一区二区三区日韩| 久久一区二区三区av| 在线观看欧美日韩| 美女视频黄a大片欧美| 亚洲青涩在线| 亚洲一区自拍| 国产一区二区三区四区五区美女 | 国产揄拍国内精品对白| 欧美一区二区三区在线| 亚洲美女黄色| 亚洲成人直播| 欧美二区视频| 99视频在线观看一区三区| 亚洲影院在线观看| 国产精品入口| 久久精品一二三区| 亚洲国产毛片完整版 | 1000部精品久久久久久久久| 欧美mv日韩mv亚洲| 一本一本a久久| 久久精品人人做人人综合| 夜夜嗨av一区二区三区中文字幕 | 久久精品国产96久久久香蕉| 久久亚洲午夜电影| 99国产精品一区| 国产一区二区三区在线观看网站 | 欧美777四色影视在线| 在线午夜精品自拍| 一区二区三区在线视频观看| 欧美精品v日韩精品v国产精品| 在线亚洲精品| 欧美成人免费va影院高清| 亚洲尤物在线视频观看| 精品51国产黑色丝袜高跟鞋| 欧美伦理影院| 美女日韩在线中文字幕| 亚洲欧美一区二区精品久久久| 亚洲国产专区| 久久人人97超碰国产公开结果| 亚洲一区二区三区视频| 亚洲人成人99网站| 国产一区二区精品在线观看| 欧美精品在线网站| 噜噜噜躁狠狠躁狠狠精品视频| 亚洲午夜久久久| 亚洲欧洲一区二区天堂久久 | 国际精品欧美精品| 欧美三级视频在线播放| 久久免费一区| 欧美一区二区免费视频| 日韩一区二区精品| 亚洲国产一区在线观看|