ITPub博客

首页 > Linux操作系统 > Linux操作系统 > select与fifo

select与fifo

原创 Linux操作系统 作者:liiinuuux 时间:2016-03-30 17:24:41 0 删除 编辑
fifo(命名管道)与popen建立的管道意思一样,区别在于popen的管道通常是在父子进程之间调用,而fifo可以在文件系统中看到,可以用于不同程序之间通信。fifo也支持tail -f,echo xxx > 等操作系统命令,甚至还有一个系统命令就叫mkfifo。
fifo作为一个文件,它的内容数据并不存放在文件系统中,而仅仅存在于内核里。
打开fifo文件和普通文件不同,如果尝试以读权限打开,会阻塞知道有另一个进程以写权限打开它,反之亦然。

创建fifo

点击(此处)折叠或打开

  1. #include <sys/types.h>
  2. #include <sys/stat.h>
  3. int mkfifo(const char *pathname, mode_t mode);
其中mode和open函数的mode意思一样


select会同时监控多个文件描述符的缓冲区。它会一直阻塞,直到超时或者哪个fd的缓冲有内容了,select就认为这个fd已经准备好了,并返回。
返回值
-1 出错
1 成功
0 超时

点击(此处)折叠或打开

  1. #include <sys/time.h>
  2. #include <sys/types.h>
  3. #include <unistd.h>
  4. int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

参数:
nfds 需要手工设置为要监控的最大的文件描述符+1,即:max(所有被监控的fd)+1
readfds, writefds, exceptfds三个用来存放要监控的文件描述符。分别是要读的,要写的和监控出现异常的。
timeout是超时设置,传NULL表示一直阻塞,timeval里面全赋值0表示不阻塞,直接返回。


下面a.c和b.c两个程序。
b.c创建一个fifo,并用select监控标准输入,一旦有输入了,就把输入内容写到fifo里
a.c打开fifo,打印里面的内容,遇到EOF就退出。
启动后,在b程序的终端输入,输入的内容会在a的终端显示出来。

[root@server2 fifo_select]# cat b.c
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>

int main(int argc, char** argv)
{
    /* fifo文件名 */
    char pipename[3] = "p1";
    /* 创建fifo */
    int ret = mkfifo(pipename, O_RDWR);
    if(ret < 0)
    {
        /* 如果已经存在,判断是不是之前创建的fifo。fifo可以重复使用。 */
        if(errno == EEXIST)
        {
            struct stat st;
            if(stat(pipename, &st) < 0) exit(errno);
            if(S_ISFIFO(st.st_mode) < 1) exit(errno);
        }
        else
        {
            exit(errno);
        }
    }

    /* 打开fifo,此时会阻塞,知道有另一个程序以写方式打开fifo */
    int p = open(pipename, O_WRONLY);
    printf("pipe fd = %d\n", p);

    /* select用的数据结构,用来存放要监控的文件描述符。这里监控的是标准输入 */
    fd_set fs;
    FD_ZERO(&fs);
    FD_SET(0, &fs);

    int n = 0;
    char buf[1024];
    while(1)
    {
        /* 监控fs里的文件描述符,直到有文件描述符可用为止 */
        select(1, &fs, NULL, NULL, NULL);
        printf("select ok\n");

        /* 判断准备好的文件描述符是不是标准输入 */
        if(FD_ISSET(0, &fs))
        {
            printf("0 ok\n");
            n = read(0, buf, 1024);
            if(n < 1024) buf[n] = '\0';
            write(p, buf, n);
        }
    }
    return 0;
}



a.c:
int main(int argc, char** argv)
{
    FILE* p = fopen("p1", "r");

    printf("open ok\n");
    char c = 0;
    while((c = getc(p)) != EOF)
    {
        printf("%c", c);
    }

    fclose(p);
    return 0;
}






来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/26239116/viewspace-2072550/,如需转载,请注明出处,否则将追究法律责任。

下一篇: poll与socket
请登录后发表评论 登录
全部评论

注册时间:2012-11-12

  • 博文量
    94
  • 访问量
    308794