IPC之FIFO

来源:互联网 发布:车牌识别有没有数据库 编辑:程序博客网 时间:2024/05/22 04:43

简介

             FIFO又被称为命名管道,它是一种特殊类型的文件,它在文件系统中以文件名的形式存在,一般的文件I/O函数都可以用于FIFO。

        打开一个FIFO时,非阻塞标志(O_NONBLOCK)产生下列影响:

    • 未指定O_NONBLOCK

        只读open()要阻塞到某个其他进程为写而打开此FIFO。类似的,只写open()要阻塞到某个其他进程为读而打开它。

    • 指定O_NONBLOCK

        只读open()立即返回。但是,如果没有进程已经为读而打开一个FIFO,那么只写open()将出错返回-1,其errno是ENXIO。

        基于O_NONBLOCK对FIFO操作的影响,一种比较好的操作FIFO的方式是以非阻塞的方式打开文件,然后以阻塞的方式读写文件或使用select。

        一个给定的FIFO有多个写进程是很常见的。这意味着如果不希望多个进程写的数据互相穿插,则需考虑原子操作,常量PIPE_BUF说明了可被原子地写到FIFO的最大数据量。

        FIFO有以下两种用途:

    1.     FIFO由shell命令使用以便将数据从一条管道线传送到另一条,为此不需要创建中间临时文件。
    2.     FIFO用于客户进程-服务器进程的应用程序中,以在客户进程和服务器进程中传递数据。


示例程序


阻塞版本


服务端

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <fcntl.h>#include <errno.h>#include <sys/stat.h>#define RECV_BUF_SIZE 1024#define SEND_BUF_SIZE 1024#define CONTENT_LEN 128#define ARGUMENT_LEN 128#define DATA_SEPARATOR ':'#define SERVER_FIFO_PATH "/tmp/fifo_server"int server_write_fd, server_read_fd, client_write_fd;char    send_buf[SEND_BUF_SIZE];charcontent[CONTENT_LEN];charclient_fifo_path[ARGUMENT_LEN];char    recv_buf[RECV_BUF_SIZE];char    send_buf[SEND_BUF_SIZE];static int  fifo_mode = S_IRUSR| S_IWUSR| S_IRGRP| S_IWGRP;/* * create server fifo * success : 0 failed : -1 */int fifo_init(void){int ret;struct stat filestat;ret = stat(SERVER_FIFO_PATH, &filestat);if(ret == 0){if (unlink(SERVER_FIFO_PATH) < 0){perror("Cannot delete old MI fifo");return -1;}}else if(ret < 0 && errno != ENOENT){perror("MI FIFO stat failed");return -1;}    if((mkfifo(SERVER_FIFO_PATH, fifo_mode) < 0)){        perror("Create client fifo error");      return -1;     }    if((chmod(SERVER_FIFO_PATH, fifo_mode) < 0)){        perror("Chmod client fifo error");goto error;    }return 0;error:   remove(SERVER_FIFO_PATH);return -1;}/* * open server fifo * success : fd failed : -1 */int open_client_fifo(char *pipe_name){    int     flags;    if(!pipe_name || *pipe_name == 0){        printf("No server fifo to open\n");        return -1;    }    client_write_fd = open(pipe_name, O_WRONLY|O_NONBLOCK);    if(client_write_fd < 0){        perror("Can't open server fifo error");        return -1;    }    if((flags = fcntl(client_write_fd, F_GETFL, 0)) < 0){        perror("Server fifo F_GETFL error");        goto error;    }    flags&=~O_NONBLOCK;    if(fcntl(client_write_fd, F_SETFL, flags) < 0){        perror("Server fifo F_GETFL error");        goto error;    }    return 0;error:    close(client_write_fd);    return -1;}/* * open server  fifo for reading * success : fd failed : -1 */int open_server_fifo(char * pipe_name){    int     flags;    if(!pipe_name || *pipe_name == 0){        printf("No client fifo to open");        return -1;    }    server_read_fd = open(pipe_name, O_RDONLY|O_NONBLOCK);    if(server_read_fd < 0){        printf("Can't open client fifo for reading");        return -1;    }    server_write_fd = open(pipe_name, O_WRONLY|O_NONBLOCK);    if(server_write_fd < 0){        printf("Can't open client fifo for writing");        return -1;    }    if((flags = fcntl(server_read_fd, F_GETFL, 0)) < 0){        printf("Client fifo F_GETFL error");        goto error;    }    flags&=~O_NONBLOCK;    if(fcntl(server_read_fd, F_SETFL, flags) < 0){        printf("Client fifo F_SETFL error");        goto error;    }    return 0;error:    close(server_read_fd);    close(server_write_fd);    return -1;}int data_parse(void){char*p, *postion;p = recv_buf;if(*p != DATA_SEPARATOR){printf("command must begin with %c\n", DATA_SEPARATOR);return -1;}p++;postion = strchr(p, DATA_SEPARATOR);if(postion == NULL){printf("file separator missing in fifo command\n");return -1;}strncpy(client_fifo_path, p, postion - p);p = ++postion;strncpy(content, p, strlen(p));return 0;}int main(int argc, char *argv[]){    int     ret;    if(fifo_init()){return -1;    }    if(open_server_fifo(SERVER_FIFO_PATH)){goto error;    }   while(1){memset(recv_buf, 0, RECV_BUF_SIZE);if((ret = read(server_read_fd, recv_buf, RECV_BUF_SIZE)) > 0){if(data_parse()){continue;}printf("Receive data from <%s> : %s\n",client_fifo_path, content);    if(open_client_fifo(client_fifo_path)){continue;    }sprintf(send_buf, "hello, %s\n", client_fifo_path);ret = write(client_write_fd, send_buf, strlen(send_buf));if(ret < 0){perror("Write data to client fifo error");continue;}}}exit(EXIT_SUCCESS);error:remove(SERVER_FIFO_PATH);exit(EXIT_FAILURE);}

客户端

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <fcntl.h>#include <errno.h>#include <sys/stat.h>#define SERVER_FIFO_PATH "/tmp/fifo_server"#define CLIENT_FIFO_PATH "/tmp/fifo_client_%d"#define SEND_BUF_SIZE 1024#define RECV_BUF_SIZE 1024#define CLIENT_FIFO_SIZE 128int server_write_fd, client_read_fd, client_write_fd;charclient_fifo[CLIENT_FIFO_SIZE];char    send_buf[SEND_BUF_SIZE];static int  fifo_mode = S_IRUSR| S_IWUSR| S_IRGRP| S_IWGRP;/* * create client fifo * success : 0 failed : -1 */int fifo_init(void){int ret;struct stat filestat;memset(client_fifo, 0, CLIENT_FIFO_SIZE);sprintf(client_fifo, CLIENT_FIFO_PATH, getpid());ret = stat(client_fifo, &filestat);if(ret == 0){if (unlink(client_fifo) < 0){perror("Cannot delete old MI fifo");return -1;}}else if(ret < 0 && errno != ENOENT){perror("MI FIFO stat failed");return -1;}    if((mkfifo(client_fifo, fifo_mode) < 0)){        perror("Create client fifo error");      return -1;     }    if((chmod(client_fifo, fifo_mode) < 0)){        perror("Chmod client fifo error");goto error;    }return 0;error:   remove(client_fifo);return -1;}/* * open server fifo for writing * success : fd failed : -1 */int open_server_fifo(char *pipe_name){    int     flags;    if(!pipe_name || *pipe_name == 0){        printf("No server fifo to open\n");        return -1;    }    server_write_fd = open(pipe_name, O_WRONLY|O_NONBLOCK);    if(server_write_fd < 0){        perror("Can't open server fifo error");        return -1;    }    if((flags = fcntl(server_write_fd, F_GETFL, 0)) < 0){        perror("Server fifo F_GETFL error");        goto error;    }    flags&=~O_NONBLOCK;    if(fcntl(server_write_fd, F_SETFL, flags) < 0){        perror("Server fifo F_GETFL error");        goto error;    }    return 0;error:    close(server_write_fd);    return -1;}/* * open client fifo * success : fd failed : -1 */int open_client_fifo(char * pipe_name){    int     flags;    if(!pipe_name || *pipe_name == 0){        printf("No client fifo to open.\n");        return -1;    }    client_read_fd = open(pipe_name, O_RDONLY|O_NONBLOCK);    if(client_read_fd < 0){        printf("Can't open client fifo for reading");        return -1;    }    client_write_fd = open(pipe_name, O_WRONLY|O_NONBLOCK);    if(client_write_fd < 0){        printf("Can't open client fifo for writing\n");        return -1;    }    if((flags = fcntl(client_read_fd, F_GETFL, 0)) < 0){        printf("Client fifo F_GETFL error.\n");        goto error;    }    flags&=~O_NONBLOCK;    if(fcntl(client_read_fd, F_SETFL, flags) < 0){        printf("Client fifo F_SETFL error.\n");        goto error;    }    return 0;error:    close(client_read_fd);    close(client_write_fd);    return -1;}int main(int argc, char *argv[]){    int     ret;    char    recv_buf[RECV_BUF_SIZE];    if(fifo_init()){return -1;    }    if(open_client_fifo(client_fifo)){goto error1;    }    if(open_server_fifo(SERVER_FIFO_PATH)){goto error2;    }sprintf(send_buf, ":%s:hello, server.", client_fifo);    ret = write(server_write_fd, send_buf, strlen(send_buf));    if(ret < 0){        perror("Write data to server fifo error");goto error3;    }memset(recv_buf, 0, RECV_BUF_SIZE);   if((ret = read(client_read_fd, recv_buf, RECV_BUF_SIZE)) > 0){printf("Receive data form server : %s", recv_buf);}   close(client_read_fd);  close(server_write_fd);   remove(client_fifo);exit(EXIT_SUCCESS);error3:close(server_write_fd);error2:close(client_read_fd);close(client_write_fd);error1:   remove(client_fifo);exit(EXIT_FAILURE);}

select版本


服务端

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <fcntl.h>#include <errno.h>#include <sys/stat.h>#define RECV_BUF_SIZE 1024#define SEND_BUF_SIZE 1024#define CONTENT_LEN 128#define ARGUMENT_LEN 128#define DATA_SEPARATOR ':'#define SERVER_FIFO_PATH "/tmp/fifo_server"int server_write_fd, server_read_fd, client_write_fd;char    send_buf[SEND_BUF_SIZE];charcontent[CONTENT_LEN];charclient_fifo_path[ARGUMENT_LEN];char    recv_buf[RECV_BUF_SIZE];char    send_buf[SEND_BUF_SIZE];static int  fifo_mode = S_IRUSR| S_IWUSR| S_IRGRP| S_IWGRP;/* * create server fifo * success : 0 failed : -1 */int fifo_init(void){int ret;struct stat filestat;ret = stat(SERVER_FIFO_PATH, &filestat);if(ret == 0){if (unlink(SERVER_FIFO_PATH) < 0){perror("Cannot delete old MI fifo");return -1;}}else if(ret < 0 && errno != ENOENT){perror("MI FIFO stat failed");return -1;}    if((mkfifo(SERVER_FIFO_PATH, fifo_mode) < 0)){        perror("Create client fifo error");      return -1;     }    if((chmod(SERVER_FIFO_PATH, fifo_mode) < 0)){        perror("Chmod client fifo error");goto error;    }return 0;error:   remove(SERVER_FIFO_PATH);return -1;}/* * open server fifo * success : fd failed : -1 */int open_client_fifo(char *pipe_name){    int     flags;    if(!pipe_name || *pipe_name == 0){        printf("No server fifo to open\n");        return -1;    }    client_write_fd = open(pipe_name, O_WRONLY|O_NONBLOCK);    if(client_write_fd < 0){        perror("Can't open server fifo error");        return -1;    }    if((flags = fcntl(client_write_fd, F_GETFL, 0)) < 0){        perror("Server fifo F_GETFL error");        goto error;    }    flags&=~O_NONBLOCK;    if(fcntl(client_write_fd, F_SETFL, flags) < 0){        perror("Server fifo F_GETFL error");        goto error;    }    return 0;error:    close(client_write_fd);    return -1;}/* * open server  fifo for reading * success : fd failed : -1 */int open_server_fifo(char * pipe_name){    //int     flags;    if(!pipe_name || *pipe_name == 0){        printf("No client fifo to open");        return -1;    }    server_read_fd = open(pipe_name, O_RDONLY|O_NONBLOCK);    if(server_read_fd < 0){        printf("Can't open client fifo for reading");        return -1;    }    return 0;}int data_parse(void){char*p, *postion;p = recv_buf;if(*p != DATA_SEPARATOR){printf("command must begin with %c\n", DATA_SEPARATOR);return -1;}p++;postion = strchr(p, DATA_SEPARATOR);if(postion == NULL){printf("file separator missing in fifo command\n");return -1;}strncpy(client_fifo_path, p, postion - p);p = ++postion;strncpy(content, p, strlen(p));return 0;}int main(int argc, char *argv[]){    int     ret, maxfd;fd_setset, read_set;structtimeval timeout;    if(fifo_init()){return -1;    }    if(open_server_fifo(SERVER_FIFO_PATH)){goto error;    }FD_ZERO(&set);FD_SET(server_read_fd, &set); maxfd = server_read_fd + 1;   while(1){read_set = set;timeout.tv_sec = 2;timeout.tv_usec = 0;memset(recv_buf, 0, RECV_BUF_SIZE);ret = select(maxfd, &read_set, NULL, NULL, &timeout);switch(ret){case 0:continue;case -1:perror("select");continue;default:if(FD_ISSET(server_read_fd, &read_set)){if((ret = read(server_read_fd,recv_buf, RECV_BUF_SIZE)) > 0){if(data_parse()){continue;}printf("Receive data from <%s> : %s\n",client_fifo_path, content);    if(open_client_fifo(client_fifo_path)){continue;    }sprintf(send_buf, "hello, %s\n", client_fifo_path);ret = write(client_write_fd, send_buf, strlen(send_buf));if(ret < 0){perror("Write data to client fifo error");continue;}}}}}remove(SERVER_FIFO_PATH);exit(EXIT_SUCCESS);error:remove(SERVER_FIFO_PATH);exit(EXIT_FAILURE);}

客户端

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <fcntl.h>#include <errno.h>#include <sys/stat.h>#define RECV_BUF_SIZE 1024#define SEND_BUF_SIZE 1024#define CONTENT_LEN 128#define ARGUMENT_LEN 128#define DATA_SEPARATOR ':'#define SERVER_FIFO_PATH "/tmp/fifo_server"int server_write_fd, server_read_fd, client_write_fd;char    send_buf[SEND_BUF_SIZE];charcontent[CONTENT_LEN];charclient_fifo_path[ARGUMENT_LEN];char    recv_buf[RECV_BUF_SIZE];char    send_buf[SEND_BUF_SIZE];static int  fifo_mode = S_IRUSR| S_IWUSR| S_IRGRP| S_IWGRP;/* * create server fifo * success : 0 failed : -1 */int fifo_init(void){int ret;struct stat filestat;ret = stat(SERVER_FIFO_PATH, &filestat);if(ret == 0){if (unlink(SERVER_FIFO_PATH) < 0){perror("Cannot delete old MI fifo");return -1;}}else if(ret < 0 && errno != ENOENT){perror("MI FIFO stat failed");return -1;}    if((mkfifo(SERVER_FIFO_PATH, fifo_mode) < 0)){        perror("Create client fifo error");      return -1;     }    if((chmod(SERVER_FIFO_PATH, fifo_mode) < 0)){        perror("Chmod client fifo error");goto error;    }return 0;error:   remove(SERVER_FIFO_PATH);return -1;}/* * open server fifo * success : fd failed : -1 */int open_client_fifo(char *pipe_name){    int     flags;    if(!pipe_name || *pipe_name == 0){        printf("No server fifo to open\n");        return -1;    }    client_write_fd = open(pipe_name, O_WRONLY|O_NONBLOCK);    if(client_write_fd < 0){        perror("Can't open server fifo error");        return -1;    }    if((flags = fcntl(client_write_fd, F_GETFL, 0)) < 0){        perror("Server fifo F_GETFL error");        goto error;    }    flags&=~O_NONBLOCK;    if(fcntl(client_write_fd, F_SETFL, flags) < 0){        perror("Server fifo F_GETFL error");        goto error;    }    return 0;error:    close(client_write_fd);    return -1;}/* * open server  fifo for reading * success : fd failed : -1 */int open_server_fifo(char * pipe_name){    //int     flags;    if(!pipe_name || *pipe_name == 0){        printf("No client fifo to open");        return -1;    }    server_read_fd = open(pipe_name, O_RDONLY|O_NONBLOCK);    if(server_read_fd < 0){        printf("Can't open client fifo for reading");        return -1;    }    return 0;}int data_parse(void){char*p, *postion;p = recv_buf;if(*p != DATA_SEPARATOR){printf("command must begin with %c\n", DATA_SEPARATOR);return -1;}p++;postion = strchr(p, DATA_SEPARATOR);if(postion == NULL){printf("file separator missing in fifo command\n");return -1;}strncpy(client_fifo_path, p, postion - p);p = ++postion;strncpy(content, p, strlen(p));return 0;}int main(int argc, char *argv[]){    int     ret, maxfd;fd_setset, read_set;structtimeval timeout;    if(fifo_init()){return -1;    }    if(open_server_fifo(SERVER_FIFO_PATH)){goto error;    }FD_ZERO(&set);FD_SET(server_read_fd, &set); maxfd = server_read_fd + 1;   while(1){read_set = set;timeout.tv_sec = 2;timeout.tv_usec = 0;memset(recv_buf, 0, RECV_BUF_SIZE);ret = select(maxfd, &read_set, NULL, NULL, &timeout);switch(ret){case 0:continue;case -1:perror("select");continue;default:if(FD_ISSET(server_read_fd, &read_set)){if((ret = read(server_read_fd,recv_buf, RECV_BUF_SIZE)) > 0){if(data_parse()){continue;}printf("Receive data from <%s> : %s\n",client_fifo_path, content);    if(open_client_fifo(client_fifo_path)){continue;    }sprintf(send_buf, "hello, %s\n", client_fifo_path);ret = write(client_write_fd, send_buf, strlen(send_buf));if(ret < 0){perror("Write data to client fifo error");continue;}}}}}remove(SERVER_FIFO_PATH);exit(EXIT_SUCCESS);error:remove(SERVER_FIFO_PATH);exit(EXIT_FAILURE);}






0 0
原创粉丝点击