模拟内核套接字编程的选择)的效果(和poll()(Simulate effect of select

2019-07-30 05:56发布

一个Linux内核驱动程序我开发的是在内核中使用网络通信( sock_create() sock->ops->bind() ,等等)。

问题是,将有多个插槽,从接收数据。 所以,我需要的东西,将模拟select()poll()在内核空间。 由于这些函数使用的文件描述符,我不能使用系统调用,除非我用的系统调用来创建套接字,但似乎没有必要,因为我在内核中很努力。

所以我在想包装默认的sock->sk_data_ready处理我自己的处理程序( custom_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标志。


另一种可能性:

对于每一个开放式插槽,替换每个插座的sk_data_ready()有一个自定义( custom_sk_data_ready()并创建一个工作( struct work_struct )和工作队列( struct workqueue_struct )。 一个常见的process_msg()函数将使用每个工人。 创建一个内核模块级的全局列表,其中每个列表元素的指针指向插座和包含劳动者结构。 当数据准备好一个插座上, custom_sk_data_ready()将签署并找到具有相同插座匹配列表元素,然后调用queue_work()与列表元素的工作队列和工人。 然后process_msg()函数将被调用,并且可以通过内容查找匹配列表元素struct work_struct *参数(地址),或使用container_of()宏来获取用于保存列表结构的地址工人结构。

哪种技术是最声音?

Answer 1:

你的第二个想法听起来更像是它的工作。

该CEPH代码看起来像它类似的东西,见net/ceph/messenger.c



文章来源: Simulate effect of select() and poll() in kernel socket programming