非阻塞IO
在应用程序中读取硬件数据时,不管硬件数据有没有准备好,read()函数不会阻塞,而是继续向下执行
阻塞IO
当应用程序中读取硬件数据时,如果硬件数据没有准备好,此时进程阻塞在read()函数位置,直到硬件数据就绪,通过read()函数读取硬件数据,程序向下执行,进程阻塞等待数据时处于休眠态
休眠状态分为两种:
D uninterruptible sleep (usually IO) 不可中断休眠态,不能通过外部信号将进程结束
S interruptible sleep (waiting for an event to complete) 可中断休眠态
相关API
- 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
select:
(1)阻塞函数,让内核检测指定文件描述符集合中,是否有文件描述符准备就绪
(2)当文件描述符准备就绪后,该函数解除阻塞。
(3)当事件产生后,集合中会只剩下触发事件的文件描述符。
poll:阻塞函数,让内核检测指定文件描述符集合中,是否有文件描述符准备就绪,当文件描述符准备就绪后,该函数解除阻塞。
epoll核心操作:一颗树、一张表、三个接口
epoll相关API
- #include <sys/epoll.h>
- 1.int epoll_create(int size);
- 功能:创建一个新的epoll
- 参数:
- size:大于0的整数
- 返回值:成功返回用于操作epoll的文件描述符,失败返回错误码
- 2.int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
- 功能:进行epoll管理
- 参数:
- epfd:epoll_create生成的文件描述符
- op:管理的类型选项
- EPOLL_CTL_ADD:用于在epoll上添加文件描述符
- EPOLL_CTL_MOD:用于修改文件描述符事件类型
- EPOLL_CTL_DEL:从epoll上移除指定的文件描述符
- fd:要操作的文件描述符
- event:设置文件描述符属性的变量
- struct epoll_event {
- uint32_t events; /* Epoll events */
- //EPOLLIN:读
- //EPOLLOUT:写
- epoll_data_t data; /* User data variable */
- };
- typedef union epoll_data {
- void *ptr;
- int fd;《=======使用这个
- uint32_t u32;
- uint64_t u64;
- } epoll_data_t;
- 返回值: 成功返回0,失败返回错误码
- 3.int epoll_wait(int epfd, struct epoll_event *events,
- int maxevents, int timeout);
- 功能:阻塞等待事件发生
- 参数:
- epfd:epoll_create生成的文件描述符
- events: 存放发生的事件的文件描述符数组的首地址
- maxevents:监听的文件描述符最大个数
- timeout:设置超时事件 毫秒级 -1表示不关注超时 >0超时事件
- 返回值:
- >0:发生事件的文件描述符个数
- ==0:超时时间到达
- <0:失败