Jos*_*hua 12 sockets linux networking kernel system-calls
我正在开发的一个Linux内核驱动程序是在内核中使用网络通信(sock_create(),sock->ops->bind()等等).
问题是将有多个套接字从中接收数据.所以,我需要的东西,将模拟select()或poll()在内核空间.由于这些函数使用文件描述符,我不能使用系统调用,除非我使用系统调用来创建套接字,但这似乎是不必要的,因为我在内核中工作.
所以我想sock->sk_data_ready在我自己的handler(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())并创建一个worker(struct work_struct)和工作队列(struct workqueue_struct).process_msg()每个工人都将使用一个常用功能.创建一个内核模块级全局列表,其中每个列表元素都有一个指向套接字的指针并包含工作者结构.当数据在套接字上准备就绪时,custom_sk_data_ready()将执行并找到具有相同套接字的匹配列表元素,然后queue_work()使用list元素的工作队列和worker 进行调用.然后process_msg()调用该函数,并且可以通过struct work_struct *参数的内容(地址)找到匹配的列表元素,或者使用container_of()宏来获取包含工作者结构的列表结构的地址.
哪种技术最健全?