#include int pipe(int fd[2]); //返回值:若成功,返回0,若出錯,返回-1
經由引數fd返回兩個檔案描述符:fd[0]為讀而開啟,fd[1]為寫而開啟。fd[1]的輸出是fd[0]的輸入。
else if(pid == 0) //子程序
else
}else if(pid > 0) //父程序
printf("the data from pipe is %s\n", d);
} return 0;
}
#include file *open(const char *cmdstring, const char *type);//返回值:若成功,返回檔案指標;若出錯,返回null
int pclose(file *fd);//返回值:若成功,返回cmdstring的終止狀態;若出錯,返回-1
函式popen先執行fork,然後呼叫exec執行cmdstring,並且返回乙個標準i/o檔案指標。
如果type是「r」,則檔案指標連線到cmdstring的標準輸出。
如果type是「w」,則檔案指標連線到cmdstring的標準輸入。
未命名的管道只能在兩個相關的程序之間使用,而且這兩個相關的程序還要有乙個共同的建立了它們的祖先程序。但是通過fifo,不相關的程序也能交換資料。#include int mkfifo(const char *path, mode_t mode);
int mkfifoat(int fd, const char *path, mode_t mode);
//兩個函式的返回值: 若成功,返回0;若出錯,返回-1.
mkfifo的第乙個引數是乙個普通的路勁名,也就是建立後fifo的名字。第二個引數與開啟普通檔案的open()函式中的mode引數相同。如果mkfifo的乙個引數是乙個已經存在路勁名時,會返回eexist錯誤,所以一般典型的呼叫**首先會檢查是否返回該錯誤,如果確實返回該錯誤,那麼只要呼叫開啟fifo的函式就可以了。
mkfifoat函式和mkfifo函式相似。但是mkfifoat函式可以被用來在fd檔案描述符表示的目錄相關的位置建立乙個fifo。
fifo不同於無名管道之處在於它提供了乙個路徑名與之關聯,以fifo的檔案形式存在於檔案系統中,這樣,即使與fifo的建立程序不存在親緣關係的程序,只要可以訪問該路徑,就能夠彼此通過fifo相互通訊,因此,通過fifo不相關的程序也能交換資料。值的注意的是,fifo嚴格遵循先進先出(first in first out),對管道及fifo的讀總是從開始處返回資料,對它們的寫則把資料新增到末尾。它們不支援諸如lseek()等檔案定位操作。
注意:有名管道的名字存在於檔案系統中,內容存放在記憶體中。
有名管道的開啟規則
有名管道比無名管道多了乙個開啟操作:open
如果當前開啟操作時為讀而開啟fifo時,若已經有相應程序為寫而開啟該fifo,則當前開啟操作將成功返回;否則,可能阻塞到有相應程序為寫而開啟該fifo(當前開啟操作設定了阻塞標誌);或者,成功返回(當前開啟操作沒有設定阻塞標誌)。
如果當前開啟操作時為寫而開啟fifo時,如果已經有相應程序為讀而開啟該fifo,則當前開啟操作將成功返回;否則,可能阻塞直到有相應程序為讀而開啟該fifo(當前開啟操作設定了阻塞標誌);或者,返回enio錯誤(當期開啟操作沒有設定阻塞標誌)。
**發現,如果open時沒有使用o_nonblock引數,我們發現不論讀端還是寫端先開啟,先開啟者都會阻塞,一直阻塞到另一端開啟。
如果指定了o_nonblock,則唯讀open立即返回。但是,如果沒有程序為讀而開啟乙個fifo,那麼只寫open將返回-1,並將errno設定成enxio.
a.從fifo中讀取資料
約定:如果乙個程序為了從fifo中讀取資料而以阻塞的方式開啟fifo, 則稱核心為該程序的讀操作設定了阻塞標誌
<1>如果有程序為讀而開啟fifo,且當前fifo內沒有資料,則對於設定了阻塞標誌的讀操作來說,將一直阻塞。對於沒有設定阻塞標誌讀操作來說返回-1,當前errno值為eagain,提醒以後再試。
<2>對於設定阻塞標誌的讀操作說,造成阻塞的原因有兩種:當前fifo內有資料,但有其他程序正在讀這些資料;另外就是fifo內沒有資料。解阻塞的原因則是fifo中有新的資料寫入,不論寫入資料量的大小,也不論讀操作請求多少資料量。
<3>如果沒有程序寫開啟fifo,則設定了阻塞標誌的讀操作會阻塞
<4>如果寫端關閉,管道中有資料讀取管道中的資料,如果管道中沒有資料讀端將不會繼續阻塞,此時返回0。
注意:如果fifo中有資料,則設定了阻塞標誌的讀操作不會因為fifo中的位元組數小於請求讀的位元組數而阻塞,此時,讀操作會返回fifo中現有的資料量。
b.向fifo中寫入資料
約定:如果乙個程序為了向fifo中寫入資料而阻塞開啟fifo,那麼稱該程序內的寫操作設定了阻塞標誌。
對於設定了阻塞標誌的寫操作:
<1>當要寫入的資料量不大於pipe_buf時,linux將保證寫入的原子性。如果此時管道空閒緩衝區不足以容納要寫入的位元組數,則進入睡眠,直到當緩衝區中能夠容納寫入的位元組數時,才開始進行一次性寫操作。
<2>當要寫入的資料量大於pipe_buf時,linux將不再保證寫入的原子性。fifo緩衝區一有空閒區域,寫程序就會試圖向管道寫入資料,寫操作在寫完所有請求寫的資料後返回。
對於沒有設定阻塞標誌的寫操作:
<1>當要寫入的資料量大於pipe_buf時,linux將不再保證寫入的原子性。在寫滿所有fifo空閒緩衝區後,寫操作返回。
<2>當要寫入的資料量不大於pipe_buf時,linux將保證寫入的原子性。如果當前fifo空閒緩衝區能夠容納請求寫入的位元組數,寫完後成功返回;如果當前fifo空閒緩衝區不能夠容納請求寫入的位元組數,則返回eagain錯誤,提醒以後再寫。
注意:只有讀端存在,寫端才有意義。如果讀端不在,寫端向fifo寫資料,核心將向對應的程序傳送sigpipe訊號(預設終止程序);
向有名管道中傳送資料的程序源**如下:
#include #include #include #include #include #define fifo_name "/tmp/my_fifo" //要建立的有名管道路徑
int main(int argc, char *argv)
} printf("process %d opening fifo o_wronly\n", getpid()); //列印提示資訊
pipe_fd = open(fifo_name, o_wronly); //開啟有名管道
printf("the file's descriptor is %d\n", pipe_fd);
if(pipe_fd != -1)
printf("write data is %s, %d bytes is write\n", buffer, res); //列印寫入的資料及資料量
(void)close(pipe_fd); //關閉管道
} else
exit(exit_failure);
printf("process %d finished\n", getpid());
exit(exit_success);
}
讀程序負責從有名管道中讀取資料,其源**如下:
#include #include #include #include #include #include #define fifo_name "/tmp/my_fifo"
int main(int argc, char *argv)
else
exit(exit_failure);
printf("process %d finished, %d bytes read\n", getpid(), bytes_read);
exit(exit_success);
}
程序間通訊 管道
原文 程序間通訊 管道 管道簡介 常說的管道都是匿名半雙工管道,匿名半雙工管道在系統中是沒有實名的,並不可以在檔案系統中以任何方式看到該管道。它只是程序的一種資源,會隨著程序的結束而被系統清除。管道通訊是在unix系統中應用比較頻繁的一種方式,例如使用grep查詢 ls grep ipc 顧名思義,...
程序間通訊 管道
程序間通訊,又稱為ipc,包含以下型別 半雙工管道fifo 全雙工管道 訊息佇列 訊號 訊號量共享記憶體 套接字socket streams。一,管道是unix系統ipc的最古老形式,他具有兩種侷限性 1 資料只能在乙個方向上流動 2 只能在具有公共祖先的程序之間使用。乙個管道由乙個程序建立,然後該...
程序間通訊 管道
管道是 一種最基本的 ipc機制,由pipe函式建立。include int pipe int fileds 2 呼叫pipe函式時在記憶體中開闢一塊緩衝區 就稱為管道 用於通訊,它有乙個讀端和乙個寫端,通過函式引數傳給使用者程式兩個檔案描述符,fileds 0 指向管道的讀端,fileds 1 指...