您的位置:首页 > 编程语言

文件编程(4)多路复用

2015-01-08 10:15 78 查看
一.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);

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: