1. FIFO:shell
FIFO也被成爲命名管道,因其經過路徑關係綁定,能夠用於任意進程間通訊,而普通無名管道只能用於有共同祖先的進行直接通訊;服務器
命名管道也是半雙工的,open管道的時候不要以讀寫方式打開,這種操做是未定義的;函數
2. FIFO建立:測試
#include <sys/stat.h> int mkfifo(const char *pathname, mode_t mode); ret = 成功返回0,失敗返回-1
FIFO是一種文件類型,mode參數與open函數中的mode參數相同,而且通常文件的操做函數(close, read, write, unlink等)都以用於FIFO;spa
3. 非阻塞標誌(O_NONBLOCK):code
(1) 阻塞模式:只讀open要阻塞到某個進程爲寫而打開此FIFO,只寫open要阻塞到某個進程爲讀而打開此FIFO;server
(2) 非阻塞模式:只讀當即返回,若是沒有進程爲讀而打開FIFO,則只寫open返回-1,erron=ENXIO;blog
4. 一端關閉:進程
(1) 若讀一個已經關閉寫端的FIFO,則讀取完數據後,會讀到文件結束符,read返回0;ip
(2) 若寫一個已經關閉讀端的FIFO,則產生SIGPIPE;
5. 用途:
(1) FIFO由shell命令使用以便將數據從一條管道傳送到另外一條,而無需建立臨時文件;
(2) FIFO用於客戶進程和服務器進程進行數據傳遞;
6. 測試代碼:兩個進程間通訊;
fifo_writer.c -- 向fifo中寫入字串
1 #include <unistd.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <string.h> 5 #include <limits.h> 6 #include <sys/stat.h> 7 #include <sys/types.h> 8 #include <fcntl.h> 9 10 #define FIFO_NAME "/var/tmp/fifo_test" 11 #define BUF_LEN PIPE_BUF 12 13 14 int main(int argc, char *argv[]) 15 { 16 int pipeid = -1; 17 int fifoid = -1; 18 19 char buffer[BUF_LEN] = { 0 }; 20 21 if (access(FIFO_NAME, F_OK) < 0){ 22 fifoid = mkfifo(FIFO_NAME, 0777); 23 if (fifoid < 0){ 24 perror("mkfifo error\n"); 25 return -1; 26 } 27 } 28 29 pipeid = open(FIFO_NAME, O_WRONLY); 30 if (pipeid < 0){ 31 perror("open pipeid error\n"); 32 return -1; 33 } 34 35 int read_bytes = read(STDIN_FILENO, buffer, BUF_LEN); 36 if (read_bytes < 0){ 37 perror("read error\n"); 38 close(pipeid); 39 return -1; 40 } 41 42 const char * buff_send = buffer; 43 int no_write_bytes = read_bytes; 44 while (no_write_bytes > 0){ 45 int n = write(pipeid, buff_send, no_write_bytes); 46 if (n < 0){ 47 perror("write error\n"); 48 close(pipeid); 49 return -1; 50 } 51 52 no_write_bytes -= n; 53 buff_send += n; 54 } 55 56 close(pipeid); 57 58 return 0; 59 }
fifo_reader.c -- 從fifo中讀出字串
1 #include <unistd.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <string.h> 5 #include <limits.h> 6 #include <sys/stat.h> 7 #include <sys/types.h> 8 #include <fcntl.h> 9 10 #define FIFO_NAME "/var/tmp/fifo_test" 11 #define BUF_LEN PIPE_BUF 12 13 14 int main(int argc, char *argv[]) 15 { 16 int pipeid = -1; 17 18 char buffer[BUF_LEN] = { 0 }; 19 20 pipeid = open(FIFO_NAME, O_RDONLY); 21 22 int n = read(pipeid, buffer, BUF_LEN - 1); 23 if (n < 0){ 24 perror("read error\n"); 25 close(pipeid); 26 return -1; 27 } 28 29 write(STDOUT_FILENO, buffer, n); 30 31 close(pipeid); 32 33 return 0; 34 }
7. 測試代碼:多個客戶端與服務器通訊
模型以下圖所示:
common.h--公共頭文件
1 #include <unistd.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <fcntl.h> 5 #include <limits.h> 6 #include <string.h> 7 8 #define SERVER_FIFO_NAME "/var/tmp/fifoServer" 9 #define CLIENT_FIFO_NAME "/var/tmp/fifoClient%d" 10 #define BUFF_SIZE PIPE_BUF 11 #define MSG_LEN 64 12 #define CLIENT_FIFO_NAME_LEN 64 13 14 typedef struct fifo_msg{ 15 pid_t client_pid; 16 char msg[MSG_LEN]; 17 }fifo_msg_t;
fifo_server.c
1 #include "common.h" 2 3 int main(int argc, char *argv[]) 4 { 5 int fifo_id = -1; 6 int server_fifo_fd = -1; 7 8 if (access(SERVER_FIFO_NAME, F_OK) < 0){ 9 fifo_id = mkfifo(SERVER_FIFO_NAME, 0777); 10 if (fifo_id < 0){ 11 perror("mkfifo error\n"); 12 return -1; 13 } 14 } 15 16 server_fifo_fd = open(SERVER_FIFO_NAME, O_RDONLY); 17 if (server_fifo_fd < 0){ 18 perror("open fifo error\n"); 19 return -1; 20 } 21 22 fifo_msg_t client_msg; 23 memset(&client_msg, 0, sizeof(client_msg)); 24 int read_bytes = 0; 25 26 do { 27 read_bytes = read(server_fifo_fd, &client_msg, sizeof(client_msg)); 28 if (read_bytes < 0){ 29 perror("read error\n"); 30 close(server_fifo_fd); 31 return -1; 32 } 33 34 char *tmp_msg = client_msg.msg; 35 while (*tmp_msg){ 36 *tmp_msg = toupper(*tmp_msg); 37 tmp_msg++; 38 } 39 40 char client_fifo[CLIENT_FIFO_NAME_LEN] = { 0 }; 41 snprintf(client_fifo, CLIENT_FIFO_NAME_LEN - 1, CLIENT_FIFO_NAME, client_msg.client_pid); 42 43 int client_fifo_fd = open(client_fifo, O_WRONLY); 44 if (client_fifo_fd < 0){ 45 perror("open client fifo error\n"); 46 } 47 48 write(client_fifo_fd, &client_msg, sizeof(client_msg)); 49 printf("write to client:%d\n", client_msg.client_pid); 50 close(client_fifo_fd); 51 52 } while (read_bytes > 0); 53 54 close(server_fifo_fd); 55 return 0; 56 }
fifo_client.c
1 #include "common.h" 2 3 int main(int argc, char *argv[]) 4 { 5 pid_t client_pid = -1; 6 int server_fifo_fd = -1; 7 int client_fifo_fd = -1; 8 9 server_fifo_fd = open(SERVER_FIFO_NAME, O_WRONLY); 10 if (server_fifo_fd < 0){ 11 perror("open server fifo error\n"); 12 return -1; 13 } 14 15 client_pid = getpid(); 16 17 char client_fifo_name[CLIENT_FIFO_NAME_LEN] = {0}; 18 snprintf(client_fifo_name, CLIENT_FIFO_NAME_LEN - 1, CLIENT_FIFO_NAME, client_pid); 19 if (mkfifo(client_fifo_name, 0777) < 0){ 20 perror("mkfifo client error\n"); 21 close(server_fifo_fd); 22 return -1; 23 } 24 25 fifo_msg_t client_msg; 26 memset(&client_msg, 0, sizeof(client_msg)); 27 client_msg.client_pid = client_pid; 28 29 #define TRY_TIMES 3 30 int times = 0; 31 for (times = 0; times < TRY_TIMES; times++){ 32 snprintf(client_msg.msg, MSG_LEN - 1, "client_pid:%d\n", client_pid); 33 write(server_fifo_fd, &client_msg, sizeof(client_msg)); 34 35 client_fifo_fd = open(client_fifo_name, O_RDONLY); 36 if (client_fifo_fd < 0){ 37 perror("open client fifo error\n"); 38 close(server_fifo_fd); 39 unlink(client_fifo_name); 40 return -1; 41 } 42 43 int n = read(client_fifo_fd, &client_msg, sizeof(client_msg)); 44 if (n > 0){ 45 printf("reveive msg from server:%s", client_msg.msg); 46 } 47 48 close(client_fifo_fd); 49 } 50 51 close(server_fifo_fd); 52 unlink(client_fifo_name); 53 return 0; 54 }