gpt4 book ai didi

linux - 模拟内核socket编程中select()和poll()的作用

转载 作者:IT王子 更新时间:2023-10-28 23:55:34 25 4
gpt4 key购买 nike

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

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

所以我想在我自己的处理程序 (custom_sk_data_ready()) 中包装默认的 sock->sk_data_ready 处理程序,这将解锁一个信号量。然后我可以编写自己的 kernel_select() 函数来尝试锁定信号量并进行阻塞等待直到它打开。这样内核函数就会进入休眠状态,直到信号量被 custom_sk_data_ready() 解锁。一旦 kernel_select() 获得锁,它就会解锁并调用 custom_sk_data_ready() 重新锁定它。因此,唯一的额外初始化是在绑定(bind)套接字之前运行 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()和 worker 。然后调用process_msg()函数,可以通过struct work_struct *参数(地址)的内容找到匹配的列表元素,也可以使用container_of() 宏来获取持有 worker 结构的列表结构的地址。

哪种技术最可靠?

最佳答案

你的第二个想法听起来更可行。

CEPH 代码看起来做了类似的事情,参见 net/ceph/messenger.c

关于linux - 模拟内核socket编程中select()和poll()的作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11336034/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com