Linux程序程式設計介紹(四)

2021-04-13 10:01:20 字數 3133 閱讀 5028

linux程序程式設計介紹(四)

2006-11-19 16:55

**:計算機基礎教程網(itwen.com)

摘要:這一節,我們來看一種比較簡單的資料傳送的方法,即通過管道傳送資料

4.程序間使用管道通訊

前幾節中我們講述了有關程序的操作,我們已經學會產生乙個新的程序,改變程序的執行影象等操作。然而,子程序與父程序,子程序與子程序之間,還缺少資料交換的方法。這一節,我們就來看一種比較簡單的資料傳送的方法,即通過管道傳送資料。

管道允許在程序之間按先進先出的方式傳送資料,管道也能使程序同步執行。管道傳統的實現方法是通過檔案系統作為儲存資料的地方。有兩種型別的管道:一種 是無名管道,簡稱為管道;另一種是有名管道,也稱為fifo。程序使用系統呼叫open來開啟有名管道,使用系統呼叫pipe來建立無名管道。使用無名管 道通訊的程序,必須是發出pipe呼叫的程序及其子程序。使用有名管道通訊的程序沒有上述限制。在以後的敘述中,所有無名管道都簡稱為管道。下面來看一下 系統呼叫pipe。

4.1 pipe 系統呼叫

系統呼叫pipe是用來建立管道的。該呼叫的宣告格式如下:

int pipe(int filedes[2]);

在使用該呼叫的程式中加入下面的標頭檔案:

#include

乙個管道擁有兩個檔案描述符用來通訊,它們指向乙個管道的索引節點,該呼叫將這兩檔案描述符放在引數filedes中返回。現在的許多系統中管道允許數 據雙向流動,但一般習慣上,檔案描述符filedes[0]用來讀資料,filedes[1]用來寫資料。如果要求程式的可移植性好,就按照習慣的用法來 程式設計。呼叫成功時,返回值為0;錯誤時,返回-1,並設定錯誤**errno:

emfile:程序使用了過多的檔案描述符。

enfile:系統檔案表滿。

efault:引數filedes無效。

下面介紹管道的操作的情況:

對於寫管道:

寫入管道的資料按到達次序排列。如果管道滿,則對管道的寫被阻塞,直到管道的資料被讀操作讀取。對於寫操作,如果一次write呼叫寫的資料量小於管道 容量,則寫必須一次完成,即如果管道所剩餘的容量不夠,write被阻塞直到管道的剩餘容量可以一次寫完為止。如果write呼叫寫的資料量大於管道容 量,則寫操作分多次完成。如果用fcntl設定管道寫埠為非阻塞方式,則管道滿不會阻塞寫,而只是對寫返回0。

對於讀管道:

讀操作按資料到達的順序讀取資料。已經被讀取的資料在管道內不再存在,這意味著資料在管道中不能重複利用。如果管道為空,且管道的寫埠是開啟狀態,則 讀操作被阻塞直到有資料寫入為止。一次read呼叫,如果管道中的資料量不夠read指定的數量,則按實際的數量讀取,並對read返回實際數量值。如果 讀埠使用fcntl設定了非阻塞方式,則當管道為空時,read呼叫返回0。

對於管道的關閉:

如果管道的讀埠 關閉,那麼在該管道上的發出寫操作呼叫的程序將接收到乙個sigpipe訊號。關閉寫埠是給讀埠乙個檔案結束符的唯一方法。對於寫埠關閉後,在該管 道上的read呼叫將返回0。下面再來看看,系統呼叫pipe的例子。在下面的例子中,父程序通過管道向子程序傳送了乙個字串。子程序將它顯示出來:

#include

#include

#include

#include

#include

int main()

if ((cld_pid=fork()) == 0)

else

}該程式執行過程的螢幕拷貝:

[root@wapgw /tmp]# ./pipe

[root@wapgw /tmp]# child read pipe is -- parent creat this buff for cld 5954

[root@wapgw /tmp]#

4.2 dup 系統呼叫

系統呼叫dup是用來複製乙個檔案描述符,也就是將程序u區的檔案描述符表中的一項複製乙份,使得這兩項同時指向系統檔案表的同一表項。該呼叫的宣告格式如下:

int dup(int oldfd);

int dup2(int oldfd, int newfd);

在使用該呼叫的程式中加入下面的標頭檔案:

#include

系統呼叫dup複製由引數oldfd指定的檔案描述到程序檔案描述符表的第乙個空表項處。而系統呼叫dup2複製由引數oldfd指定的檔案描述到引數 newfd指定的檔案描述符表項處。老的檔案描述符和新複製的檔案描述符可以互換使用。它們共享鎖、檔案指標和檔案狀態。例如,對其中乙個檔案描述符使用 系統呼叫lseek修改檔案指標的位置,對另一檔案描述符來說檔案指標也改變了,其實我們了解了核心的工作原理,這一點很容易理解。因為我們知道,檔案指 針是放在系統檔案表中的。但這兩個檔案描述符具有不同的close-on-exec標誌,因為該標誌是存放在檔案描述符表中的。

該呼叫成功時,返回值為新的描述符;錯誤時,返回-1,並設定相應的錯誤**errno:

ebadf:引數oldfd不是乙個已經開啟的檔案描述符;或者引數newfd超出允許的檔案描述符的取值範圍。

emfile:程序開啟的檔案描述符數量已經到達最大值,但仍然企圖開啟新的檔案描述符。

下面我們來看乙個簡單的例子。在這個例子中,我們將標準輸出(檔案描述符為1)關閉,並將乙個開啟了普通檔案「output」的檔案描述符複製到標準輸 出上,因為剛關閉了檔案描述符1,所以,檔案描述符表的第乙個空表項是1。所以,程式以後的printf等向標準輸出寫的內容都寫到了檔案 output中。

#include

#include

#include

#include

#include

int main()

close(1); /* 關閉標準輸出 */

dup(fd); /* 複製fd到檔案描述符1上 */

close(fd); /* 即時關閉不用的檔案描述符是乙個好習慣 */

printf("this line will write to file ");

exit(0);

}該程式執行過程的螢幕拷貝:

[wap@wapgw /tmp]$ gcc -o dup_test dup_test.c

[wap@wapgw /tmp]$ ./dup_test

[wap@wapgw /tmp]$ more output

this line will write to file

[wap@wapgw /tmp]$

Linux程序程式設計

一 與程序相關的系統函式 1.getpid include 提供pid t型別的定義 include 提供函式的定義 pid t getpid void 返回值為當前程序的程序id 2.getppid include 提供pid t型別的定義 include 提供函式的定義 pid getppid ...

Linux 程序程式設計

程序程式設計 1 getpid 函式的作用 獲取程序的識別碼 程序號 函式的原型 pid t getpid void 返回值 目前程序的程序號 標頭檔案 include 2 fork 函式的作用 建立乙個程序 函式的原型 pid t fork void 函式的返回值 0 出錯 0 表示當前建立的是子...

Linux 程序程式設計

特點 wait waitpid 殭屍程序 特點 pid t waitpid pid t pid,int status,options 使用pipe 使用方便 兩個程序中,其中乙個程序讀取管道 使用pipe函式構建父子關係,呼叫ls l grep a.out demo c int main int i...