亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

搜索

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

WBOY
發(fā)布: 2024-02-15 13:40:03
轉(zhuǎn)載
917人瀏覽過(guò)

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)閉和刪除等方面。

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

無(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ī)則:

  1. 如果當(dāng)前打開(kāi)操作是為讀而打開(kāi)FIFO時(shí),若已經(jīng)有相應(yīng)進(jìn)程為寫而打開(kāi)該FIFO,則當(dāng)前打開(kāi)操作將成功返回;否則,可能阻塞直到有相應(yīng)進(jìn)程為寫而打開(kāi)該FIFO(當(dāng)前打開(kāi)操作設(shè)置了阻塞標(biāo)志);或者,成功返回(當(dāng)前打開(kāi)操作沒(méi)有設(shè)置阻塞標(biāo)志)。
  2. 如果當(dāng)前打開(kāi)操作是為寫而打開(kāi)FIFO時(shí),如果已經(jīng)有相應(yīng)進(jìn)程為讀而打開(kāi)該FIFO,則當(dāng)前打開(kāi)操作將成功返回;否則,可能阻塞直到有相應(yīng)進(jìn)程為讀而打開(kāi)該FIFO(當(dāng)前打開(kāi)操作設(shè)置了阻塞標(biāo)志);或者,返回ENXIO錯(cuò)誤(當(dāng)前打開(kāi)操作沒(méi)有設(shè)置阻塞標(biāo)志)。

總之就是一句話,一旦設(shè)置了阻塞標(biāo)志,調(diào)用mkfifo建立好之后,那么管道的兩端讀寫必須分別打開(kāi),有任何一方未打開(kāi),則在調(diào)用open的時(shí)候就阻塞。

從FIFO中讀取數(shù)據(jù):

約定:如果一個(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ù)!)

  1. 則對(duì)于設(shè)置了阻塞標(biāo)志的讀操作來(lái)說(shuō),將一直阻塞(就是block住了,等待數(shù)據(jù)。它并不消耗CPU資源,這種進(jìn)程的同步方式對(duì)CPU而言是非常有效率的。)
  2. 對(duì)于沒(méi)有設(shè)置阻塞標(biāo)志讀操作來(lái)說(shuō)則返回-1,當(dāng)前errno值為EAGAIN,提醒以后再試。

對(duì)于設(shè)置了阻塞標(biāo)志的讀操作說(shuō)(見(jiàn)上面的約定)
造成阻塞的原因有兩種

  1. FIFO內(nèi)有數(shù)據(jù),但有其它進(jìn)程在讀這些數(shù)據(jù)
  2. FIFO內(nèi)沒(méi)有數(shù)據(jù)。解阻塞的原因則是FIFO中有新的數(shù)據(jù)寫入,不論信寫入數(shù)據(jù)量的大小,也不論讀操作請(qǐng)求多少數(shù)據(jù)量。

讀打開(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。

有道小P
有道小P

有道小P,新一代AI全科學(xué)習(xí)助手,在學(xué)習(xí)中遇到任何問(wèn)題都可以問(wèn)我。

有道小P64
查看詳情 有道小P

注:如果FIFO中有數(shù)據(jù),則設(shè)置了阻塞標(biāo)志的讀操作不會(huì)因?yàn)镕IFO中的字節(jié)數(shù)小于請(qǐng)求讀的字節(jié)數(shù)而阻塞,此時(shí),讀操作會(huì)返回FIFO中現(xiàn)有的數(shù)據(jù)量。

向FIFO中寫入數(shù)據(jù):

約定:如果一個(gè)進(jìn)程為了向FIFO中寫入數(shù)據(jù)而阻塞打開(kāi)FIFO,那么稱該進(jìn)程內(nèi)的寫操作為設(shè)置了阻塞標(biāo)志的寫操作。

對(duì)于設(shè)置了阻塞標(biāo)志的寫操作:

  1. 當(dāng)要寫入的數(shù)據(jù)量不大于PIPE_BUF時(shí),linux將保證寫入的原子性。如果此時(shí)管道空閑緩沖區(qū)不足以容納要寫入的字節(jié)數(shù),則進(jìn)入睡眠,直到當(dāng)緩沖區(qū)中能夠容納要寫入的字節(jié)數(shù)時(shí),才開(kāi)始進(jìn)行一次性寫操作。(PIPE_BUF ==>> /usr/include/linux/limits.h)
  2. 當(dāng)要寫入的數(shù)據(jù)量大于PIPE_BUF時(shí),linux將不再保證寫入的原子性。FIFO緩沖區(qū)一有空閑區(qū)域,寫進(jìn)程就會(huì)試圖向管道寫入數(shù)據(jù),寫操作在寫完所有請(qǐng)求寫的數(shù)據(jù)后返回。

對(duì)于沒(méi)有設(shè)置阻塞標(biāo)志的寫操作:

  1. 當(dāng)要寫入的數(shù)據(jù)量大于PIPE_BUF時(shí),linux將不再保證寫入的原子性。在寫滿所有FIFO空閑緩沖區(qū)后,寫操作返回。
  2. 當(dāng)要寫入的數(shù)據(jù)量不大于PIPE_BUF時(shí),linux將保證寫入的原子性。如果當(dāng)前FIFO空閑緩沖區(qū)能夠容納請(qǐng)求寫入的字節(jié)數(shù),寫完后成功返回;如果當(dāng)前FIFO空閑緩沖區(qū)不能夠容納請(qǐng)求寫入的字節(jié)數(shù),則返回EAGAIN錯(cuò)誤,提醒以后再寫;

簡(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
登錄后復(fù)制

管道寫端 pipe_read.c

/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);
}
登錄后復(fù)制

管道讀端 pipe_write.c

//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);??
}
登錄后復(fù)制

本文介紹了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)文章!

最佳 Windows 性能的頂級(jí)免費(fèi)優(yōu)化軟件
最佳 Windows 性能的頂級(jí)免費(fèi)優(yōu)化軟件

每個(gè)人都需要一臺(tái)速度更快、更穩(wěn)定的 PC。隨著時(shí)間的推移,垃圾文件、舊注冊(cè)表數(shù)據(jù)和不必要的后臺(tái)進(jìn)程會(huì)占用資源并降低性能。幸運(yùn)的是,許多工具可以讓 Windows 保持平穩(wěn)運(yùn)行。

下載
來(lái)源:良許Linux教程網(wǎng)網(wǎng)
本文內(nèi)容由網(wǎng)友自發(fā)貢獻(xiàn),版權(quán)歸原作者所有,本站不承擔(dān)相應(yīng)法律責(zé)任。如您發(fā)現(xiàn)有涉嫌抄襲侵權(quán)的內(nèi)容,請(qǐng)聯(lián)系admin@php.cn
最新問(wèn)題
開(kāi)源免費(fèi)商場(chǎng)系統(tǒng)廣告
最新下載
更多>
網(wǎng)站特效
網(wǎng)站源碼
網(wǎng)站素材
前端模板
關(guān)于我們 免責(zé)申明 意見(jiàn)反饋 講師合作 廣告合作 最新更新
php中文網(wǎng):公益在線php培訓(xùn),幫助PHP學(xué)習(xí)者快速成長(zhǎng)!
關(guān)注服務(wù)號(hào) 技術(shù)交流群
PHP中文網(wǎng)訂閱號(hào)
每天精選資源文章推送
PHP中文網(wǎng)APP
隨時(shí)隨地碎片化學(xué)習(xí)
PHP中文網(wǎng)抖音號(hào)
發(fā)現(xiàn)有趣的

Copyright 2014-2025 http://ipnx.cn/ All Rights Reserved | php.cn | 湘ICP備2023035733號(hào)