加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Linux > 正文

linux – 在内核套接字编程中模拟select()和poll()的效果

发布时间:2020-12-13 18:27:00 所属栏目:Linux 来源:网络整理
导读:我正在开发的一个 Linux内核驱动程序是使用内核中的网络通信(sock_create(),sock- ops- bind()等). 问题是会有多个socket来接收数据.所以我需要一些可以在内核空间中模拟一个select()或poll()的东西.由于这些函数使用文件描述符,我不能使用系统调用,除非我使
我正在开发的一个 Linux内核驱动程序是使用内核中的网络通信(sock_create(),sock-> ops-> bind()等).

问题是会有多个socket来接收数据.所以我需要一些可以在内核空间中模拟一个select()或poll()的东西.由于这些函数使用文件描述符,我不能使用系统调用,除非我使用系统调用来创建套接字,但这似乎是不必要的,因为我在内核中工作.

所以我正在考虑在我自己的处理程序(custom_sk_data_ready())中包装默认的sock-> sk_data_ready处理程序,这将解锁一个信号量.然后我可以编写自己的kernel_select()函数来尝试锁定信号量,并进行阻塞等待,直到它打开.这样,内核函数进入休眠状态,直到信号量被custom_sk_data_ready()解锁为止.一旦kernel_select()获取锁定,它会解锁并调用custom_sk_data_ready()来重新锁定它.所以唯一的额外的初始化是在绑定套接字之前运行custom_sk_data_ready(),所以第一次调用custom_select()不会被错误地触发.

我看到一个可能的问题.如果发生多个接收,则对custom_sk_data_ready()的多个调用将尝试解锁信号量.因此,为了不丢失多个调用并跟踪正在使用的sock,将必须有一个表或列表,指向正在使用的套接字.而custom_sk_data_ready()将必须在表/列表中标识它被传递的套接字.

这种方法是否健全?还是应该在使用标准系统调用时与用户/内核空间问题进行斗争?

初步查询:

sock结构中的所有回调函数都在中断上下文中调用.这意味着他们不能睡觉.要允许主内核线程在准备好的套接字列表上进行休眠,使用互斥体,但是custom_sk_data_ready()必须像互斥体上的自旋锁一样(重复调用mutex_trylock()).这也意味着任何动态分配都必须使用GFP_ATOMIC标志.

额外的可能性:

对于每个开放的套接字,使用自定义的(custom_sk_data_ready())替换每个套接字的sk_data_ready(),并创建一个worker(struct work_struct)和工作队列(struct workqueue_struct).一个常用的process_msg()函数将用于每个工作.创建内核模块级全局列表,其中每个列表元素都有一个指向套接字的指针,并包含工作者结构.当套接字上的数据准备就绪时,custom_sk_data_ready()将执行并找到具有相同套接字的匹配列表元素,然后使用list元素的工作队列和worker调用queue_work().然后将调用process_msg()函数,并且可以通过struct work_struct *参数(一个地址)的内容来找到匹配的列表元素,或者使用container_of()宏来获取包含该属性的列表结构的地址工人结构.

哪种技术是最健全的?

解决方法

你的第二个想法听起来更像它会奏效.

CEPH代码看起来像是类似的,参见net / ceph / messenger.c.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读