ipc - demo for pipe

創建管道函數:

 

#include <sys/types.h>

#include <sys/stat.h>

int mkfifo(const char * pathname, mode_t mode)

函數說明  參數pathname 指向欲打開的文件路徑字符串。下列是參數flags 所能使用的旗標:
S_IRWXU00700 
權限,代表該文件所有者具有可讀、可寫及可執行的權限。
S_IRUSR 
S_IREAD00400權限,代表該文件所有者具有可讀取的權限。
S_IWUSR 
S_IWRITE00200 權限,代表該文件所有者具有可寫入的權限。
S_IXUSR 
S_IEXEC00100 權限,代表該文件所有者具有可執行的權限。
S_IRWXG 00070
權限,代表該文件用戶組具有可讀、可寫及可執行的權限。
S_IRGRP 00040 
權限,代表該文件用戶組具有可讀的權限。
S_IWGRP 00020
權限,代表該文件用戶組具有可寫入的權限。
S_IXGRP 00010 
權限,代表該文件用戶組具有可執行的權限。
S_IRWXO 00007
權限,代表其他用戶具有可讀、可寫及可執行的權限。
S_IROTH 00004 
權限,代表其他用戶具有可讀的權限
S_IWOTH 00002
權限,代表其他用戶具有可寫入的權限。
S_IXOTH 00001 
權限,代表其他用戶具有可執行的權限。
 
返回值  若所有欲覈查的權限都通過了檢查則返回值,表示成功,只要有一個權限被禁止則返回-1
錯誤代碼  EEXIST 參數pathname 所指的文件已存在,卻使用了O_CREATO_EXCL旗標。
EACCESS 
參數pathname所指的文件不符合所要求測試的權限。
EROFS 
欲測試寫入權限的文件存在於只讀文件系統內。
EFAULT 
參數pathname指針超出可存取內存空間。
EINVAL 
參數mode 不正確。
ENAMETOOLONG 
參數pathname太長。
ENOTDIR 
參數pathname不是目錄。
ENOMEM 
核心內存不足。
ELOOP 
參數pathname有過多符號連接問題。
EIO I/O 
存取錯誤。

pathname參數是要創建的FIFO文件的名稱, mode是給FIFO文件設定的權限。FIFO文件與其它文件一樣,可以用removeunlink進行刪除。如果mkfifo的第一參數是一個已經存在的路徑名時,會返回EEXIST錯誤,所以一般典型的調用代碼首先會檢查是否返回該錯誤,如果確實返回該錯誤,那麼只要調用打開FIFO函數就可以了。一般文件的I/O函數都可以用於FIFO,如closeread

write等。管道僅需要創建而不需要打開,因爲使用它們的進程通過繼承獲得了管道的文件描述符。但命名管道則需要打開,因爲使用它們的進程可以沒有任何關係。對命名管道的打開通常使用文件打開

FIFO打開操作注意

    1. 打開讀的FIFO

如果已經存在打開寫的FIFO,則打開成功立刻返回.

不存在寫的FIFO被打開, open(“FIFO”, O_RDONLY)則阻塞直到有數據寫入

open(“FIFO”, O_RDONLY|O_NONBLOCK)則立刻成功返回

  • 如果有進程寫打開FIFO,且當前FIFO內沒有數據,則對於設置了阻塞標誌的讀操作來說,將一直阻塞。對於沒有設置阻塞標誌讀操作來說則返回-1,當前errno值爲EAGAIN,提醒以後再試。如果讀操作進行時纔打開寫FIFO則不會再返回-1,返回0

  • 對於設置了阻塞標誌的讀操作說,造成阻塞的原因有兩種:當前FIFO內有數據,但有其它進程在讀這些數據;另外就是FIFO內沒有數據。解阻塞的原因則是FIFO中有新的數據寫入,不論信寫入數據量的大小,也不論讀操作請求多少數據量。

  • 讀打開的阻塞標誌只對本進程第一個讀操作施加作用,如果本進程內有多個讀操作序列,則在第一個讀操作被喚醒並完成讀操作後,其它將要執行的讀操作將不再阻塞,即使在執行讀操作時,FIFO中沒有數據也一樣(此時,讀操作返回0)。

  • 如果沒有進程寫打開FIFO,則設置了阻塞標誌的讀操作會阻塞。

注:如果FIFO中有數據,則設置了阻塞標誌的讀操作不會因爲FIFO中的字節數小於請求讀的字節數而阻塞,此時,讀操作會返回FIFO中現有的數據量。

    2. 打開寫的FIFO

如果已經存在打開讀的FIFO,則打開成功立刻返回.

不存在讀的FIFO被打開,open(“FIFO”, O_WDONLY)則阻塞直到有爲讀而打開的FIFO

open(“FIFO”, O_WDONLY|O_NONBLOCK)則返回錯誤ENXIO.

對於設置了阻塞標誌的寫操作:

  • 當要寫入的數據量不大於PIPE_BUF時,linux將保證寫入的原子性。如果此時管道空閒緩衝區不足以容納要寫入的字節數,則進入睡眠,直到當緩衝區中能夠容納要寫入的字節數時,纔開始進行一次性寫操作。

  • 當要寫入的數據量大於PIPE_BUF時,linux將不再保證寫入的原子性。FIFO緩衝區一有空閒區域,寫進程就會試圖向管道寫入數據,寫操作在寫完所有請求寫的數據後返回。

對於沒有設置阻塞標誌的寫操作:

  • 當要寫入的數據量大於PIPE_BUF時,linux將不再保證寫入的原子性。在寫滿所有FIFO空閒緩衝區後,寫操作返回。

  • 當要寫入的數據量不大於PIPE_BUF時,linux將保證寫入的原子性。如果當前FIFO空閒緩衝區能夠容納請求寫入的字節數,寫完後成功返回;如果當前FIFO空閒緩衝區不能夠容納請求寫入的字節數,則返回EAGAIN錯誤,提醒以後再寫;

 

Write pipe demo:

#include <sys/types.h>

#include <sys/stat.h>

#include <errno.h>

#include <fcntl.h>

#include <stdio.h>

#include <memory.h>

#include <string.h>

#define FIFO_TEST "/tmp/fifo_test"

 

void main(int argc,char** argv)

{

         int fd;

         char write_buf[1024*5] = "first";

         int ret = 0;

 

         mkfifo(FIFO_TEST, 0x777);

         fd = open( FIFO_TEST, O_WRONLY );

         if(fd == -1 )

         {

                 if(errno==ENXIO)

                 {

                          printf("open error; no reading process/n");

                          goto error_end;

                 }               

         }

         ret = write( fd, write_buf, strlen(write_buf));

         if( -1 == ret )

         {

                 if( EAGAIN == errno )

                 {

                          printf("write to fifo error; try later/n");

                 }

                

                 goto error_end;

         }

         else

         {

                 printf("real write num is %d/n", ret);

         }

        

         for( ret = 0; ret < sizeof(write_buf); ret++)

               write_buf[ret] = ret%10+'0';

         ret = write( fd, write_buf, sizeof(write_buf) );

         // more than 4096 bytes writing everytime is  test for the non-atomic write

         if( ret == -1)

         {       

                 if( EAGAIN == errno )

                 {

                          printf("try later/n");

                 }

         }

error_end:

         return;

 

}

 

Read pipe demo:

#include <sys/types.h>

#include <sys/stat.h>

#include <errno.h>

#include <fcntl.h>

#include <stdio.h>

#include <memory.h>

 

#define FIFO_TEST "/tmp/fifo_test"

#define FIFO_READ_SIZE    1024

 

void main(int argc,char** argv)

{

         char read_buf[FIFO_READ_SIZE] ={0} ;

         int  fd;

         int  r_byte;

         int  ret;

 

         mkfifo( FIFO_TEST, 0x777);

         fd=open(FIFO_TEST,O_RDONLY|O_NONBLOCK, 0);

         if( -1 == fd )

         {

                 printf("open for read error/n");

                 unlink(FIFO_TEST);

                 return;

                 //exit(0);      

         }

         while(1)

         {

                

                 memset(read_buf, 0, sizeof(read_buf) );

                 ret = read( fd, read_buf, sizeof(read_buf) );

                 if(-1 == ret )

                 {

                          if(errno==EAGAIN)

                          {

                                   printf("test situation:FIFO that opened as WDONLY  do reading operation first /n");

                          }

                         

                          break;

                 }

                 read_buf[sizeof(read_buf)-1] = 0;

                 printf("real read bytes %d string=%s/n", ret,  read_buf);

                 sleep(1);

         }       

         unlink(FIFO_TEST);

}

 

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章