linux系統(tǒng)是一種支持多任務(wù)并發(fā)執(zhí)行的操作系統(tǒng),它可以同時(shí)運(yùn)行多個(gè)進(jìn)程,從而提高系統(tǒng)的利用率和效率。但是,如果這些進(jìn)程之間需要進(jìn)行數(shù)據(jù)交換和協(xié)作,就需要使用一些進(jìn)程間通信(ipc)的方式,例如信號(hào)、消息隊(duì)列、共享內(nèi)存、信號(hào)量等。其中,有名管道(fifo)是一種比較簡(jiǎn)單而強(qiáng)大的ipc方式,它可以讓兩個(gè)或多個(gè)進(jìn)程通過(guò)一個(gè)文件來(lái)進(jìn)行數(shù)據(jù)傳輸,無(wú)需關(guān)心文件的內(nèi)容和格式。本文將介紹linux系統(tǒng)中的有名管道(fifo)的方法,包括有名管道的創(chuàng)建、打開(kāi)、讀寫、關(guān)閉和刪除等方面。
無(wú)名管道應(yīng)用的一個(gè)重大限制是它沒(méi)有名字,因此,只能用于具有親緣關(guān)系的進(jìn)程間通信,在有名管道(named pipe或FIFO)提出后,該限制得到了克服。FIFO不同于管道之處在于它提供一個(gè)路徑名與之關(guān)聯(lián),以FIFO的文件形式存在于文件系統(tǒng)中。這樣,即使與FIFO的創(chuàng)建進(jìn)程不存在親緣關(guān)系的進(jìn)程,只要可以訪問(wèn)該路徑,就能夠彼此通過(guò)FIFO相互通信(能夠訪問(wèn)該路徑的進(jìn)程以及FIFO的創(chuàng)建進(jìn)程之間),因此,通過(guò)FIFO不相關(guān)的進(jìn)程也能交換數(shù)據(jù)。值得注意的是,F(xiàn)IFO嚴(yán)格遵循先進(jìn)先出(first in first out),對(duì)管道及FIFO的讀總是從開(kāi)始處返回?cái)?shù)據(jù),對(duì)它們的寫則把數(shù)據(jù)添加到末尾。它們不支持諸如lseek()等文件定位操作。
管道的緩沖區(qū)是有限的(管道制存在于內(nèi)存中,在管道創(chuàng)建時(shí),為緩沖區(qū)分配一個(gè)頁(yè)面大?。?br>
管道所傳送的是無(wú)格式字節(jié)流,這就要求管道的讀出方和寫入方必須事先約定好數(shù)據(jù)的格式,比如多少字節(jié)算作一個(gè)消息(或命令、或記錄)等等
FIFO往往都是多個(gè)寫進(jìn)程,一個(gè)讀進(jìn)程。
FIFO的打開(kāi)規(guī)則:
總之就是一句話,一旦設(shè)置了阻塞標(biāo)志,調(diào)用mkfifo建立好之后,那么管道的兩端讀寫必須分別打開(kāi),有任何一方未打開(kāi),則在調(diào)用open的時(shí)候就阻塞。
約定:如果一個(gè)進(jìn)程為了從FIFO中讀取數(shù)據(jù)而阻塞打開(kāi)FIFO,那么稱該進(jìn)程內(nèi)的讀操作為設(shè)置了阻塞標(biāo)志的讀操作。(意思就是我現(xiàn)在要打開(kāi)一個(gè)有名管道來(lái)讀數(shù)據(jù)!)
如果有進(jìn)程寫打開(kāi)FIFO,且當(dāng)前FIFO內(nèi)沒(méi)有數(shù)據(jù)(可以理解為管道的兩端都建立好了,但是寫端還沒(méi)開(kāi)始寫數(shù)據(jù)!)
對(duì)于設(shè)置了阻塞標(biāo)志的讀操作說(shuō)(見(jiàn)上面的約定)
造成阻塞的原因有兩種
讀打開(kāi)的阻塞標(biāo)志只對(duì)本進(jìn)程第一個(gè)讀操作施加作用,如果本進(jìn)程內(nèi)有多個(gè)讀操作序列,則在第一個(gè)讀操作被喚醒并完成讀操作后,其它將要執(zhí)行的讀操作將不再阻塞,即使在執(zhí)行讀操作時(shí),F(xiàn)IFO中沒(méi)有數(shù)據(jù)也一樣,此時(shí),讀操作返回0。
注:如果FIFO中有數(shù)據(jù),則設(shè)置了阻塞標(biāo)志的讀操作不會(huì)因?yàn)镕IFO中的字節(jié)數(shù)小于請(qǐng)求讀的字節(jié)數(shù)而阻塞,此時(shí),讀操作會(huì)返回FIFO中現(xiàn)有的數(shù)據(jù)量。
約定:如果一個(gè)進(jìn)程為了向FIFO中寫入數(shù)據(jù)而阻塞打開(kāi)FIFO,那么稱該進(jìn)程內(nèi)的寫操作為設(shè)置了阻塞標(biāo)志的寫操作。
對(duì)于設(shè)置了阻塞標(biāo)志的寫操作:
對(duì)于沒(méi)有設(shè)置阻塞標(biāo)志的寫操作:
簡(jiǎn)單描述下上面設(shè)置了阻塞標(biāo)志的邏輯
設(shè)置了阻塞標(biāo)志
if?(buf_to_write?then ?if?(?buf_to_write?>?system_buf_left?)?//保證寫入的原子性,要么一次性把buf_to_write全都寫完,要么一個(gè)字節(jié)都不寫! ?then ??block?; ??until?(?buf_to_write?else ??write?; ?fi else ?write?;?//不管怎樣,就是不斷寫,知道把緩沖區(qū)寫滿了才阻塞 fi
/pipe_read.c #include #include #include #include #include #include #include #define FIFO_NAME "/tmp/my_fifo" #define BUFFER_SIZE PIPE_BUF int main() { int pipe_fd; int res; int open_mode = O_RDONLY; char buffer[BUFFER_SIZE + 1]; int bytes = 0; memset(buffer, '\0', sizeof(buffer)); printf("Process %d opeining FIFO O_RDONLY\n", getpid()); pipe_fd = open(FIFO_NAME, open_mode); printf("Process %d result %d\n", getpid(), pipe_fd); if (pipe_fd != -1) { do{ res = read(pipe_fd, buffer, BUFFER_SIZE); bytes += res; printf("%d\n",bytes); }while(res > 0); close(pipe_fd); } else { exit(EXIT_FAILURE); } printf("Process %d finished, %d bytes read\n", getpid(), bytes); exit(EXIT_SUCCESS); }
//pipe_write.c #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()?? {?? ????int?pipe_fd;?? ????int?res;?? ????int?open_mode?=?O_WRONLY;?? ?? ????int?bytes?=?0;?? ????char?buffer[BUFFER_SIZE?+?1];?? ?? ????if?(access(FIFO_NAME,?F_OK)?==?-1)?? ????{?? ????????res?=?mkfifo(FIFO_NAME,?0777);?? ????????if?(res?!=?0)?? ????????{?? ????????????fprintf(stderr,?"Could?not?create?fifo?%s\n",?FIFO_NAME);?? ????????????exit(EXIT_FAILURE);?? ????????}?? ????}?? ?? ????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)?? ????{?? ????????while?(bytes?if?(res?==?-1)?? ????????????{?? ????????????????fprintf(stderr,?"Write?error?on?pipe\n");?? ????????????????exit(EXIT_FAILURE);?? ????????????}?? ????????????bytes?+=?res;?? ????????printf("%d\n",bytes); ????????}?? ????????close(pipe_fd);?? ????}?? ????else?? ????{?? ????????exit(EXIT_FAILURE);?? ????}?? ?? ????printf("Process?%d?finish\n",?getpid());?? ????exit(EXIT_SUCCESS);?? }
本文介紹了linux系統(tǒng)中的有名管道(FIFO)的方法,包括有名管道的創(chuàng)建、打開(kāi)、讀寫、關(guān)閉和刪除等方面。通過(guò)了解和掌握這些知識(shí),我們可以更好地使用有名管道(FIFO)來(lái)實(shí)現(xiàn)進(jìn)程間通信,提高系統(tǒng)的性能和可靠性。當(dāng)然,linux系統(tǒng)中的有名管道(FIFO)還有很多其他的特性和用法,需要我們不斷地學(xué)習(xí)和探索。希望本文能給你帶來(lái)一些啟發(fā)和幫助。
以上就是linux系統(tǒng)中的有名管道(FIFO)的詳細(xì)內(nèi)容,更多請(qǐng)關(guān)注php中文網(wǎng)其它相關(guān)文章!
每個(gè)人都需要一臺(tái)速度更快、更穩(wěn)定的 PC。隨著時(shí)間的推移,垃圾文件、舊注冊(cè)表數(shù)據(jù)和不必要的后臺(tái)進(jìn)程會(huì)占用資源并降低性能。幸運(yùn)的是,許多工具可以讓 Windows 保持平穩(wěn)運(yùn)行。
微信掃碼
關(guān)注PHP中文網(wǎng)服務(wù)號(hào)
QQ掃碼
加入技術(shù)交流群
Copyright 2014-2025 http://ipnx.cn/ All Rights Reserved | php.cn | 湘ICP備2023035733號(hào)