Linux 信号驱动IO
Linux 信号驱动IO
1. fcntl()
在Linux操作系统中,fcntl()
是一个用于操作文件描述符的系统调用。它提供了多种功能,包括控制文件描述符的属性、管理文件锁定、设置文件的非阻塞模式等。
本文只截取了用于IO模型的
fcntl()
部分内容,fcntl()
的详细内容请看—>Linux fcntl函数
在打开文件时,如果不使用fcntl()
对其进行设置,这个文件就默认使用阻塞IO。非阻塞IO和信号驱动IO都需要手动调用fcntl()
才能使用。
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, .../* arg */)
**fd:**需要进行操作的文件描述符。
**cmd:**指定要进行的操作。
F_GETFL
表示返回当前文件描述符的状态标志,如是否是非阻塞模式(O_NONBLOCK
)。F_SETFL
表示设置文件描述符的状态标志,在可变参数(arg
)中,输入要设置的状态标志,如O_NONBLOCK
(非阻塞模式)、O_ASYNC
(信号驱动模式)
int flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flags | O_NONBLOCK); // 设置非阻塞模式
//或
fcntl(fd, F_SETFL, flags | O_ASYNC); //设置信号驱动模式
2 信号驱动IO
信号驱动IO的原理是,当底层数据就绪时,向进程发送 SIGIO
信号,通知进程调用 recv()
读取数据。由于信号驱动 IO 也参与了 IO 的过程,所以信号驱动 IO 也属于同步 IO。
使用信号驱动 IO 首先要进行设置:
-
用
signal()
或sigaction()
添加SIGIO
信号及其自定义处理函数sig_handler()
。 -
用
fcntl()
设置FASYNC
标志,将文件描述符设置为信号驱动模式。fcntl()
会调用fasync_helper()
将指向该进程的指针加入到设备的异步通知队列中,表示该进程对设备的事件感兴趣。当事件发生时,比如设备驱动接收到数据,kill_fasync()
会遍历这个异步通知队列中,找到相应的进程发送SIGIO
信号。