Unix下五种IO模型

http://blog.chinaunix.net/uid-25324849-id-247813.html

1. I/O模型 
Unix下共有五种I/O模型 
a. 阻塞I/O 
b. 非阻塞I/O 
c. I/O复用(select和poll) 
d. 信号驱动I/O(SIGIO) 
e. 异步I/O(Posix.1的aio_系列函数) 
1). 阻塞I/O模型 
应用程序调用一个IO函数,导致应用程序阻塞,等待数据准备好。 
如果数据没有准备好,一直等待。。。。 
数据准备好了,从内核拷贝到用户空间 
I/O函数返回成功指示

2). 非阻塞I/O模型 
我们把一个套接口设置为非阻塞就是告诉内核,当所请求的I/O操作无法完成时,不要将进程睡眠,而是返回一个错误。这样我们的I/O操作函数将不断的测试 数据是否已经准备好,如果没有准备好,继续测试,直到数据准备好为止。在这个不断测试的过程中,会大量的占用CPU的时间。

3). I/O复用模型 
I/O复用模型会用到select或者poll函数,这两个函数也会使进程阻塞,但是和阻塞I/O所不同的的,这两个函数可以同时阻塞多个I/O操作。而且可以同时对多个读操作,多个写操作的I/O函数进行检测,直到有数据可读或可写时,才真正调用I/O操作函数。 

4). 信号驱动I/O模型 
首先我们允许套接口进行信号驱动I/O,并安装一个信号处理函数,进程继续运行并不阻塞。当数据准备好时,进程会收到一个SIGIO信号,可以在信号处理函数中调用I/O操作函数处理数据。

5). 异步I/O模型 
调用aio_read函数,告诉内核描述字,缓冲区指针,缓冲区大小,文件偏移以及通知的方式,然后立即返回。当内核将数据拷贝到缓冲区后,再通知应用程序。

2. 几种I/O模型的比较 
前四种模型的区别是第一阶段基本相同,第二阶段基本相同,都是将数据从内核拷贝到调用者的缓冲区。而异步I/O的两个阶段都不同于前四个模型。

3. 同步I/O和异步I/O 
a. 同步I/O操作引起请求进程阻塞,直到I/O操作完成。 
异步I/O操作不引起请求进程阻塞。 
b. 我们的前四个模型都是同步I/O,只有最后一个异步I/O模型是异步I/O。

部分内容来自:http://blog.csdn.net/sunyubo458/archive/2010/12/24/6096723.aspx

4. Select函数 
a. Select函数可以指示内核等待多个事件中的任一个发生,并仅在任一个事件发生或经某个指定的时间后才返回,才唤醒进程 
b. 可以调用select函数,通知内核在下列情况发生时才返回: 
集合{1,4,5}中的任何描述符准备好读,或者 
集合{2,7}中的任何描述符准备好写,或者 
集合{1,4}中任何描述符有异常条件待处理,或者 
已经经过了10.2秒 
c.描述字可以不受限制与套接字,任意的描述符都可以用select来测试 
d. 函数原型 
int select(int maxfds, fd_set *readfds, fd_set *writefds, 
      fd_set *exceptfds, struct tim *timeout); 
参数说明: 
timeout:告诉内核等待任一描述符准备好可以花费的时间,这里会有三种情况, 
第一种情况是timeout是NULL,这样将一直等待,直到某个描述符准备好; 
第二种情况是timeout的值是0,那么将不等待,立即返回; 
第三种情况是timeout中的秒或微秒被赋值,那么将等待指定的时间。 
此外,如果进程收到一个信号,select也会被中断返回。 
readfds,writefds和exceptfds指定了让内核测试读,写和异常条件所需的描述字。 
maxfds:说明了被测试的描述符的个数,它的值是要被测试的最大的描述符加1. 
返回值:所有描述符集的已准备好的总位数。返回时,描述符集中任何没有准备好的描述符都被清0,我们用FD_ISSET来测试是哪个描述符准备好了。因此,每次调用select时,都要重新将我们关心的描述符在描述符集中置为1. 
e. fd_set说明 
fd_set是一个整数数组,每个数中的每一位对应一个描述符。例如用32位表示一个整数,那么数组的第一个元素对应于描述字0~31,第二个元素对应于描述字32~63. 
四个相关的宏: 
       FD_CLR(int fd, fd_set *set); 
      FD_ISSET(int fd, fd_set *set); 
      FD_SET(int fd, fd_set *set); 
      FD_ZERO(fd_set *set); 
f.描述符准备好读的条件: 
套接口缓冲区中的数据字节大于等于套接口接收缓冲区低潮限度的当前值。套接口将不阻塞并返回一个大于0的值,就是当前准备好读的数据字节数。 
套接口收到一个FIN,套接口的读操作将返回一个0. 
套接口是一个监听套接口,并且以完成的连接数非0。 
有一个套接口错误待处理。套接口的读操作将返回-1. 
g.描述符准备好写的条件: 
套接口发送缓冲区的可用空间大于等于套接口发送缓冲区低潮限度的当前值。,且或者套接口以连接,套接口不要求连接。 
套接口写这一半关闭,这样将产生一个SIGPIPE错误。 
有一个套接口错误待处理。 
h.描述符异常的条件: 
套接口存在带外数据 
仍处于带外标记 
i. 每个进程可以使用的最大描述符 
有一个宏FD_SETSIZE定义了一个进程可以使用的最大描述符数。如果要更改这个值不仅仅要在定义的头文件中改变,还要重新编译内核。

5. 使用select函数修改前面的客户-服务器程序 
在前面的客户-服务器程序中,客户端采用的是停-等这样的策略来接收来自标准输入的用户输入,这样的好处是可以一对一的完成从用户输入,然后读取从服务器 返回的字符串,这样的弊端是当程序阻塞在等待用户输入时,无法及时的处理来自服务器的FIN等这些消息。现在我们用select函数将客户端程序做一些修 改,使能避免前面提到的问题。 
另外,服务器也采用select函数,从而避免产生过多的进程,使用select后可以只有一个进程就可以处理多个客户端。在服务器端建立一个整数型的数 组,用来存放已经完成的客户端连接。每次从见天套接口读到数据后,我们将新的来自客户端的连接加入到这个数组中,并且修改maxfd的值。每次从客户端套 接口读到数据后,将读到的数据重新写回到客户端套接口。 
a.服务器从客户套接口读到数据后,返回值有可能为0,这说明客户端已经关闭了写这个方向的连接。在将数据写入客户端套接口后,要将连接关闭。并将客户连接从存放客户连接的数组中移除。 
b.采用上面的方案,存在一个潜在的问题就是可能受到拒绝服务的攻击。一个恶意用户和服务器建立连接,发送单个字符,但是没有发送换行符或者终止,这样服 务器将阻塞在read函数中。可能的解决办法是采用非阻塞I/O或者让每个客户用单独的进程来处理或者为I/O操作设置超时。 
c.客户端接收到EOF时,只能关闭写这个方向的连接,因为我们仍然希望读取来自服务器的数据。此时是不能用close来关闭连接的,而要用 shutdown来关闭。如果套接字的访问计数大于0,那么close只是将计数减1;如果套接字的访问计数等于0,close将终止套接字的两个方向, 那样我们将不能读取仍然没有从服务器发送回来的数据。 
6. shutdown函数 
int shutdown(int s, int how); 
参数说明: 
s: 代表套接字描述字 
how:SHUT_RD    -- 关闭套接字的读取数据方向的连接 
     SHUT_WR    -- 关闭套接字的写入数据方向的连接 
     SHUT_RDWR -- 关闭套接字双向的连接 
7. pselect函数 
int pselect(int n, fd_set *readfds, fd_set *writefds, 
      fd_set *exceptfds, const struct timespec *timeout, const 
      sigset_t *sigmask); 
a.pselect函数采用timespec结构,这个结构支持纳秒 
b.sigmask是信号掩码,将禁止递交某些信号 
8. poll函数 
int poll(struct pollfd *ufds, unsigned int nfds, int timeout); 
a.参数说明 
ufds: 是一个struct pollfd结构体的指针 
nfds: 说明我们关心的描述字的个数 
timeout: 超时等待的时间,单位是毫秒 
b.struct pollfd结构体说明 
       struct pollfd { 
             int fd;          
             short events;    
             short revents;   
      }; 
fd: 是描述字 
events: 是在描述字上关心的事件 
revents: 是在描述字上返回的事件

poll函数返回后我们要测试revents中的事件是否是我们关心的。

时间: 2024-10-20 15:20:01

Unix下五种IO模型的相关文章

Linux下的五种IO模型

5种IO模型 Linux下五种IO模型 (1)阻塞I/O:什么都不干,导致应用程序阻塞,等待数据准备好,如果数据没有准备好,一直阻塞,等数据准备好了从内核拷贝到用户空间 (2)非阻塞I/O:把一个套接字接口设置为非阻塞,告诉内核,当所请求的IO无法完成时,不要将进程睡眠,而是返回一个错误,这样IO操作函数会不断地测试数据是否准备好,如果没有准备好 ,继续测试,直到准备好为止 (3)I/O复用(select epoll):select或epoll会使进程阻塞,但是和阻塞IO不同的是,这两个函数可以

简述linux同步与异步、阻塞与非阻塞概念以及五种IO模型

1.概念剖析 相信很多从事linux后台开发工作的都接触过同步&异步.阻塞&非阻塞这样的概念,也相信都曾经产生过误解,比如认为同步就是阻塞.异步就是非阻塞,下面我们先剖析下这几个概念分别是什么含义. 同步:所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回.也就是必须一件一件事做,等前一件做完了才能做下一件事. 例如普通B/S模式(同步):提交请求->等待服务器处理->处理完毕返回 这个期间客户端浏览器不能干任何事 异步:异步的概念和同步相对.当一个异步过程

linux同步与异步、阻塞与非阻塞概念以及五种IO模型

1.概念剖析 相信很多从事linux后台开发工作的都接触过同步&异步.阻塞&非阻塞这样的概念,也相信都曾经产生过误解,比如认为同步就是阻塞.异步就是非阻塞,下面我们先剖析下这几个概念分别是什么含义. 同步:所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回.也就是必须一件一件事做,等前一件做完了才能做下一件事. 例如普通B/S模式(同步):提交请求->等待服务器处理->处理完毕返回 这个期间客户端浏览器不能干任何事 异步:异步的概念和同步相对.当一个异步过程

聊聊 Linux 中的五种 IO 模型

本文转载自: http://mp.weixin.qq.com/s?__biz=MzAxODI5ODMwOA==&mid=2666538919&idx=1&sn=6013c451b5f14bf809aec77dd5df6cff&scene=21#wechat_redirect 上一篇<聊聊同步.异步.阻塞与非阻塞>已经通俗的讲解了,要理解同步.异步.阻塞与非阻塞重要的两个概念点了,没有看过的,建议先看这篇博文理解这两个概念点.在认知上,建立统一的模型.这样,大家在

聊聊Linux 五种IO模型

1 概念说明 在进行解释之前,首先要说明几个概念: 用户空间和内核空间 进程切换 进程的阻塞 文件描述符 缓存 IO 1.1 用户空间与内核空间 现在操作系统都是采用虚拟存储器,那么对32位操作系统而言,它的寻址空间(虚拟存储空间)为4G(2的32次方).操作系统的核心是内核,独立于普通的应用程序,可以访问受保护的内存空间,也有访问底层硬件设备的所有权限.为了保证用户进程不能直接操作内核(kernel),保证内核的安全,操作系统将虚拟空间划分为两部分,一部分为内核空间,一部分为用户空间.针对li

Linux五种IO模型

Linux五种IO模型 转载:http://blog.csdn.net/jay900323/article/details/18141217 Linux五种IO模型性能分析 目录(?)[-] 概念理解 Linux下的五种IO模型 阻塞IO模型 非阻塞IO模型 IO复用模型 信号驱动IO 异步IO模型 个IO模型的比较 selectpollepoll简介 1. 概念理解 在进行网络编程时,我们常常见到同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)四种调用方式:

Windows五种IO模型性能分析和Linux五种IO模型性能分析

Windows五种IO模型性能分析和Linux五种IO模型性能分析 http://blog.csdn.net/jay900323/article/details/18141217 http://blog.csdn.net/jay900323/article/details/18140847 重叠I/O模型的另外几个优点在于,微软针对重叠I/O模型提供了一些特有的扩展函数.当使用重叠I/O模型时,可以选择使用不同的完成通知方式. 采用事件对象通知的重叠I/O模型是不可伸缩的,因为针对发出WSAWa

Linux之——五种IO模型

一. 同步与异步 之前在对线程的谈论中提到了线程对临界资源访问的一个同步与互斥的关系,这里要强调,在IO模型中的同步与异步与线程的同步与互斥完全不是一回事. 所谓同步,就是指当调用者发出调用的时候,在没有得到结果之前调用并不返回,而是调用者自身一直在那里等待结果,至于等待的方式不同可以分为不同IO模型,下面会进行具体讨论:因此,这里的同步就可以理解为:调用者发出的调用(如一个系统调用函数)和所需要的结果是保持一致性也就是同步性的,你不给我结果,我就一直在那里等着就不返回,我不能单飞我一定要带着结

[转载] Linux五种IO模型

转载:http://blog.csdn.net/jay900323/article/details/18141217 Linux五种IO模型性能分析 目录(?)[-] 概念理解 Linux下的五种IO模型 阻塞IO模型 非阻塞IO模型 IO复用模型 信号驱动IO 异步IO模型 个IO模型的比较 selectpollepoll简介 1. 概念理解 在进行网络编程时,我们常常见到同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)四种调用方式:同步:      所谓同步