Linux内核(七)轮询 *** 作

Linux内核(七)轮询 *** 作,第1张

在用户程序中,select()和poll()也是与设备阻塞和非阻塞访问相关的内容。

使用非阻塞IO的应用程序通常会使用select()和poll()系统调用查询是否可以对设备进行无阻塞的访问。

select()和poll()系统调用最终会使设备驱动中的poll()函数执行,在后续的Linux内核版本中还引入了epoll(),即扩展的poll()。

select()和poll()系统调用的本质是一样的,前者在BSD Unix中引入,后者在System V中引入。

应用程序中使用最广泛的是BSD Unix中引入的select()系统调用,原型如下:

如下图所示,

第一次对n个文件进行select()的时候,若任何一个文件满足要求,select()就直接返回;

第二次再进行select()的时候,没有文件满足读写要求,select()的进程阻塞且睡眠。

由于调用select()的时候,每个驱动的poll()接口都会被调用到。实际上执行select()的进程被挂到了每个驱动的等待队列上,可以被任何一个驱动唤醒。如果FDn变得可读写,select()返回。

poll()的功能和实现原理与select()类似,其原型函数为:

当多路复用的文件数量庞大、IO流量频繁的时候,一般不太适合使用select()和poll(),这种情况下select()和poll()表现较差,推荐使用epoll()。

使用epoll()最大的好处就是不会随着fd数目的增长而降低效率,select()则会随着fd数量增大性能明显下降。

相关接口:

创建一个epoll()的句柄,size用来告诉内核要监听多少个fd,当创建好epoll()句柄时,它本身也会占用一个fd值,所以在使用完epoll()后,必须调用close()关闭。

告诉内核要监听什么类型的事件:

第一个参数epfd是epoll_create()的返回值,

第二个参数表示动作,包含:

第3个参数是需要监听的fd,

第4个参数是告诉内核需要监听的事件类型,struct_epoll_event结构如下:

events可以是以下几个宏的”或“:

一般来说,当涉及的fd数量较少时,使用select是合适的;如果涉及的fd很多,如在大规模并发的服务器中监听许多socket的时候,则不太适合选用select,适合使用epoll。

内核开发者ArndBergmann发出了一个新的补丁,允许Linux内核在指定C11的GNU方言时默认使用“-std=gnu11”。

事件的前因后果为,Linux内核社区日前曾讨论了是否要为内核采用现代C语言标准。Linus在讨论中提出了从C89提升到C99的想法;并表示,内核代码一直停留在C89的原因之一是编译器gcc的旧版本会出现奇怪的问题,导致初始化程序被破坏。但现在内核要求的GCC最低版本已经提高到了v5.1,那些bug可能已经不再相关。

最后事实证明,以当前内核的最低版本编译器要求和当前代码的条件,他们实际上可以开始使用C11构建内核。ArndBergmann提议直接升级到C11甚至C2x。虽然他不确定C11是否会带来任何对内核有用的新内容,但如果升级到C17或C2x,会破坏对gcc-5/6/7的支持;因此升级到C11更容易实现,而且跨越太大内核社区未必接受。

Linus对该想法表示了赞成。在Bergmann确认此举可行后,Linus宣布将在下一个内核版本v5.18中尝试使用C11标准。


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/yw/6240231.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-03-18
下一篇2023-03-18

发表评论

登录后才能评论

评论列表(0条)

    保存