一 創建管道函數:
#include <sys/types.h> #include <sys/stat.h> int mkfifo(const char * pathname, mode_t mode) |
函數說明 參數pathname 指向欲打開的文件路徑字符串。下列是參數flags 所能使用的旗標:
S_IRWXU00700 權限,代表該文件所有者具有可讀、可寫及可執行的權限。
S_IRUSR 或S_IREAD,00400權限,代表該文件所有者具有可讀取的權限。
S_IWUSR 或S_IWRITE,00200 權限,代表該文件所有者具有可寫入的權限。
S_IXUSR 或S_IEXEC,00100 權限,代表該文件所有者具有可執行的權限。
S_IRWXG 00070權限,代表該文件用戶組具有可讀、可寫及可執行的權限。
S_IRGRP 00040 權限,代表該文件用戶組具有可讀的權限。
S_IWGRP 00020權限,代表該文件用戶組具有可寫入的權限。
S_IXGRP 00010 權限,代表該文件用戶組具有可執行的權限。
S_IRWXO 00007權限,代表其他用戶具有可讀、可寫及可執行的權限。
S_IROTH 00004 權限,代表其他用戶具有可讀的權限
S_IWOTH 00002權限,代表其他用戶具有可寫入的權限。
S_IXOTH 00001 權限,代表其他用戶具有可執行的權限。
返回值 若所有欲覈查的權限都通過了檢查則返回0 值,表示成功,只要有一個權限被禁止則返回-1。
錯誤代碼 EEXIST 參數pathname 所指的文件已存在,卻使用了O_CREAT和O_EXCL旗標。
EACCESS 參數pathname所指的文件不符合所要求測試的權限。
EROFS 欲測試寫入權限的文件存在於只讀文件系統內。
EFAULT 參數pathname指針超出可存取內存空間。
EINVAL 參數mode 不正確。
ENAMETOOLONG 參數pathname太長。
ENOTDIR 參數pathname不是目錄。
ENOMEM 核心內存不足。
ELOOP 參數pathname有過多符號連接問題。
EIO I/O 存取錯誤。
pathname參數是要創建的FIFO文件的名稱, mode是給FIFO文件設定的權限。FIFO文件與其它文件一樣,可以用remove和unlink進行刪除。如果mkfifo的第一參數是一個已經存在的路徑名時,會返回EEXIST錯誤,所以一般典型的調用代碼首先會檢查是否返回該錯誤,如果確實返回該錯誤,那麼只要調用打開FIFO函數就可以了。一般文件的I/O函數都可以用於FIFO,如close、read、
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); } |