多路复用IO--poll

多路复用IO–poll

poll定义

#include <poll.h>
int poll(struct pollfd fdarray[], nfds_t nfds, int timeout);

返回值:准备就绪的描述符数目:若超时,返回0;若出错,返回-1

与select不同,poll不是为每个条件(可续性、可写性和异常条件)构造一个描述符集,而是构造一个pollfd结构的数组,每个数组元素指定一个描述符编号以及我们对该描述符感兴趣的条件。

struct pollfd {
  int fd;           /* file descriptor to check, or < 0 to ignore */
  short events;     /* events of interest on fd */
  short revents;    /* events that occurred on fd */ 
}

参数说明

(1)fdarray数组中的元素数由nfds指定。

(2)应将每个数组元素的events成员设置为下图中所示值的一个或几个,通过这些值告诉内核我们关心的是每个描述符的哪些事件。返回时,revents成员由内核设置,用于说明每个描述符发生了哪些事件。

标志名输入至events?从revents得到结果?说明
POLLINyy可以不阻塞地读高优先级数据意外的数据(等效于POLLRDNORM|POLLRDBAND)
POLLRDNORMyy可以不阻塞地读普通数据
POLLRDBANDyy可以不阻塞地读优先级数据
POLLPRIyy可以不阻塞地读高优先级数据
POLLOUTyy可以不阻塞地写普通数据
POLLWRNORMyy与POLLOUT相同
POLLWRBANDyy可以不阻塞地写优先级数据
POLLERRy已出错
POLLHUPy已挂断
POLLNVALy描述符没有引用一个打开文件

(3)poll的最后一个参数指定的是我们愿意等待多长时间。

  • timeout == -1

    永远等待。

  • timeout == 0

    不等待。测试所有描述符并立即返回。

  • timeout > 0

    等待timeout毫秒。当指定的描述符之一已准备好,或timeout到期时立即返回。如果timeout到期时还没有一个描述符准备好,则返回值是0。

实例讲解

下面已一个例子来演示poll的用法。

我们有两个程序,poll.c和write_fifo.c。

poll.c中,我们循环监听了两个描述符,STDIN_FILENO标准输入描述符和命名管道fd。不同的fd上有数据反馈,在显示器上会打印不同的输出。

write_fifo.c中,每隔5秒向命名管道fd写入”this is for test”。

/**
 * poll.c
 * 演示poll的主要用法
 */

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <poll.h>

#define fifo_filename "test_fifo"

int main(int argc, char *argv[])
{
    int ret;
    int fd;
    struct pollfd fds[2];

    ret = mkfifo(fifo_filename, 0666);
    if (ret != 0) {
        perror("mkfifo error");
    }

    fd = open(fifo_filename, O_RDWR);
    if (fd < 0) {
        perror("open error");
        exit(-1);
    }

    ret = 0;

    fds[0].fd = 0;
    fds[1].fd = fd;

    fds[0].events = POLLIN;
    fds[1].events = POLLIN;

    while (1) {
        ret = poll(fds, 2, -1);

        if (ret == -1) {
            perror("epoll_wait error");
        } else if (ret > 0) {
            char buf[100] = {0};

            if ((fds[0].revents & POLLIN) == POLLIN) {
                read(0, buf, sizeof(buf));
                printf("stdin buf = %s\n", buf);
            } else if ((fds[1].revents & POLLIN == POLLIN)) {
                read(fd, buf, sizeof(buf));
                printf("fifo buf = %s\n", buf);
            }
        } else if (ret == 0) {
            printf("time out\n");
        }
    }

    exit(0);
}
/**
 * write_fifo.c
 * 给命名管道发送信息
 */

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>

#define fifo_filename "test_fifo"

int main(int argc, char *argv[])
{
    int ret = 0;
    int fd;

    ret = mkfifo(fifo_filename, 0666);
    if (ret != 0) {
        perror("mkfifo error");
    }

    fd = open(fifo_filename, O_RDWR);
    if (fd < 0) {
        perror("open error");
        exit(-1);
    }

    while (1) {
        char *str = "this is for test";
        write(fd, str, strlen(str));
        printf("after write to fifo\n");
        sleep(5);
    }

    exit(0);
}

编译两个程序

/myblog/myblog/source/poll# gcc poll.c -o poll
/myblog/source/poll# gcc write_fifo.c -o write_fifo

启动poll程序,如下:

/myblog/source/poll# ./poll
fifo buf = this is for test
fifo buf = this is for test
fifo buf = this is for test
hello
stdin buf = hello

fifo buf = this is for test
fifo buf = this is for test
^C

启动write_fifo程序,如下:

/myblog/source/poll# ./write_fifo
mkfifo error: File exists
after write to fifo
after write to fifo
after write to fifo
after write to fifo
after write to fifo
^C

从程序运行结果可以看出,当write_fifo不断往命名管道写入”this is for test”时,select监听到命名管道fd已准备好,从fd上读出数据并打印到显示器上;当我们从标准输入中打出hello时,select监听到STDIN_FILENO(描述符为0)已准备好,从描述符0中读出数据并打印到显示器上。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值