595|0

220

帖子

1

TA的资源

一粒金砂(高级)

楼主
 

《原子Linux驱动开发》+阻塞和非阻塞IO,异步通知 [复制链接]

《原子Linux驱动开发》这本书主要聚焦于Linux内核驱动开发的核心概念和实现方法,对于驱动开发者来说是一本非常有价值的参考书籍。在驱动开发中,处理输入/输出(I/O)是常见的任务,而阻塞和非阻塞I/O以及异步通知是处理I/O操作的几种重要方法。

阻塞I/O

阻塞I/O是一种常见的I/O模式,在这种模式下,当线程发起一个I/O操作(如读取或写入)时,如果数据没有准备好,线程会阻塞(即暂停执行),直到数据准备好。这意味着线程在等待数据期间无法执行其他任务,从而可能导致资源利用率低下。

非阻塞I/O

与阻塞I/O不同,非阻塞I/O允许线程在等待数据准备好的同时执行其他任务。如果数据没有准备好,非阻塞I/O调用会立即返回错误,而不是让线程阻塞。这提高了系统的响应性和吞吐量,但也可能增加程序的复杂性,因为线程需要不断地检查数据是否准备好。

异步通知

异步通知是一种机制,用于在数据准备好时通知线程,而不是让线程主动轮询或阻塞。这通常通过中断、信号或回调函数来实现。当数据准备好时,硬件或内核会触发一个通知,告知线程可以进行I/O操作。这种机制可以提高系统的效率和响应性,特别是在处理大量并发I/O操作时。

在Linux驱动开发中,实现这些I/O模式需要深入理解Linux内核的I/O机制、中断处理、信号量、等待队列等概念。驱动开发者需要根据具体的应用场景和需求选择适合的I/O模式,并合理地设计驱动程序的结构和接口。

 

 

在Linux系统中,非阻塞I/O访问模式是一种常见的方法,用于处理那些可能需要花费较长时间等待的操作,比如从设备读取数据。当设备不可用或数据未准备好时,非阻塞I/O调用会立即返回一个错误码,而不是让调用线程进入睡眠状态等待数据准备好。这样,应用程序可以继续执行其他任务,而不是阻塞等待数据。

 

 select()函数允许一个进程监视多个文件描述符,以查看它们中的任何一个是否已准备好进行读、写或异常操作。这在处理多个套接字或文件描述符时特别有用,因为它允许进程非阻塞地等待多个事件。

select() 函数原型

参数解释
  • nfds:这是所有文件描述符集合中最大的文件描述符加1。这通常设置为要监视的所有文件描述符中的最大值加1。
  • readfds:指向fd_set结构的指针,用于监视准备读操作的文件描述符。
  • writefds:指向fd_set结构的指针,用于监视准备写操作的文件描述符。
  • exceptfds:指向fd_set结构的指针,用于监视异常条件。
  • timeout:指向timeval结构的指针,指定了select()等待的最长时间。如果为NULL,则select()将无限期等待。

 

  • FD_ZERO(fd_set *set): 清除fd_set集合的所有位。
  • FD_SET(int fd, fd_set *set): 在fd_set集合中设置与文件描述符fd相关联的位。
  • FD_CLR(int fd, fd_set *set): 清除fd_set集合中与文件描述符fd相关联的位。
  • FD_ISSET(int fd, fd_set *set): 测试fd_set集合中是否设置了与文件描述符fd相关联的位。

 

epoll()函数是Linux特有的I/O复用函数,用于处理大量的并发连接。相比于select和poll函数,epoll在性能上有所提升和改进。

epoll函数通过一组相关的函数来实现I/O复用,它使用一种高效的事件通知机制,将用户关心的文件描述符上的事件放在内核里的一个事件表中。这样,就无需像select和poll那样每次调用都要重复传入文件描述符集或事件集,从而提高了效率。

使用epoll函数,通常需要经过以下步骤:

  1. 创建epoll文件描述符:通过调用epoll_create函数来创建一个epoll实例,并返回一个用于后续操作的文件描述符。
  2. 添加文件描述符到epoll中:使用epoll_ctl函数将需要监视的文件描述符添加到epoll实例中。这个函数可以进行注册、修改或删除文件描述符上的事件。
  3. 等待事件的发生:调用epoll_wait函数来等待在epoll实例上注册的文件描述符上的事件发生。当有事件发生时,该函数会返回并告知哪些文件描述符就绪,可以进行相应的读或写操作。

 

 

 

关于Linux中的信号机制。信号是一种软件中断,用于通知进程发生了某个事件。在Linux系统中,信号用于通知进程各种异步事件,如用户按键、硬件故障、进程异常等。每个信号都有一个唯一的编号,并且通常与一个默认的行为相关联。

正如您所提到的,大多数信号都可以被进程捕获并处理,但是有几个信号是例外,例如SIGKILL和SIGSTOP。SIGKILL信号用于强制终止进程,它不能被忽略、阻塞或捕获。SIGSTOP信号用于暂停进程的执行,同样不能被忽略或捕获。

在应用程序中,可以使用signal()函数或更现代的sigaction()函数来设置信号的处理函数。当进程接收到一个信号时,如果该信号的处理函数已被设置,那么就会调用这个处理函数来响应这个信号。

 

由于信号是异步的,因此信号处理函数应该尽可能简单和快速,避免执行可能阻塞或长时间运行的操作。这是因为信号可能在程序的任何时刻到达,如果处理函数执行复杂操作,可能会导致不可预测的行为或死锁。

此帖出自Linux开发论坛
点赞 关注

回复
举报
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表