linux系統中的有名管道

2021-06-18 23:02:27 字數 3417 閱讀 1551

無名管道應用的乙個重大限制是它沒有名字,因此,只能用於具有親緣關係的程序間通訊,在有名管道(named pipe或fifo)提出後,該限制得到了克服。fifo不同於管道之處在於它提供乙個路徑名與之關聯,以fifo的檔案形式存在於檔案系統中。這樣,即使與fifo的建立程序不存在親緣關係的程序,只要可以訪問該路徑,就能夠彼此通過fifo相互通訊(能夠訪問該路徑的程序以及fifo的建立程序之間),因此,通過fifo不相關的程序也能交換資料。值得注意的是,fifo嚴格遵循先進先出(first in first out),對管道及fifo的讀總是從開始處返回資料,對它們的寫則把資料新增到末尾。它們不支援諸如lseek()等檔案定位操作。

管道的緩衝區是有限的

(管道制存在於記憶體中,在管道建立時,為緩衝區分配乙個頁面大小)

管道所傳送的是

無格式位元組流

,這就要求管道的讀出方和寫入方必須事先約定好資料的格式,比如多少位元組算作乙個訊息(或命令、或記錄)等等

fifo往往都是多個寫程序,乙個讀程序。

fifo的開啟規則:

如果當前開啟操作是為讀而開啟fifo時,若已經有相應程序為寫而開啟該fifo,則當前開啟操作將成功返回;否則,可能阻塞直到有相應程序為寫而開啟該fifo(當前開啟操作設定了阻塞標誌);或者,成功返回(當前開啟操作沒有設定阻塞標誌)。

如果當前開啟操作是為寫而開啟fifo時,如果已經有相應程序為讀而開啟該fifo,則當前開啟操作將成功返回;否則,可能阻塞直到有相應程序為讀而開啟該fifo(當前開啟操作設定了阻塞標誌);或者,返回enxio錯誤(當前開啟操作沒有設定阻塞標誌)。

總之就是一句話,一旦設定了阻塞標誌,呼叫mkfifo建立好之後,那麼管道的兩端讀寫必須分別開啟,有任何一方未開啟,則在呼叫open的時候就阻塞。

約定:如果乙個程序為了從fifo中讀取資料而阻塞開啟fifo,那麼稱該程序內的讀操作為設定了阻塞標誌的讀操作。(意思就是我現在要開啟乙個有名管道來讀資料!)

如果有程序寫開啟fifo,且當前fifo內沒有資料(可以理解為管道的兩端都建立好了,但是寫端還沒開始寫資料!)

則對於設定了阻塞標誌的讀操作來說,將一直阻塞(就是block住了,等待資料。它並不消耗cpu資源,這種程序的同步方式對cpu而言是非常有效率的。)

對於沒有設定阻塞標誌讀操作來說則返回-1,當前errno值為eagain,提醒以後再試。

對於設定了阻塞標誌的讀操作說(見上面的約定)

造成阻塞的原因有兩種

fifo內有資料,但有其它程序在讀這些資料

fifo內沒有資料。解阻塞的原因則是fifo中有新的資料寫入,不論信寫入資料量的大小,也不論讀操作請求多少資料量。

讀開啟的阻塞標誌只對本程序第乙個讀操作施加作用,如果本程序內有多個讀操作序列,則在第乙個讀操作被喚醒並完成讀操作後,其它將要執行的讀操作將不再阻塞,即使在執行讀操作時,fifo中沒有資料也一樣,此時,讀操作返回0。

注:如果fifo中有資料,則設定了阻塞標誌的讀操作不會因為fifo中的位元組數小於請求讀的位元組數而阻塞,此時,讀操作會返回fifo中現有的資料量。

約定:如果乙個程序為了向fifo中寫入資料而阻塞開啟fifo,那麼稱該程序內的寫操作為設定了阻塞標誌的寫操作。

對於設定了阻塞標誌的寫操作:

當要寫入的資料量不大於pipe_buf時,linux將保證寫入的原子性。如果此時管道空閒緩衝區不足以容納要寫入的位元組數,則進入睡眠,直到當緩衝區中能夠容納要寫入的位元組數時,才開始進行一次性寫操作。(pipe_buf ==>> /usr/include/linux/limits.h)

當要寫入的資料量大於pipe_buf時,linux將不再保證寫入的原子性。fifo緩衝區一有空閒區域,寫程序就會試圖向管道寫入資料,寫操作在寫完所有請求寫的資料後返回。

對於沒有設定阻塞標誌的寫操作:

當要寫入的資料量大於pipe_buf時,linux將不再保證寫入的原子性。在寫滿所有fifo空閒緩衝區後,寫操作返回。

當要寫入的資料量不大於pipe_buf時,linux將保證寫入的原子性。如果當前fifo空閒緩衝區能夠容納請求寫入的位元組數,寫完後成功返回;如果當前fifo空閒緩衝區不能夠容納請求寫入的位元組數,則返回eagain錯誤,提醒以後再寫;

簡單描述下上面設定了阻塞標誌的邏輯

設定了阻塞標誌

if (buf_to_write <=  pipe_buf) 		//寫入的資料量不大於pipe_buf時

then

if ( buf_to_write > system_buf_left ) //保證寫入的原子性,要麼一次性把buf_to_write全都寫完,要麼乙個位元組都不寫!

then

block ;

until ( buf_to_write <= system_buf_left );

goto write ;

else

write ;

fielse

write ; //不管怎樣,就是不斷寫,知道把緩衝區寫滿了才阻塞

fi

#include #include #include #include #include #include #include #define fifo_name "/tmp/my_fifo"  

#define buffer_size pipe_buf

int main()

while(res > 0);

close(pipe_fd);

} else

printf("process %d finished, %d bytes read\n", getpid(), bytes);

exit(exit_success);

}

#include #include #include #include #include #include #include #define fifo_name "/tmp/my_fifo"  

#define buffer_size pipe_buf

#define ten_meg (1024 * 100)

int main()

} printf("process %d opening fifo o_wronly\n", getpid());

pipe_fd = open(fifo_name, open_mode);

printf("process %d result %d\n", getpid(), pipe_fd);

//sleep(20);

if (pipe_fd != -1)

bytes += res;

printf("%d\n",bytes);

} close(pipe_fd);

} else

printf("process %d finish\n", getpid());

exit(exit_success);

}

linux系統中的有名管道(FIFO)

無名管道應用的乙個重大限制是它沒有名字,因此,只能用於具有親緣關係的程序間通訊,在有名管道 named pipe或fifo 提出後,該限制得到了克服。fifo不同於管道之處在於它提供乙個路徑名與之關聯,以fifo的檔案形式存在於檔案系統中。這樣,即使與fifo的建立程序不存在親緣關係的程序,只要可以...

Linux 有名管道

include apue.h 在當前目錄建立乙個管道檔案 main printf success to mkfifo ret d n ret return 0 include apue.h main printf success to open file fd d n fd 向有名管道中寫資料 wr...

Linux有名管道程式設計

有名管道可以用於任何兩個程式間通訊,因為有名字可引用。注意管道都是單向的,因此雙方通訊需要兩個管道。下面分別是這兩個程式 同樣是lucy先執行,然後是peter。fifolucy.c include include include include include include include in...