新聞中心
在Linux系統(tǒng)中,命名管道(Named Pipes)是一種允許進(jìn)程之間進(jìn)行通信的特殊文件類型。命名管道與一般的管道不同,它允許兩個(gè)或多個(gè)進(jìn)程之間進(jìn)行雙向通信,而且可以持久存在于文件系統(tǒng)中,使得進(jìn)程可以在不同時(shí)間進(jìn)行通信。本文將介紹,包括創(chuàng)建、刪除、使用等方面。

做網(wǎng)站、成都做網(wǎng)站的關(guān)注點(diǎn)不是能為您做些什么網(wǎng)站,而是怎么做網(wǎng)站,有沒有做好網(wǎng)站,給創(chuàng)新互聯(lián)一個(gè)展示的機(jī)會(huì)來證明自己,這并不會(huì)花費(fèi)您太多時(shí)間,或許會(huì)給您帶來新的靈感和驚喜。面向用戶友好,注重用戶體驗(yàn),一切以用戶為中心。
創(chuàng)建命名管道
在Linux系統(tǒng)中,使用mkfifo命令來創(chuàng)建命名管道。mkfifo按照后面跟的文件名創(chuàng)建一個(gè)命名管道,并且該文件可以跟其他文件一樣通過ls命令查看。命令的格式如下:
“`
$ mkfifo filename
“`
其中,filename為你希望創(chuàng)建的文件名。下面我們以舉例的方式來介紹如何創(chuàng)建一個(gè)命名管道。
“`
$ mkfifo my_pipe
“`
使用命名管道
一旦命名管道被創(chuàng)建,就可以使用該命名管道進(jìn)行通信。我們可以使用echo命令向管道中寫入數(shù)據(jù),使用cat命令從管道中讀出數(shù)據(jù),也可以通過其他方式讀寫數(shù)據(jù)。下面我們將通過兩個(gè)進(jìn)程之間進(jìn)行通信來演示如何使用命名管道。
打開一個(gè)終端窗口,輸入以下命令:
“`
$ cat my_pipe
“`
該命令會(huì)將my_pipe管道中的數(shù)據(jù)輸出到終端窗口。此時(shí),終端窗口會(huì)一直等待,直到有數(shù)據(jù)被寫入到my_pipe中。我們需要打開另一個(gè)終端窗口,向my_pipe中寫入一些數(shù)據(jù),這樣上述命令才能輸出這些數(shù)據(jù)。
在新的終端窗口中,輸入以下命令:
“`
$ echo “Hello, world!” > my_pipe
“`
此時(shí),”Hello, world!”將被寫入到my_pipe中,并且會(huì)被cat命令輸出到上一個(gè)終端窗口中。注意,你可以通過其他方式向該管道中寫入數(shù)據(jù),例如使用文件重定向、使用腳本等。
刪除命名管道
當(dāng)不再需要使用命名管道時(shí),可以使用rm命令將其刪除。刪除命名管道后,該命名管道中的數(shù)據(jù)也會(huì)被刪除。命令的格式如下:
“`
$ rm filename
“`
其中,filename為需要?jiǎng)h除的文件名。下面我們以舉例的方式來介紹如何刪除之前創(chuàng)建的命名管道。
“`
$ rm my_pipe
“`
本文介紹了,包括創(chuàng)建、刪除、使用等方面。命名管道不僅可以在兩個(gè)進(jìn)程之間進(jìn)行通信,也可以用于腳本編程、文件傳輸?shù)确矫妗J炀氄莆彰艿赖氖褂梅椒?,有助于提高工作效率和編程水平?/p>
成都網(wǎng)站建設(shè)公司-創(chuàng)新互聯(lián)為您提供網(wǎng)站建設(shè)、網(wǎng)站制作、網(wǎng)頁設(shè)計(jì)及定制高端網(wǎng)站建設(shè)服務(wù)!
一個(gè)Linux多進(jìn)程編程?
1 引言
對(duì)于沒有接觸過Unix/Linux操作系統(tǒng)的人來說,fork是最難理解的概念之一:它執(zhí)行一次卻返回兩個(gè)值。fork函數(shù)是Unix系統(tǒng)最杰出的成就之一,它是七十年代UNIX早期的開發(fā)者經(jīng)過長期在理論和實(shí)踐上的艱苦探索后取得的成果,一方面,它使操作系統(tǒng)在進(jìn)程管理上付出了最小的代價(jià),另一方面,又為程序員提供了一個(gè)簡潔明了的多進(jìn)程方法。與DOS和早期的Windows不同,Unix/Linux系統(tǒng)是真正實(shí)現(xiàn)多任務(wù)操作的系統(tǒng),可以說,不使用多進(jìn)程編程,就不能算是真正的Linux環(huán)境下編程。
多線程程序設(shè)計(jì)的概念早在六十年代就被提出,但直到八十年代中期,Unix系統(tǒng)中才引入多線程機(jī)制,如今,由于自身的許多優(yōu)點(diǎn),多線程編程已經(jīng)得到了廣泛的應(yīng)用。
下面,我們將介紹在Linux下編寫多進(jìn)程和多線程程序的一些初步知識(shí)。
2 多進(jìn)程編程
什么是一個(gè)進(jìn)程?進(jìn)程這個(gè)概念是針對(duì)系統(tǒng)而不是針對(duì)用戶的,對(duì)用戶來說,他面對(duì)的概念是程序。當(dāng)用戶敲入命令執(zhí)行一個(gè)程序的時(shí)候,對(duì)系統(tǒng)而言,它將啟動(dòng)一個(gè)進(jìn)程。但和程序不同的是,在這個(gè)進(jìn)程中,系統(tǒng)可能需要再啟動(dòng)一個(gè)或多個(gè)進(jìn)程來完成獨(dú)立的多個(gè)任務(wù)。多進(jìn)程編程的主要內(nèi)容包括進(jìn)程控制和進(jìn)程間通信,在了解這些之前,我們先要簡單知道進(jìn)程的結(jié)構(gòu)。
2.1 Linux下進(jìn)程的結(jié)構(gòu)
Linux下一個(gè)進(jìn)程在內(nèi)存里有三部分的數(shù)據(jù),就是”代碼段”、”堆棧段”和”數(shù)據(jù)段”。其實(shí)學(xué)過匯編語言的人一定知道,一般的CPU都有上述三種段寄存器,以方便操作系統(tǒng)的運(yùn)行。這三個(gè)部分也是構(gòu)成一個(gè)完整的執(zhí)行序列的必要的部分。
“代碼段”,顧名思義,就是存放了程序代碼的數(shù)據(jù),假如機(jī)器中有數(shù)個(gè)進(jìn)程運(yùn)行相同的一個(gè)程序,那么它們就可以使用相同的代碼段。”堆棧段”存放的就是子程序的返回地址、子程序的參數(shù)以及程序的局部變量。而數(shù)據(jù)段則存放程序的全局變量,常數(shù)以及動(dòng)態(tài)數(shù)據(jù)分配的數(shù)據(jù)空間(比如用malloc之類的函數(shù)取得的空間)。這其中有許多細(xì)節(jié)問題,這里限于篇幅就不多介紹了。系統(tǒng)如果同時(shí)運(yùn)行數(shù)個(gè)相同的程序,它們之間就不能使用同一個(gè)堆棧段和數(shù)據(jù)段。
2.2 Linux下的進(jìn)程控制
在傳統(tǒng)的Unix環(huán)境下,有兩個(gè)基本的操作用于創(chuàng)建和修改進(jìn)程:函數(shù)fork( )用來創(chuàng)建一個(gè)新的進(jìn)程,該進(jìn)程幾乎是當(dāng)前進(jìn)程的一個(gè)完全拷貝;函數(shù)族e(cuò)xec( )用來啟動(dòng)另外的進(jìn)程以取代當(dāng)前運(yùn)行的進(jìn)程。Linux的進(jìn)程控制和傳統(tǒng)的Unix進(jìn)程控制基本一致,只在一些細(xì)節(jié)的地方有些區(qū)別,例如在Linux系統(tǒng)中調(diào)用vfork和fork完全相同,而在有些版本的Unix系統(tǒng)中,vfork調(diào)用有不同的功能。由于這些差別幾乎不影響我們大多數(shù)的編程,在這里我們不予考慮。
2.2.1 fork( )
fork在英文中是”分叉”的意思。為什么取這個(gè)名字呢?因?yàn)橐粋€(gè)進(jìn)程在運(yùn)行中,如果使用了fork,就產(chǎn)生了另一個(gè)進(jìn)程,于是進(jìn)程就”分叉”了,所以這個(gè)名字取得很形象。下面就看看如何具體使用fork,這段程序演示了使用fork的基本框架:
void main(){
int i;
if ( fork() == 0 ) {
/* 子進(jìn)程程序 */
for ( i = 1; i ” );
fgets( command, 256, stdin );
command = 0;
if ( fork() == 0 ) {
/* 子進(jìn)程執(zhí)行此命令 */
execlp( command, command );
/* 如果exec函數(shù)返回,表明沒有正常執(zhí)行命令,打印錯(cuò)誤信息*/
perror( command );
exit( errorno );
}
else {
/* 父進(jìn)程, 等待子進(jìn)程結(jié)束,并打印子進(jìn)程的返回值 */
wait ( &rtn );
printf( ” child process return %d\n”,. rtn );
}
}
}
此程序從終端讀入命令并執(zhí)行之,執(zhí)行完成后,父進(jìn)程繼續(xù)等待從終端讀入命令。熟悉DOS和WINDOWS系統(tǒng)調(diào)用的朋友一定知道DOS/WINDOWS也有exec類函數(shù),其使用方法是類似的,但DOS/WINDOWS還有spawn類函數(shù),因?yàn)镈OS是單任務(wù)的系統(tǒng),它只能將”父進(jìn)程”駐留在機(jī)器內(nèi)再執(zhí)行”子進(jìn)程”,這就是spawn類的函數(shù)。WIN32已經(jīng)是多任務(wù)的系統(tǒng)了,但還保留了spawn類函數(shù),WIN32中實(shí)現(xiàn)spawn函數(shù)的方法同前述UNIX中的方法差不多,開設(shè)子進(jìn)程后父進(jìn)程等待子進(jìn)程結(jié)束后才繼續(xù)運(yùn)行。UNIX在其一開始就是多任務(wù)的系統(tǒng),所以從核心角度上講不需要spawn類函數(shù)。
在這一節(jié)里,我們還要講講system()和popen()函數(shù)。system()函數(shù)先調(diào)用fork(),然后再調(diào)用exec()來執(zhí)行用戶的登錄shell,通過它來查找可執(zhí)行文件的命令并分析參數(shù),最后它么使用wait()函數(shù)族之一來等待子進(jìn)程的結(jié)束。函數(shù)popen()和函數(shù)system()相似,不同的是它調(diào)用pipe()函數(shù)創(chuàng)建一個(gè)管道,通過它來完成程序的標(biāo)準(zhǔn)輸入和標(biāo)準(zhǔn)輸出。這兩個(gè)函數(shù)是為那些不太勤快的程序員設(shè)計(jì)的,在效率和安全方面都有相當(dāng)?shù)娜毕荩诳赡艿那闆r下,應(yīng)該盡量避免。
2.3 Linux下的進(jìn)程間通信
詳細(xì)的講述進(jìn)程間通信在這里絕對(duì)是不可能的事情,而且筆者很難有信心說自己對(duì)這一部分內(nèi)容的認(rèn)識(shí)達(dá)到了什么樣的地步,所以在這一節(jié)的開頭首先向大家推薦著名作者Richard Stevens的著名作品:《Advanced Programming in the UNIX Environment》,它的中文譯本《UNIX環(huán)境高級(jí)編程》已有機(jī)械工業(yè)出版社出版,原文精彩,譯文同樣地道,如果你的確對(duì)在Linux下編程有濃厚的興趣,那么趕緊將這本書擺到你的書桌上或計(jì)算機(jī)旁邊來。說這么多實(shí)在是難抑心中的景仰之情,言歸正傳,在這一節(jié)里,我們將介紹進(jìn)程間通信最最初步和最最簡單的一些知識(shí)和概念。
首先,進(jìn)程間通信至少可以通過傳送打開文件來實(shí)現(xiàn),不同的進(jìn)程通過一個(gè)或多個(gè)文件來傳遞信息,事實(shí)上,在很多應(yīng)用系統(tǒng)里,都使用了這種方法。但一般說來,進(jìn)程間通信(IPC:InterProcess Communication)不包括這種似乎比較低級(jí)的通信方法。Unix系統(tǒng)中實(shí)現(xiàn)進(jìn)程間通信的方法很多,而且不幸的是,極少方法能在所有的Unix系統(tǒng)中進(jìn)行移植(唯一一種是半雙工的管道,這也是最原始的一種通信方式)。而Linux作為一種新興的操作系統(tǒng),幾乎支持所有的Unix下常用的進(jìn)程間通信方法:管道、消息隊(duì)列、共享內(nèi)存、信號(hào)量、套接口等等。下面我們將逐一介紹。
2.3.1 管道
管道是進(jìn)程間通信中最古老的方式,它包括無名管道和有名管道兩種,前者用于父進(jìn)程和子進(jìn)程間的通信,后者用于運(yùn)行于同一臺(tái)機(jī)器上的任意兩個(gè)進(jìn)程間的通信。
無名管道由pipe()函數(shù)創(chuàng)建:
#include
int pipe(int filedis);
參數(shù)filedis返回兩個(gè)文件描述符:filedes為讀而打開,filedes為寫而打開。filedes的輸出是filedes的輸入。下面的例子示范了如何在父進(jìn)程和子進(jìn)程間實(shí)現(xiàn)通信。
#define INPUT 0
#define OUTPUT 1
void main() {
int file_descriptors;
/*定義子進(jìn)程號(hào) */
pid_t pid;
char buf;
int returned_count;
/*創(chuàng)建無名管道*/
pipe(file_descriptors);
/*創(chuàng)建子進(jìn)程*/
if((pid = fork()) == -1) {
printf(“Error in fork\n”);
exit(1);
}
/*執(zhí)行子進(jìn)程*/
if(pid == 0) {
printf(“in the spawned (child) process…\n”);
/*子進(jìn)程向父進(jìn)程寫數(shù)據(jù),關(guān)閉管道的讀端*/
close(file_descriptors);
write(file_descriptors, “test data”, strlen(“test data”));
exit(0);
} else {
/*執(zhí)行父進(jìn)程*/
printf(“in the spawning (parent) process…\n”);
/*父進(jìn)程從管道讀取子進(jìn)程寫的數(shù)據(jù),關(guān)閉管道的寫端*/
close(file_descriptors);
returned_count = read(file_descriptors, buf, sizeof(buf));
printf(“%d bytes of data received from spawned process: %s\n”,
returned_count, buf);
}
}
在Linux系統(tǒng)下,有名管道可由兩種方式創(chuàng)建:命令行方式mknod系統(tǒng)調(diào)用和函數(shù)mkfifo。下面的兩種途徑都在當(dāng)前目錄下生成了一個(gè)名為myfifo的有名管道:
方式一:mkfifo(“myfifo”,”rw”);
方式二:mknod myfifo p
生成了有名管道后,就可以使用一般的文件I/O函數(shù)如open、close、read、write等來對(duì)它進(jìn)行操作。下面即是一個(gè)簡單的例子,假設(shè)我們已經(jīng)創(chuàng)建了一個(gè)名為myfifo的有名管道。
/* 進(jìn)程一:讀有名管道*/
#include
#include
void main() {
FILE * in_file;
int count = 1;
char buf;
in_file = fopen(“mypipe”, “r”);
if (in_file == NULL) {
printf(“Error in fdopen.\n”);
exit(1);
}
while ((count = fread(buf, 1, 80, in_file)) > 0)
printf(“received from pipe: %s\n”, buf);
fclose(in_file);
}
/* 進(jìn)程二:寫有名管道*/
#include
#include
void main() {
FILE * out_file;
int count = 1;
char buf;
out_file = fopen(“mypipe”, “w”);
if (out_file == NULL) {
printf(“Error opening pipe.”);
exit(1);
}
sprintf(buf,”this is test data for the named pipe example\n”);
fwrite(buf, 1, 80, out_file);
fclose(out_file);
}
2.3.2 消息隊(duì)列
消息隊(duì)列用于運(yùn)行于同一臺(tái)機(jī)器上的進(jìn)程間通信,它和管道很相似,事實(shí)上,它是一種正逐漸被淘汰的通信方式,我們可以用流管道或者套接口的方式來取代它,所以,我們對(duì)此方式也不再解釋,也建議讀者忽略這種方式。
2.3.3 共享內(nèi)存
共享內(nèi)存是運(yùn)行在同一臺(tái)機(jī)器上的進(jìn)程間通信最快的方式,因?yàn)閿?shù)據(jù)不需要在不同的進(jìn)程間復(fù)制。通常由一個(gè)進(jìn)程創(chuàng)建一塊共享內(nèi)存區(qū),其余進(jìn)程對(duì)這塊內(nèi)存區(qū)進(jìn)行讀寫。得到共享內(nèi)存有兩種方式:映射/dev/mem設(shè)備和內(nèi)存映像文件。前一種方式不給系統(tǒng)帶來額外的開銷,但在現(xiàn)實(shí)中并不常用,因?yàn)樗刂拼嫒〉膶⑹菍?shí)際的物理內(nèi)存,在Linux系統(tǒng)下,這只有通過限制Linux系統(tǒng)存取的內(nèi)存才可以做到,這當(dāng)然不太實(shí)際。常用的方式是通過shmXXX函數(shù)族來實(shí)現(xiàn)利用共享內(nèi)存進(jìn)行存儲(chǔ)的。
首先要用的函數(shù)是shmget,它獲得一個(gè)共享存儲(chǔ)標(biāo)識(shí)符。
#include
#include
#include
int shmget(key_t key, int size, int flag);
這個(gè)函數(shù)有點(diǎn)類似大家熟悉的malloc函數(shù),系統(tǒng)按照請(qǐng)求分配size大小的內(nèi)存用作共享內(nèi)存。Linux系統(tǒng)內(nèi)核中每個(gè)IPC結(jié)構(gòu)都有的一個(gè)非負(fù)整數(shù)的標(biāo)識(shí)符,這樣對(duì)一個(gè)消息隊(duì)列發(fā)送消息時(shí)只要引用標(biāo)識(shí)符就可以了。這個(gè)標(biāo)識(shí)符是內(nèi)核由IPC結(jié)構(gòu)的關(guān)鍵字得到的,這個(gè)關(guān)鍵字,就是上面之一個(gè)函數(shù)的key。數(shù)據(jù)類型key_t是在頭文件sys/types.h中定義的,它是一個(gè)長整形的數(shù)據(jù)。在我們后面的章節(jié)中,還會(huì)碰到這個(gè)關(guān)鍵字。
當(dāng)共享內(nèi)存創(chuàng)建后,其余進(jìn)程可以調(diào)用shmat()將其連接到自身的地址空間中。
void *shmat(int shmid, void *addr, int flag);
shmid為shmget函數(shù)返回的共享存儲(chǔ)標(biāo)識(shí)符,addr和flag參數(shù)決定了以什么方式來確定連接的地址,函數(shù)的返回值即是該進(jìn)程數(shù)據(jù)段所連接的實(shí)際地址,進(jìn)程可以對(duì)此進(jìn)程進(jìn)行讀寫操作。
linux進(jìn)程間通信用的是posix還是system
linux進(jìn)程間通信的幾種機(jī)制的比較及適用場合
1.# 管道( pipe ):管道是一種半雙工的通信方式,數(shù)據(jù)只能單向流動(dòng),而且只能在具有親緣關(guān)系的進(jìn)程間使用。進(jìn)程的親緣關(guān)系通常是指父子進(jìn)程關(guān)系。
# 有名管道 (named pipe) : 有名管道也是半雙工的通信方式,但是它允許無親緣關(guān)系進(jìn)程間的通信。
# 信號(hào)量( semophore ) : 信號(hào)量是一個(gè)計(jì)數(shù)器,可以用來控制多個(gè)進(jìn)程對(duì)共享資源的訪問。它常作為一種鎖機(jī)制,防止某進(jìn)程正在訪問共享資源時(shí),其他進(jìn)程也訪問該資源。因此,主要作為進(jìn)程間以及同一進(jìn)程內(nèi)不同線程之間的同步手段。
# 消息隊(duì)列( message queue ) : 消息隊(duì)列是由消息的鏈表,存放在內(nèi)核中并由消息隊(duì)列標(biāo)識(shí)符標(biāo)識(shí)。消息隊(duì)列克服了信號(hào)傳遞信息少、管道只能承載無格式字節(jié)流以及緩沖區(qū)大小受限等缺點(diǎn)。
# 信號(hào) ( sinal ) : 信號(hào)是一種比較復(fù)雜的通信方式,用于通知接收進(jìn)程某個(gè)事件已經(jīng)發(fā)生。
#共享內(nèi)存( shared memory):共享內(nèi)大晌存就是映射一段能被其他進(jìn)程所訪問的內(nèi)存,這段共享內(nèi)存由
一個(gè)進(jìn)程創(chuàng)建,但多個(gè)進(jìn)程都可以訪問。共享內(nèi)存是最快的IPC方式,它是針對(duì)其他進(jìn)程間通信方式運(yùn)行效率低而專門設(shè)計(jì)的。它往往與其他通信機(jī)制,如信號(hào)量,配合使用,來實(shí)現(xiàn)進(jìn)程間的同步和通信衡坦。
# 套接字( socket ) : 套解口也是一種進(jìn)程間通信機(jī)制,與其他通信機(jī)制不同的是,它咐仿桐可用于不同及其間的進(jìn)程通信。
linux named pipe的介紹就聊到這里吧,感謝你花時(shí)間閱讀本站內(nèi)容,更多關(guān)于linux named pipe,Linux命名管道的使用方法,一個(gè)Linux多進(jìn)程編程?,linux進(jìn)程間通信用的是posix還是system的信息別忘了在本站進(jìn)行查找喔。
香港云服務(wù)器機(jī)房,創(chuàng)新互聯(lián)(www.cdcxhl.com)專業(yè)云服務(wù)器廠商,回大陸優(yōu)化帶寬,安全/穩(wěn)定/低延遲.創(chuàng)新互聯(lián)助力企業(yè)出海業(yè)務(wù),提供一站式解決方案。香港服務(wù)器-免備案低延遲-雙向CN2+BGP極速互訪!
網(wǎng)頁名稱:Linux命名管道的使用方法(linuxnamedpipe)
本文URL:http://m.fisionsoft.com.cn/article/cohhppj.html


咨詢
建站咨詢
