Download presentation
Presentation is loading. Please wait.
1
第九课 高级文件 IO 编程
2
本章的主要内容 高级文件 IO 概述 Select 模型 Poll 模型 实验
3
高级 IO I/O 的方式有很多种,我们之前使用的 IO 方式的特点是: – 单路:只能等待一个 fd 可读或可写 – 阻塞:睡眠直到 fd 可读或可写 – 同步: read 和 write 必须结束才返回?? 因此有与之对应的: – 多路:同时等待多个 fd 可读或可写 – 非阻塞: fd 不可读或不可写立即返回 – 异步: I/O 没有结束 read 和 write 也可返回
4
非阻塞 I/O 以非阻塞方式打开一个文件,如: fd = open(“love.txt”, O_RDWR | O_NONBLOCK, 0); 也可以用 fcntl 让一个已经打开的文件描述 字变成非阻塞: flags = fcntl(fd, F_GETFL, 0); fcntl(fd, F_SETFL, flags | O_NONBLOCK);
5
非阻塞 I/O 对一个非阻塞的 fd 来说,如果它无数据可 读,则 read(fd, …); 返回 -1 , errno 的值被 置为 EAGAIN ;同样,如果它暂时不可写, write(fd, …); 返回 -1 , errno=EAGAIN 。 (阻塞式 I/O 在这两种情况下都是等待)。 注意:应当区分无数据可读与文件已经读 到结尾。后者 read 返回 0 ,无论阻塞否。 非阻塞 I/O 经常与多路 I/O 配合使用。
6
多路 I/O 想像一个 fd 集合 fdset ,以及一个函数 fun , 我们指定:调用 fun(fdset) 进程进入睡眠, 直到 fdset 中至少有一个 fd 可读,此时 fun 返 回并把可读的 fd 保存在 fdset 中。 这样做的好处是,我们可以同时从多个 fd 中等待数据,如果某一个可读我们就从中 读取,否则就睡眠。
7
多路 I/O Unix 下就存在这种的一个 fun ,但它的功能更加强大。 它就是 select (在有的系统下为 poll , Linux 都支持) 函数原型: #include int select(int maxfdp1, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
8
多路 I/O 函数的声明太复杂。编写一个程序来综合 的演示多路 I/O ,非阻塞 I/O ,以及 FIFO 。
9
I/O 处理的模型 阻塞 I/O 模型:在这种模型下,若所调用的 I/O 函数没有完 成相关的功能,则会使进程挂起,直到相关数据到达才会 返回。如常见对管道设备、终端设备和网络设备进行读写 时经常会出现这种情况。 非阻塞模型:在这种模型下,当请求的 I/O 操作不能完成时, 则不让进程睡眠,而且立即返回。非阻塞 I/O 使用户可以 调用不会阻塞的 I/O 操作,如 open() 、 write() 和 read() 。如 果该操作不能完成,则会立即返回出错(例如:打不开文 件)或者返回 0 (例如:在缓冲区中没有数据可以读取或 者没空间可以写入数据)。
10
I/O 多路转接模型:在这种模型下,如果请求的 I/O 操作阻塞,且它不是真正阻塞 I/O ,而是让其中的 一个函数等待,在这期间, I/O 还能进行其他操作。 如本节要介绍的 select() 和 poll 函数 () ,就是属于这 种模型。 信号驱动 I/O 模型:在这种模型下,通过安装一个 信号处理程序,系统可以自动捕获特定信号的到 来,从而启动 I/O 。这是由内核通知用户何时可以 启动一个 I/O 操作决定的。 异步 I/O 模型:在这种模型下,当一个描述符已准 备好,可以启动 I/O 时,进程会通知内核。现在, 并不是所有的系统都支持这种模型。
11
select() 和 poll() select() 和 poll() 的 I/O 多路转接模型是处理 I/O 复用的一个高效的方法。它可以具体设 置程序中每一个所关心的文件描述符的条 件、希望等待的时间等,从 select() 和 poll() 函数返回时,内核会通知用户已准备好的 文件描述符的数量、已准备好的条件等。 通过使用 select() 和 poll() 函数的返回结果, 就可以调用相应的 I/O 处理函数了。
12
select() 函数格式( 1 )
13
select() 函数格式( 2 ) 一般来说,在使用 select() 函数之前,首先使用 FD_ZERO() 和 FD_SET() 来初始化文件描述符集,在使用了 select() 函数时,可 循环使用 FD_ISSET() 来测试描述符集,在执行完对相关文件描 述符的操作之后,使用 FD_CLR() 来清除描述符集。
14
poll() 函数格式
15
思考与练习 使用多路复用函数实现 3 个串口的通信:串 口 1 接收数据,串口 2 和串口 3 向串口 1 发送 数据。
Similar presentations