文件编程(4)多路复用

一.IO处理模型

1.阻塞IO模型

如果所调用的IO函数没有完成相应的IO功能,会使进程挂起,直到等待的相关数据到达才会返回。比如对管道设备,终端设备,网络设备等的操作。

2.非阻塞IO模型

当请求不能满足的时候,不会让进程睡眠,而是直接睡眠。比如我们常见的open,write,read等函数。

3.多路转接模型

如果请求得不到满足,但是又不是真的IO阻塞,而是其中的一个函数等待,在此期间函数还可以进行其他操作,比如select以及poll函数就是这种类型。

4.信号驱动IO模型

进程要定义一个信号处理程序,系统可以自动捕获特定信号的的到来,从而启动IO操作,由内核通知用户何时可以启动一个IO操作。

5.异步IO模型

先让内核其哦对嗯IO操作,完成以后再通知进程IO操作结束。

二.关于多路转接模型

select和poll函数,他们可以设定程序中所关心的文件描述符,希望等待的时间等。从函数返回的时候,内核会通知用户准备好的文件描述符的数量,已经准备好的条件或者事件等。通过select和poll的返回结果,对应检测到某个文件描述符的注册事件或者是超时,或者是调用出错。

三.select函数说明

1.所需头文件

<sys/types.h>

<sys/time.h>

<unistd.h>

2.函数原型

int select(int numfds,fd_set *readfds,fd_set *writefds,fd_set *exeptfds,struct timeval *timeout);

3.参数说明

(1)numfds:为需要监视的文件描述符的最大值加1

(2)readfds:由select函数监视的读文件描述符集合

(3)writefds:由select函数监视的写文件描述符集合

(4)exeptfds:由select函数监视的异常处理文件描述符集合

(5)timeout:

----》NULL:永远等待

----》具体值:具体的超时值

----》0:从不等待,测试所有指定的文件描述符立即返回

4.返回值

成功:准备好的文件描述符

失败:-1

超时:0

5.select涉及到的文件描述符处理宏定义函数

(1)FD_ZERO(fd_set *set):清除一个文件描述符集合

(2)FD_SET(int fd,fd_set *set):将一个文件描述符加入到set集合

(3)FD_CLR(int fd,fd_set *set):将一个文件描述符从set集合删除

(4)FD_ISSET(int fd,fd_set *set):测试fd是否属于set。可以用于调用select以后检测集合中的哪个文件描述符是否有变化

(5)FD_SETSIZE表示fd_set结构能够容纳的文件描述符的最大数目

6.注意事项

(1)使用select函数之前一般要用FD_ZERO和FD_SET初始化文件描述符集合

(2)在重复调用select函数的时候,先把一次初始化好的文件描述符集合备份下来,每次读取他即可

(3)在select返回以后,可循环使用FD_ISSET来测试描述符集合

(4)在执行完对相关文件描述符的操作以后,用FD_CLR清除该文件描述符

四.poll函数说明

1.头文件

<sys/types.h>

<poll.h>

2.函数原型

int poll(struct pollfd *fds,int numfds,int timeout);

3.参数说明

(1)fds:用于描述需要对哪些文件的哪种类型的操作进行监控

(2)numfds:需要监听的文件个数,即第一个参数所指向的数组中的元素数目

(3)timeout:阻塞的超时时间,精确到毫秒级别,如果小于0,表示无限等待

4.返回值:

成功:大于0,表示事件发生的pollfd结构的个数

失败:-1

超时:0

五.使用实例

1.select的弊端

(1)内核必须检查多余的文件描述符

(2)每次调用select以后都要重置被监听的文件描述符集合

(3)可监听的文件描述符个数受限制

2.用mknod命令创建两个管道in1,in2,然后在两个虚拟终端分别运行cat>in1和cat>in2,同时在第三个终端运行主程序。

3.如果三个文件一直处于无输入状态,则主程序一直处于阻塞状态,为了防止无限期等待,在主程序中设置超时值。

4.实际代码

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <poll.h>

#define MAX_BUFSIZE  1024
#define IN_FILES 3
#define TIME_OUT 60000
#define MAX(a,b)    ((a > b) ? (a): (b))

int main(void)
{

    struct pollfd fds[IN_FILES];
    
    char buf[MAX_BUFSIZE];

    int i,res,real_read,maxfd;

    /*open two source files with some permission*/

    fds[0].fd = 0;

    if((fds[1].fd = open("in1",O_RDONLY|O_NONBLOCK)) < 0)
    {
        printf("open in1 error!\n");
        return 1;
    }

    if((fds[2].fd = open("in2",O_RDONLY|O_NONBLOCK)) < 0)
    {
        printf("open in2 error!\n");
        return 1;
    }

    /*achieve the bigger one from two filedescriptions*/
    for(i = 0; i < IN_FILES;i++)
    {

        fds[i].events = POLLIN;
    }

    while(fds[0].events || fds[1].events || fds[2].events)
    {

        if(poll(fds,IN_FILES,0) < 0)
        {
            printf("Poll error or time out\n");
            return 1;
        }
        for(i = 0;i < IN_FILES;i++)
        {
            if(fds[i].events)
            {
                memset(buf,0,MAX_BUFSIZE);
                real_read = read(fds[i].fd,buf,MAX_BUFSIZE);
                if(real_read < 0)
                {

                    if(errno != EAGAIN)
                    {

                        return 1;
                    }
                }
                else if(!real_read)
                {
                    close(fds[i].fd);
                    fds[i].events = 0;                        
                }
                else{

                    if(i == 0)
                    {

                        if((buf[0] == 'q') || (buf[0] == 'Q'))
                        {
                            return 1;
        
                        }
                    }
                    else{

                        buf[real_read] = '\0';
                        printf("%s",buf);
                    }
                }

            }
        }

    }

    exit(0);    
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值