管道通訊——FIFO的代碼實現

1、用到的函數
umask
        linux中的 umask 函數主要用於:在建立新文件或目錄時 屏蔽掉新文件或目錄不該有的訪問容許權限。
        文件的訪問容許權限共有9種,分別是:r w x r w x r w x(它們分別表明:用戶讀 用戶寫 用戶執行 組讀 組寫 組執行 其它讀 其它寫 其它執行)
        其實這個函數的做用,就是設置容許當前進程建立文件或者目錄最大可操做的權限,好比這裏設置爲0,它的意思就是0取反再建立文件時權限相與,也就是:(~0) &            mode 等於八進制的值0777 & mode了,這樣就是給後面的代碼調用函數mkdir給出最大的權限,避免了建立目錄或文件的權限不肯定性
第一位表明了一項特別的安全特性,叫做粘着位(sticky bit),後面的3位表示文件或目錄對應的umask八進制值。要理解umask是怎麼工做的,得先理解八進制模式的安全性設置。
八進制模式的安全性設置先獲取這3個rwx權限的值,而後將其轉換成3位二進制值,用一個八進制值來表示。在這個二進制表示中,每一個位置表明一個二進制位。所以,若是讀權限是惟一置位的權限,權限值就是r--,轉換成二進制值就是100,表明的八進制值是4。下表列出了可
能會遇到的組合。
 

S_IFIFO|0666 
        S_IFIFO|0666指明建立有名管道且存取權限爲0666,即建立者/其同組用戶/其餘用戶都可讀可寫

mknod(FIFO_FILE,S_IFIFO|0666,0);
函數mknod參數中path爲建立的命名管道的全路徑名:mod爲建立的命名管道的模式,指明其存取權限;dev爲設備值,該值取決於⽂件建立的種類,它只在建立設備⽂件時纔會⽤到。這個函數調⽤成功都返回0,失敗返回-1

perror
        C 庫函數 void perror(const char *str) 把一個描述性錯誤消息輸出到標準錯誤 stderr。首先輸出字符串         str,後跟一個冒號,而後是一個空格
        str -- 這是 C 字符串,包含了一個自定義消息,將顯示在本來的錯誤消息以前
        該函數不返回任何值

exit是一個函數,進程退出時會有一個值,exit函數的參數就是指明進程退出的返回值,操做系統根據這個值來判斷是不是正常退出。好比說:
exit(1)是異常退出,好比你的代碼在出現不該該出現的分枝,要求終止程序的時候就用exit(1)
exit(0)是正常退出,就是你認爲代碼一切正常的時候的退出

open
open函數屬於Linux中系統IO,用於「打開」文件,代碼打開一個文件意味着得到了這個文件的訪問句柄。
int fd = open(參數1,參數2,參數3);
int fd = open(const char *pathname,int flags,mode_t mode);
1.句柄(file descriptor 簡稱fd)
首先每一個文件都屬於本身的句柄,例如標準輸入是0,標準輸出是1,標準出錯是2。
每打開一個文件就會返回句柄來操做這個文件,通常是從3開始,而後4,5,6一直下去。
close(fd)以後句柄就返回給系統,例如打開一個文件後fd是3,close以後再打開另一個文件也仍是3,但表明的文件不同了。
2.使用open前須要先包含頭文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
3.參數1(pathname)
即將要打開的文件路徑,例如:「a.txt」當前目錄下的a.txt文件
4.參數2(flags)
flags分爲兩類:主類,副類
主類:O_RDONLY 以只讀方式打開   /   O_WRONLY 以只寫方式打開   /O_RDWR 以可讀可寫方式打開
三這是互斥的
副類:
O_CREAT 若是文件不存在則建立該文件
O_EXCL 若是使用O_CREAT選項且文件存在,則返回錯誤消息
O_NOCTTY 若是文件爲終端,那麼終端不能夠調用open系統調用的那個進程的控制終端
O_TRUNC 若是文件已經存在澤刪除文件中原有數據
O_APPEND 以追加的方式打開
主副能夠配合使用,例如:O_RDWR|O_CREAT|O_TRUNC
5.參數3(mode)
mode:若是文件被新建,指定其權限未mode
mode是八進制權限碼,0777表示文件全部者   該文件用戶組     其餘用戶都有可讀可寫可執行權限

ssize_t
        ssize_t是有符號整型,在32位機器上等同與int,在64位機器上等同與long int

read()
函數定義:ssize_t read(int fd, void * buf, size_t count);
函數說明:read()會把參數fd所指的文件傳送count 個字節到buf 指針所指的內存中。
返回值:返回值爲實際讀取到的字節數, 若是返回0, 表示已到達文件尾或是無可讀取的數據。若參數count 爲0, 則read()不會有做用並返回0。
注意:read時fd中的數據若是小於要讀取的數據,就會引發阻塞。

fflush
在使用多個輸出函數連續進行屢次輸出時,有可能發現輸出錯誤。由於下一個數據在上一個數據還沒輸出完畢,還在輸出緩衝區中時,下一個printf就把另外一個數據加入輸出緩衝區,結果沖掉了原來的數據,出現輸出錯誤。 在 printf();後加上fflush(stdout); 強制立刻輸出,避免錯誤

close (fd)
每打開一個文件就會返回句柄來操做這個文件,通常是從3開始,而後4,5,6一直下去。
close(fd)以後句柄就返回給系統,例如打開一個文件後fd是3,close以後再打開另一個文件也仍是3,但表明的文件不同了

write()
函數定義:ssize_t write (int fd, const void * buf, size_t count);
函數說明:write()會把參數buf所指的內存寫入count個字節到參數放到所指的文件內。
返回值:若是順利write()會返回實際寫入的字節數。當有錯誤發生時則返回-1,錯誤代碼存入errno中

 
2、代碼實現
read端代碼
 1 #include<stdlib.h>
 2 #include<stdio.h>
 3 #include<sys/types.h>
 4 #include<sys/stat.h>
 5 #include<fcntl.h>
 6 #include<errno.h>
 7 #define PATH "./fifo"
 8 #define SIZE 128
 9 int main()
10 {
11 umask(0);
12 if (mkfifo (PATH,0666|S_IFIFO) == -1)
13 {
14 perror ("mkefifo error");
15 exit(0);
16 }
17 int fd = open (PATH,O_RDONLY);
18 if (fd<0)
19 {
20   printf("open fd is error\n");
21   return 0;
22 }
23   
24 char Buf[SIZE];
25 while(1){
26 ssize_t s = read(fd,Buf,sizeof(Buf));
27 if (s<0)
28 {
29   perror("read error");
30   exit(1);
31 }
32 else if (s == 0)
33 {
34   printf("client quit! i shoud quit!\n");
35   break;
36 }
37 else
38 {
39   Buf[s] = '\0';
40   printf("client# %s ",Buf);
41   fflush(stdout);
42 }
43 }
44 close (fd);
45 return 3;
46 }

 


write端代碼
 1 #include<stdlib.h>
 2 #include<stdio.h>
 3 #include<unistd.h>
 4 #include<sys/types.h>
 5 #include<sys/stat.h>
 6 #include<string.h>
 7 #include<errno.h>
 8 #include<fcntl.h>
 9   
10 #define PATH "./fifo"
11 #define SIZE 128
12 int main()
13 {
14 int fd = open(PATH,O_WRONLY);
15 if (fd < 0)
16 {
17   perror("open error");
18   exit(0);
19 }
20   
21 char Buf[SIZE];
22 while(1)
23 {
24   printf("please Enter#:");
25   fflush(stdout);
26   ssize_t s = read(0,Buf,sizeof(Buf));
27   if (s<0)
28   {
29    perror("read is failed");
30    exit(1);
31   }
32   else if(s==0)
33   {
34    printf("read is closed!");
35    return 1;
36   }
37   else{
38    Buf[s]= '\0';
39    write(fd,Buf,strlen(Buf));
40   }
41 }
42 return 0;
43 }

3、實例展現html

write端
read端
4、存在的問題
數據溢出了怎麼辦?
當這種狀況發生時,隨後對管道的write()調用將默認地被阻塞,等待某些數據被讀取,以便騰出足夠的空間供write()調用寫。
這個過程用到了fflush函數。
在 printf();後加上fflush(stdout); 強制立刻輸出,避免錯誤
相關文章
相關標籤/搜索