非阻塞IO
在应用程序中读取硬件数据时,无论硬件数据是否准备完毕,read()函数不会阻塞,继续向下执行
阻塞IO
当应用程序中读取硬件数据时,在硬件数据没有准备好时,进程会阻塞在read()函数位置,直到硬件数据就绪,程序继续向下执行,进程阻塞等待数据时处于休眠状态
D uninterruptible sleep (usually IO) //不可中断休眠态,不能通过外部信号将进程结束
S interruptible sleep (waiting for an event to complete)//可中断休眠态
相关函数:
1.定义等待队列头 wait_queue_head_t wq_head;
2.初始化等待队列头 init_waitqueue_head(&wq_head);
3.wait_event(wq_head, condition)
功能:检查condition的真假,如果为真,则函数执行结束,如果为假,将进程切换到不可中断休眠状态
参数:wq_head:等待队列头
condition:标志变量
4.wait_event_interruptible(wq_head, condition)
功能:检查condition的真假,如果为真,则函数执行结束,如果为假,将进程切换到可中断休眠状态
参数:wq_head:等待队列头
condition:标志变量 返回值:如果condition为真则返回0,如果被一个信号中断,则返回错误码-ERESTARTSYS
5.wake_up(&wq_head)
功能:将不可中断休眠态的进程唤醒,当执行这个函数时如果condition为假,则进程被唤醒后会再次休眠
参数:等待队列头地址
6.wake_up_interruptible(&wq_head)
功能:将 可中断休眠态的进程唤醒当执行这个函数时如果condition为假,则进程被唤醒后会再次休眠
参数:等待队列头地址
IO多路复用
IO多路复用的实现机制有三种:select/poll/epoll。IO多路复用可以在一个进程中同时监听多个硬件数据,其将用户空间中监听到的事件文件描述符添加到时间集合中,调用函数进行判断集合中文件描述符对应的硬件数据是否准备就绪,如果没有一个事件发生,将进程切换到休眠状态,当有一个或者多个硬件数据准备好了,将休眠的进程唤醒,对准备好的硬件数据进行读写
SELECT:
select函数实现多路复用的步骤:
创建一个fd_set类型的集合,用于存放需要监视的文件描述符。
将需要监视的文件描述符添加到集合中,使用FD_SET宏定义实现。
调用select函数,传入需要监视的最大文件描述符值、读集合、写集合、异常集合以及超时时间等参数。
select函数会阻塞等待,直到有一个或多个文件描述符就绪或超时,返回可读、可写或异常状态的文件描述符数目。
根据返回值,可以通过FD_ISSET宏定义来判断哪些文件描述符已经就绪,进行相应的处理。
需要注意的是,在使用select函数时,需要注意文件描述符的数量和性能问题,过多的文件描述符可能会导致select函数效率降低。
POLL:
阻塞函数,让内核检测指定文件描述符集合中,是否有文件描述符准备就绪,当文件描述符准备就绪后,该函数解除阻塞。
EPOLL:
核心操作:一颗树、一张表、三个接口
调用
epoll_create
创建一个 epoll 实例,并使用epoll_ctl
向 epoll 实例中添加文件描述符,然后调用epoll_wait
等待事件的发生。具体步骤如下:
- 调用
epoll_create
创建一个 epoll 实例,返回一个文件描述符。- 通过
epoll_ctl
向 epoll 实例中添加文件描述符,指定要监听的事件类型和事件处理函数。- 调用
epoll_wait
等待事件的发生,返回就绪的文件描述符列表。- 处理就绪的文件描述符,执行相应的操作。