(APUE点滴记录) I/O多路转接

来源:互联网 发布:日本围棋软件 编辑:程序博客网 时间:2024/06/05 00:21

2013-04-20 wcdj

一大早得知四川雅安发生7.0级地震,望灾区的人民尽快得到救助,祈福平安。


问题:

当从一个描述符读,然后又写到另一个描述符时,可以在下列形式的循环中使用阻塞I/O:

while ( (n = read(STDIN_FILENO, buf,BUFSIZ)) > 0 ){            if( write(STDOUT_FILENO, buf, n) != n )            {                        printf("write error\n");                        return1;            }}

但是如果需要从多个描述符读,上面的方法是不行的,如果仍旧使用阻塞I/O,那么就可能长时间阻塞在一个描述符上,而另一个描述符虽有很多数据却不能得到及时处理。针对这个问题,有哪些处理方法呢?

 

方法1:

用fork将一个进程变成两个进程,每个进程处理一条数据通路,即每个进程都执行阻塞read。

问题是:在进程终止时,使程序变得复杂。

 

方法2:

使用多线程单进程,这避免了终止的复杂性。

问题是:但却要求处理线程之间的同步,依然没有摆脱复杂性。

 

方法3:

使用单进程非阻塞I/O读数据,即轮询(polling)的方式。将多个描述符都设置为非阻塞的,对第一个描述符发一个read,如果该输入上有数据,则读数据并处理它;如果无数据可读,则read立即返回。然后对第二个描述符做同样的处理。所有描述符处理完之后,等待若干秒然后再进行轮询。

问题是:浪费CPU时间,因为大多数时间实际是无数据可读的,但仍花费时间不断反复执行read系统调用,在多任务系统中应当避免使用这种方法。

 

方法4:

异步I/O(asynchronous I/O),其思想是:告知内核启动某个操作,并让内核在整个操作(包括将数据从内核复制到我们自己的缓冲区)完成后通知我们。即,异步I/O模型是由内核通知我们I/O操作合适完成。

问题是:并非所有系统都支持这种机制。

 

方法5:

使用I/O多路转接(I/Omultiplexing)。先构造一张有关描述符的列表,然后调用一个函数,直到这些描述符中的一个已准备好进行I/O时,该函数才返回,在返回时,此函数告诉进程哪些描述符已准备好可以进行I/O。poll、pselect和select这三个函数使我们能够执行I/O多路转接。即,我们使用select可以等待多个描述符就绪。

 

PS: 关于I/O复用更多可以参考:

[1] UNPv3第六章

[2] APUEv2  14.5




原创粉丝点击