日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > linux >内容正文

linux

linux 管道文件上机总结,[转载]LINUX 管道 fifo 等总结

發(fā)布時(shí)間:2023/12/10 linux 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux 管道文件上机总结,[转载]LINUX 管道 fifo 等总结 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Linux進(jìn)程通信:命名管道FIFO小結(jié)

Linux下進(jìn)程之間通信可以用命名管道FIFO完成。命名管道是一種特殊類(lèi)型的文件,因?yàn)長(zhǎng)inux中所有事物都是文件,它在文件系統(tǒng)中以文件名的形式存在。

在程序中,我們可以使用兩個(gè)不同的函數(shù)調(diào)用來(lái)建立管道:

#include

#include

int mkfifo(const char *filename,

mode_t mode);

int mknode(const char *filename,

mode_t mode | S_IFIFO, (dev_t) 0 );

下面先來(lái)創(chuàng)建一個(gè)管道:

#include?

#include?

#include?

#include?

intmain()

{

intres?=?mkfifo("/tmp/my_fifo",?0777);

if(res?==?0)

{

printf("FIFO?created/n");

}

exit(EXIT_SUCCESS);

}

#include

#include

#include

#include

int main()

{

int res = mkfifo("/tmp/my_fifo", 0777);

if (res == 0)

{

printf("FIFO created/n");

}

exit(EXIT_SUCCESS);

}

編譯這個(gè)程序:

gcc –o fifo1.c

fifo

運(yùn)行這個(gè)程序:

$ ./fifo1

用ls命令查看所創(chuàng)建的管道

$ ls -lF

/tmp/my_fifo

prwxr-xr-x 1 root root 0 05-08

20:10 /tmp/my_fifo|

注意:ls命令的輸出結(jié)果中的第一個(gè)字符為p,表示這是一個(gè)管道。最后的|符號(hào)是由ls命令的-F選項(xiàng)添加的,它也表示是這是一個(gè)管道。

雖然,我們所設(shè)置的文件創(chuàng)建模式為“0777”,但它被用戶(hù)掩碼(umask)設(shè)置(022)給改變了,這與普通文件創(chuàng)建是一樣的,所以文件的最終模式為755。

打開(kāi)FIFO一個(gè)主要的限制是,程序不能是O_RDWR模式打開(kāi)FIFO文件進(jìn)行讀寫(xiě)操作,這樣做的后果未明確定義。這個(gè)限制是有道理的,因?yàn)槲覀兪褂肍IFO只是為了單身傳遞數(shù)據(jù),所以沒(méi)有必要使用O_RDWR模式。如果一個(gè)管道以讀/寫(xiě)方式打開(kāi)FIFO,進(jìn)程就會(huì)從這個(gè)管道讀回它自己的輸出。如果確實(shí)需要在程序之間雙向傳遞數(shù)據(jù),最好使用一對(duì)FIFO,一個(gè)方向使用一個(gè)。

當(dāng)一個(gè)Linux進(jìn)程被阻塞時(shí),它并不消耗CPU資源,這種進(jìn)程的同步方式對(duì)CPU而言是非常有效率的。

有關(guān)Linux下命名管道FIFO的讀寫(xiě)規(guī)則可以參見(jiàn)之前所寫(xiě)的一篇文章:。

一、實(shí)驗(yàn):使用FIFO實(shí)現(xiàn)進(jìn)程間通信

兩個(gè)獨(dú)立的程序:

1.

生產(chǎn)者程序,它在需要時(shí)創(chuàng)建管道,然后盡可能快地向管道中寫(xiě)入數(shù)據(jù)。

2.

消費(fèi)者程序,它從FIFO中讀取數(shù)據(jù)并丟棄它們。

生產(chǎn)者程序fifo2.c:

#include?

#include?

#include?

#include?

#include?

#include?

#include?

#define?FIFO_NAME?"/tmp/Linux/my_fifo"

#define?BUFFER_SIZE?PIPE_BUF

#define?TEN_MEG?(1024?*?1024?*?10)

intmain()

{

intpipe_fd;

intres;

intopen_mode?=?O_WRONLY;

intbytes?=?0;

charbuffer[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);

if(pipe_fd?!=?-1)

{

while(bytes?

{

res?=?write(pipe_fd,?buffer,?BUFFER_SIZE);

if(res?==?-1)

{

fprintf(stderr,?"Write?error?on?pipe/n");

exit(EXIT_FAILURE);

}

bytes?+=?res;

}

close(pipe_fd);

}

else

{

exit(EXIT_FAILURE);

}

printf("Process?%d?finish/n",?getpid());

exit(EXIT_SUCCESS);

}

#include

#include

#include

#include

#include

#include

#include

#define FIFO_NAME "/tmp/Linux/my_fifo"

#define BUFFER_SIZE PIPE_BUF

#define TEN_MEG (1024 * 1024 * 10)

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);

if (pipe_fd != -1)

{

while (bytes < TEN_MEG)

{

res = write(pipe_fd, buffer, BUFFER_SIZE);

if (res == -1)

{

fprintf(stderr, "Write error on pipe/n");

exit(EXIT_FAILURE);

}

bytes += res;

}

close(pipe_fd);

}

else

{

exit(EXIT_FAILURE);

}

printf("Process %d finish/n", getpid());

exit(EXIT_SUCCESS);

}

消費(fèi)者程序fifo3.c:

#include?

#include?

#include?

#include?

#include?

#include?

#include?

#define?FIFO_NAME?"/tmp/Linux/my_fifo"

#define?BUFFER_SIZE?PIPE_BUF

intmain()

{

intpipe_fd;

intres;

intopen_mode?=?O_RDONLY;

charbuffer[BUFFER_SIZE?+?1];

intbytes?=?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;

}while(res?>?0);

close(pipe_fd);

}

else

{

exit(EXIT_FAILURE);

}

printf("Process?%d?finished,?%d?bytes?read/n",?getpid(),?bytes);

exit(EXIT_SUCCESS);

}

#include

#include

#include

#include

#include

#include

#include

#define FIFO_NAME "/tmp/Linux/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;

}while(res > 0);

close(pipe_fd);

}

else

{

exit(EXIT_FAILURE);

}

printf("Process %d finished, %d bytes read/n", getpid(), bytes);

exit(EXIT_SUCCESS);

}

編譯這兩個(gè)程序:

gcc –o fifo2

fifo2.c

gcc –o fifo3

fifo3.c

運(yùn)行這兩個(gè)程序:

[root@localhost chaper12]# ./fifo2

&

à后臺(tái)執(zhí)行,寫(xiě)數(shù)據(jù)

[2] 23121

Process 23121 opening FIFO

O_WRONLY

[root@localhost chaper12]# time

./fifo3à讀數(shù)據(jù)

Process 24155 opeining FIFO

O_RDONLY

Process 23121 result

3

Process 24155 result

3

Process 23121

finish

Process 24155 finished, 10485760

bytes read

[2]- Done

./fifo2

real 0m0.214s

user 0m0.000s

sys 0m0.179s

以上兩個(gè)程序均是使用阻塞模式FIFO。Linux會(huì)安排好這兩個(gè)進(jìn)程之間的調(diào)試,使它們?cè)诳梢赃\(yùn)行的時(shí)候運(yùn)行,在不能運(yùn)行的時(shí)候阻塞。因此,寫(xiě)進(jìn)程將在管道滿(mǎn)時(shí)阻塞,讀進(jìn)程將在管道空時(shí)阻塞。

虛擬機(jī)上,time命令顯示,讀進(jìn)程只運(yùn)行了0.2秒的時(shí)間,卻讀取了10M字節(jié)的數(shù)據(jù)。這說(shuō)明管道在程序之間傳遞數(shù)據(jù)是非常有效的。

二、實(shí)驗(yàn):使用FIFO的客戶(hù)/服務(wù)器應(yīng)用程序

利用FIFO實(shí)現(xiàn)一個(gè)客戶(hù)/服務(wù)器的應(yīng)用程序,服務(wù)器進(jìn)程接受請(qǐng)求,對(duì)它們進(jìn)程處理,最后把結(jié)果數(shù)據(jù)返回給發(fā)送請(qǐng)求的客戶(hù)方。

首先建立一個(gè)頭文件client.h,它定義了客戶(hù)和服務(wù)器程序都要用到的數(shù)據(jù)結(jié)構(gòu),并包含了必要的頭文件。

#include?

#include?

#include?

#include?

#include?

#include?

#include?

#define?SERVER_FIFO_NAME?"/tmp/Linux/chaper12/server_fifo"

#define?CLIENT_FIFO_NAME?"/tmp/Linux/chaper12/client_%d_fifo"

#define?BUFFER_SIZE?PIPE_BUF

#define?MESSAGE_SIZE?20

#define?NAME_SIZE?256

typedefstructmessage

{

pid_t?client_pid;

chardata[MESSAGE_SIZE?+?1];

}message;

#include

#include

#include

#include

#include

#include

#include

#define SERVER_FIFO_NAME "/tmp/Linux/chaper12/server_fifo"

#define CLIENT_FIFO_NAME "/tmp/Linux/chaper12/client_%d_fifo"

#define BUFFER_SIZE PIPE_BUF

#define MESSAGE_SIZE 20

#define NAME_SIZE 256

typedef struct message

{

pid_t client_pid;

char data[MESSAGE_SIZE + 1];

}message;

接下來(lái)是服務(wù)器程序server.c,在這一部分,是以只讀阻塞模式打開(kāi)服務(wù)器管道,用于接收客戶(hù)發(fā)送過(guò)來(lái)的數(shù)據(jù),這些數(shù)據(jù)采用message結(jié)構(gòu)體封裝。

#include?"client.h"

intmain()

{

intserver_fifo_fd;

intclient_fifo_fd;

intres;

charclient_fifo_name[NAME_SIZE];

message?msg;

char*p;

if(mkfifo(SERVER_FIFO_NAME,?0777)?==?-1)

{

fprintf(stderr,?"Sorry,?create?server?fifo?failure!/n");

exit(EXIT_FAILURE);

}

server_fifo_fd?=?open(SERVER_FIFO_NAME,?O_RDONLY);

if(server_fifo_fd?==?-1)

{

fprintf(stderr,?"Sorry,?server?fifo?open?failure!/n");

exit(EXIT_FAILURE);

}

sleep(5);

while(res?=?read(server_fifo_fd,?&msg,sizeof(msg))?>?0)

{

p?=?msg.data;

while(*p)

{

*p?=?toupper(*p);

++p;

}

sprintf(client_fifo_name,?CLIENT_FIFO_NAME,?msg.client_pid);

client_fifo_fd?=?open(client_fifo_name,?O_WRONLY);

if(client_fifo_fd?==?-1)

{

fprintf(stderr,?"Sorry,?client?fifo?open?failure!/n");

exit(EXIT_FAILURE);

}

write(client_fifo_fd,?&msg,?sizeof(msg));

close(client_fifo_fd);

}

close(server_fifo_fd);

unlink(SERVER_FIFO_NAME);

exit(EXIT_SUCCESS);

}

#include "client.h"

int main()

{

int server_fifo_fd;

int client_fifo_fd;

int res;

char client_fifo_name[NAME_SIZE];

message msg;

char *p;

if (mkfifo(SERVER_FIFO_NAME, 0777) == -1)

{

fprintf(stderr, "Sorry, create server fifo failure!/n");

exit(EXIT_FAILURE);

}

server_fifo_fd = open(SERVER_FIFO_NAME, O_RDONLY);

if (server_fifo_fd == -1)

{

fprintf(stderr, "Sorry, server fifo open failure!/n");

exit(EXIT_FAILURE);

}

sleep(5);

while (res = read(server_fifo_fd, &msg, sizeof(msg)) > 0)

{

p = msg.data;

while (*p)

{

*p = toupper(*p);

++p;

}

sprintf(client_fifo_name, CLIENT_FIFO_NAME, msg.client_pid);

client_fifo_fd = open(client_fifo_name, O_WRONLY);

if (client_fifo_fd == -1)

{

fprintf(stderr, "Sorry, client fifo open failure!/n");

exit(EXIT_FAILURE);

}

write(client_fifo_fd, &msg, sizeof(msg));

close(client_fifo_fd);

}

close(server_fifo_fd);

unlink(SERVER_FIFO_NAME);

exit(EXIT_SUCCESS);

}

客戶(hù)端程序client.c,這個(gè)程序用于向服務(wù)器發(fā)送消息,并接收來(lái)自服務(wù)器的回復(fù)。

#include?"client.h"

intmain()

{

intserver_fifo_fd;

intclient_fifo_fd;

intres;

charclient_fifo_name[NAME_SIZE];

message?msg;

msg.client_pid?=?getpid();

sprintf(client_fifo_name,?CLIENT_FIFO_NAME,?msg.client_pid);

if(mkfifo(client_fifo_name,?0777)?==?-1)

{

fprintf(stderr,?"Sorry,?create?client?fifo?failure!/n");

exit(EXIT_FAILURE);

}

server_fifo_fd?=?open(SERVER_FIFO_NAME,?O_WRONLY);

if(server_fifo_fd?==?-1)

{

fprintf(stderr,?"Sorry,?open?server?fifo?failure!/n");

exit(EXIT_FAILURE);

}

sprintf(msg.data,?"Hello?from?%d",?msg.client_pid);

printf("%d?sent?%s?",?msg.client_pid,?msg.data);

write(server_fifo_fd,?&msg,?sizeof(msg));

client_fifo_fd?=?open(client_fifo_name,?O_RDONLY);

if(client_fifo_fd?==?-1)

{

fprintf(stderr,?"Sorry,?client?fifo?open?failure!/n");

exit(EXIT_FAILURE);

}

res?=?read(client_fifo_fd,?&msg,?sizeof(msg));

if(res?>?0)

{

printf("received:%s/n",?msg.data);

}

close(client_fifo_fd);

close(server_fifo_fd);

unlink(client_fifo_name);

exit(EXIT_SUCCESS);

}

#include "client.h"

int main()

{

int server_fifo_fd;

int client_fifo_fd;

int res;

char client_fifo_name[NAME_SIZE];

message msg;

msg.client_pid = getpid();

sprintf(client_fifo_name, CLIENT_FIFO_NAME, msg.client_pid);

if (mkfifo(client_fifo_name, 0777) == -1)

{

fprintf(stderr, "Sorry, create client fifo failure!/n");

exit(EXIT_FAILURE);

}

server_fifo_fd = open(SERVER_FIFO_NAME, O_WRONLY);

if (server_fifo_fd == -1)

{

fprintf(stderr, "Sorry, open server fifo failure!/n");

exit(EXIT_FAILURE);

}

sprintf(msg.data, "Hello from %d", msg.client_pid);

printf("%d sent %s ", msg.client_pid, msg.data);

write(server_fifo_fd, &msg, sizeof(msg));

client_fifo_fd = open(client_fifo_name, O_RDONLY);

if (client_fifo_fd == -1)

{

fprintf(stderr, "Sorry, client fifo open failure!/n");

exit(EXIT_FAILURE);

}

res = read(client_fifo_fd, &msg, sizeof(msg));

if (res > 0)

{

printf("received:%s/n", msg.data);

}

close(client_fifo_fd);

close(server_fifo_fd);

unlink(client_fifo_name);

exit(EXIT_SUCCESS);

}

編譯程序:

gcc –o server

server.c

gcc –o client

client.c

測(cè)試這個(gè)程序,我們需要一個(gè)服務(wù)器進(jìn)程和多個(gè)客戶(hù)進(jìn)程。為了讓多個(gè)客戶(hù)進(jìn)程在同一時(shí)間啟動(dòng),我們使用了shell命令:

[root@localhost chaper12]# ./server

&

[26] 5171

[root@localhost chaper12]# for i in

1 2 3 4 5; do ./client & done

[27] 5172

[28] 5173

[29] 5174

[30] 5175

[31] 5176

[root@localhost chaper12]# 5172

sent Hello from 5172 received:HELLO FROM 5172

5173 sent Hello from 5173

received:HELLO FROM 5173

5174 sent Hello from 5174

received:HELLO FROM 5174

5175 sent Hello from 5175

received:HELLO FROM 5175

5176 sent Hello from 5176

received:HELLO FROM 5176

分析這個(gè)例子,服務(wù)器以只讀模式創(chuàng)建它的FIFO并阻塞,直到第一個(gè)客戶(hù)以寫(xiě)方式打開(kāi)同一現(xiàn)個(gè)FIFO來(lái)建立連接為止。此時(shí),服務(wù)器進(jìn)程解除阻塞并執(zhí)行sleep語(yǔ)句,這使得來(lái)自客戶(hù)的數(shù)據(jù)排除等候。在實(shí)際應(yīng)用程序中,應(yīng)該把sleep語(yǔ)句刪除,這里面只是為了演示當(dāng)有多個(gè)客戶(hù)請(qǐng)求同時(shí)到達(dá)時(shí),程序的正確操作方法。

與此同時(shí),在客戶(hù)端打開(kāi)服務(wù)器FIFO后,它創(chuàng)建自己唯一的一個(gè)命名管道以讀取服務(wù)器返回的數(shù)據(jù)。完成這些工作后,客戶(hù)發(fā)送數(shù)據(jù)給服務(wù)器(如果管道滿(mǎn)或服務(wù)器仍處于休眠就阻塞),并阻塞于對(duì)自己FIFO的read調(diào)用上,等待服務(wù)器響應(yīng)。

接收到來(lái)自客戶(hù)的數(shù)據(jù)后,服務(wù)器處于它,然后以寫(xiě)的方式打開(kāi)客戶(hù)管道并將處理后的數(shù)據(jù)返回,這將解除客戶(hù)端的阻塞狀態(tài),客戶(hù)程序就可以從自己的管道里面讀取服務(wù)器返回的數(shù)據(jù)了。

整個(gè)處理過(guò)程不斷重復(fù),直到最后一個(gè)客戶(hù)關(guān)閉服務(wù)器管道為止,這將使服務(wù)器的read調(diào)用失敗(返回0),因?yàn)橐呀?jīng)沒(méi)有進(jìn)程以寫(xiě)方式打開(kāi)服務(wù)器管道了。如果這是一個(gè)真正的服務(wù)器進(jìn)程的話(huà),它還需要繼續(xù)等待其他客戶(hù)的請(qǐng)求,我們就需要對(duì)它進(jìn)行修改,有兩種方法:

(1)對(duì)它自己的服務(wù)器管道打開(kāi)一個(gè)文件描述符,這樣read調(diào)用將阻塞而不是返回0。

(2)當(dāng)read調(diào)用返回0時(shí),關(guān)閉并重新打開(kāi)服務(wù)器管道,使服務(wù)器進(jìn)程阻塞在open調(diào)用處以等待客戶(hù)的到來(lái),就像它最初啟動(dòng)時(shí)那樣。

總結(jié)

以上是生活随笔為你收集整理的linux 管道文件上机总结,[转载]LINUX 管道 fifo 等总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。