1 命名管道(FIFO)
????? 管道應用的一個重大缺陷就是沒有名字,因此只能用于親緣進程之間的通信。 后來從管道為基礎提出命名管道(named pipe,F(xiàn)IFO)的概念,該限制得到了克服。 FIFO不同于管道之處在于它提供一個路徑名與之關聯(lián),以FIFO的文件形式存在于文件系統(tǒng)中。這樣,即使與FIFO的創(chuàng)建進程不存在親緣關系的進程,只要可以訪問該路徑,就能夠彼此通過FIFO相互通信(能夠訪問該路徑的進程以及FIFO的創(chuàng)建進程之間),因此,通過FIFO不相關的進程也能交換數(shù)據(jù)。 值得注意的是,F(xiàn)IFO嚴格遵循先進先出(first in first out),對管道及FIFO的讀總是從開始處返回數(shù)據(jù),對它們的寫則把數(shù)據(jù)添加到末尾。它們不支持諸如lseek()等文件定位操作。
2 命名管道的創(chuàng)建
#include <sys/types.h>
#include <sys/stat.h>
int
mkfifo(
const
char
*pathname,
//
文件的路徑
mode_t mode
//和open函數(shù)mode一樣
);
如果pathname路徑下的文件已經(jīng)存在,則mkfifo返回-1,errono將會返回EEXIST。
?
3 命名管道操作
?????? FIFO在文件系統(tǒng)中表現(xiàn)為一個文件,大部分的系統(tǒng)文件調用都可以在FIFO上面,比如:read,open,write,close,unlink,stat等函數(shù),但是seek函數(shù)不能對FIFO調用。
? ? ? 可以調用open打開FIFO,請注意以下方面:?
?????????? A 當以阻塞(未指定O_NONBLOCK)方式只讀打開FIFO的時候,則將會被阻塞,直到有其他進程以寫方式打開該FIFO。??? ? ? ?? B 類似的,當以阻塞(未指定O_NONBLOCK)方式只寫打開FIFO的時候,則將會被阻塞,直到有其他進程以讀方式打開該FIFO
?????????? C 當以非阻塞方式(指定O_NONBLOCK)方式只讀打開FIFO的時候,則立即返回。當只寫open時,如果沒有進程為讀打開FIFO,則返回-1,其errno是ENXIO
4 應用實例
???? 本例為一個client-server模式,服務器端將會創(chuàng)建一個聞名fifo文件(本例中為“/tmp/server”),并讀取該fifo文件。客戶端則打開該fifo文件,并把其請求寫入該FIFO文件。服務器端讀取該命令并執(zhí)行之。
???? 服務器端的代碼為:
#include <unistd.h>
#include
<stdlib.h>
#include
<stdio.h>
#include
<
string
.h>
#include
<unistd.h>
#include
<fcntl.h>
#include
<limits.h>
#include
<sys/types.h>
#include
<sys/stat.h>
#include
<ctype.h>
#define
SERVER_FIFO_NAME "/tmp/serv_fifo"
#define
CLIENT_FIFO_NAME "/tmp/cli_%d_fifo"
#define
BUFFER_SIZE 20
struct
data_to_pass_st{
pid_t client_pid;
char
some_data[BUFFER_SIZE-
1
];
};
int
main(){
int
server_fifo_fd,client_fifo_fd;
struct
data_to_pass_st mydata;
int
read_res;
char
client_fifo[
256
];
char
*
tmp_char_ptr;
mkfifo(SERVER_FIFO_NAME,
0777
);
server_fifo_fd
=
open(SERVER_FIFO_NAME,O_RDONLY);
if
(server_fifo_fd==-
1
){
fprintf(stderr,
"
Server fifo failure\n
"
);
exit(EXIT_FAILURE);
}
sleep(
10
);
do
{
read_res
=read(server_fifo_fd,&mydata,
sizeof
(mydata));
if
(read_res>
0
){
tmp_char_ptr
=
my_data.some_data;
while
(*tmp_char_ptr>
0
){
//
把some_data中的所有字符全部轉換為大寫
*tmp_char_ptr=toupper(*
tmp_char_ptr);
tmp_char_ptr
++
;
}
sprintf(client_fifo,CLIENT_FIFO_NAME,my_data.client_pid);
client_fifo_fd
=
open(client_fifo,O_WRONLY);
if
(client_fifo_fd!=-
1
){
write(client_fifo_fd,
&my_data,
sizeof
(my_data));
close(client_fifo_fd);
}
}
}
while
(read_res>
0
);
close(server_fifo_fd);
unlink(SERVER_FIFO_NAME);
exit(EXIT_SUCCESS);
}
客戶端代碼為:
#include <unistd.h>
#include
<stdlib.h>
#include
<stdio.h>
#include
<
string
.h>
#include
<unistd.h>
#include
<fcntl.h>
#include
<limits.h>
#include
<sys/types.h>
#include
<sys/stat.h>
#include
<ctype.h>
#define
SERVER_FIFO_NAME "/tmp/serv_fifo"
#define
CLIENT_FIFO_NAME "/tmp/cli_%d_fifo"
#define
BUFFER_SIZE 20
struct
data_to_pass_st{
pid_t client_pid;
char
some_data[BUFFER_SIZE-
1
];
};
int
main(){
int
server_fifo_fd,client_fifo_fd;
struct
data_to_pass_st my_data;
int
times_to_send;
char
client_fifo[
256
];
server_fifo_fd
=
open(SERVER_FIFO_NAME,O_WRONLY);
if
(server_fifo_fd==-
1
){
fprintf(stderr,
"
Sorry,no server\n
"
);
exit(EXIT_FAILURE);
}
my_data.client_pid
=
getpid();
sprintf(client_fifo,CLIENT_FIFO_NAME,my_data.client_pid);
if
(mkfifo(client_fifo,
0777
)==-
1
){
fprintf(stderr,
"
Sorry,can't make %s\n
"
,client_fifo);
exit(EXIT_FAILURE);
}
for
(times_to_send=
0
;times_to_send<
5
;times_to_send++
){
sprintf(my_data.some_data,
"
Hello from %d
"
,my_data.client_pid,my_data.some_data);
write(server_fifo_fd,
&my_data,
sizeof
(my_data));
client_fifo_fd
=
open(client_fifo,O_RDONLY);
if
(client_fifo_fd!=-
1
){
if
(read(client_fifo_fd,&my_data,
sizeof
(my_data))>
0
){
printf(
"
received:%s\n
"
,my_data.some_data);
}
close(client_fifo_fd);
}
}
close(server_fifo_fd);
unlink(client_fifo);
exit(EXIT_SUCCESS);
}
5 總結
???? 與管道相比,F(xiàn)IFO最大的特點就是其在文件系統(tǒng)中有fifo文件存在,這樣就可以做到進程間通信。
6? FIFO的缺點
?????
當然FIFO也有它的局限性。客戶端可以發(fā)請求到服務器,但前提是要知道一個公共的FIFO通道,
對于實現(xiàn)服務器回傳應答到客戶端的問題,可以通過為每一個客戶端創(chuàng)建一個專用的FIFO,來實現(xiàn)回傳應答
。但也有不足,
服務器會同時應答成千上萬個客戶端,創(chuàng)建如此多的FIFO是否會使系統(tǒng)負載過大,相應的如何判斷客戶端是否因意外而崩潰成為難題,或者客戶端不讀取應答直接退出,所以服務器必須處理SIGPIPE信號,并做相應處理。(當沒有進程為讀打開FIFO文件時,write函數(shù)進行寫操作會產(chǎn)生SIGPIPE信號)
更多文章、技術交流、商務合作、聯(lián)系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

