内核线程与定时器
我正在编写一个使用自定义屏幕打印系统的内核模块。基本上每次涉及 print
时,字符串都会插入到链接列表中。 每隔 X 秒,我需要处理列表并在打印字符串之前对字符串执行一些操作。
基本上我有两种选择来实现这样的过滤器:
1)计时器(最终会自行重新启动)
2)休眠X秒的内核线程
当过滤器执行其操作时,没有其他东西可以使用链接列表,当然,插入字符串时,过滤函数将等待。
AFAIK 计时器在中断上下文中运行,因此它无法休眠,但是内核线程呢?他们能睡觉吗?如果是,有什么理由不在我的项目中使用它们吗?还可以使用什么其他解决方案?
总结一下:我的过滤函数只有 3 个要求:
1) 必须能够 printk
2) 使用列表时,尝试访问列表的所有其他内容都必须阻塞,直到过滤函数完成执行
3 )必须每 X 秒运行一次(不是实时要求)
I'm writing a kernel module which uses a customized print-on-screen system. Basically each time a print
is involved the string is inserted into a linked list.
Every X seconds I need to process the list and perform some operations on the strings before printing them.
Basically I have two choices to implement such a filter:
1) Timer (which restarts itself in the end)
2) Kernel thread which sleeps for X seconds
While the filter is performing its stuff nothing else can use the linked list and, of course, while inserting a string the filter function shall wait.
AFAIK timer runs in interrupt context so it cannot sleep, but what about kernel threads? Can they sleep? If yes is there some reason for not to use them in my project? What other solution could be used?
To summarize: my filter function has got only 3 requirements:
1) Must be able to printk
2) When using the list everything else which is trying to access the list must block until the filter function finishes execution
3) Must run every X seconds (not a realtime requirement)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
允许 kthread 休眠。 (但是,并非所有 kthread 都为所有客户端提供休眠执行。例如,softirqd 则不会。)
但话又说回来,您也可以使用自旋锁(及其相关成本)并且无需额外的线程(这基本上就是计时器的作用,使用 spinlock_bh)。这确实是一个权衡。
kthreads are allowed to sleep. (However, not all kthreads offer sleepful execution to all clients. softirqd for example would not.)
But then again, you could also use spinlocks (and their associated cost) and do without the extra thread (that's basically what the timer does, uses spinlock_bh). It's a tradeoff really.
我真的不知道您的意思是
print
还是printk
。但是,如果您正在谈论printk()
,则需要分配内存,并且您会遇到麻烦,因为printk()
可能会在原子上下文中调用。这使您可以选择使用循环缓冲区(因此,您应该容忍删除一些字符串,因为您可能没有足够的内存来保存所有字符串)。在这种情况下,我什至不会做内核线程:如果成本不是太高,我会在 print() 中进行处理。
否则,我将创建一个新的系统调用:
sys_get_strings()
或其他内容,它将整个链接列表转储到用户空间中(并在复制时从列表中删除条目)。这样整个行为就由用户空间控制。您可以创建一个守护程序,每隔 X 秒调用一次系统调用。您还可以在用户空间中进行所有昂贵的处理。
您还可以创建一个新设备,并显示
/dev/print-on-screen
:dev_open
将分配内存,而print()
则不会不再是无操作,而是在设备预分配的内存中提供数据(以防在原子上下文中使用print()
等)。dev_release
会抛出所有内容dev_read
会得到字符串dev_write
可以在屏幕打印系统上执行某些操作I don't really know if you meant
print
orprintk
. But if you're talking aboutprintk()
, You would need to allocate memory and you are in trouble becauseprintk()
may be called in an atomic context. Which leaves you the option to use a circular buffer (and thus, you should be tolerent to drop some strings because you might not have enough memory to save all the strings).In that case, I would not even do a kernel thread: I would do the processing in
print()
if not too costly.Otherwise, I would create a new system call:
sys_get_strings()
or something, that would dump the whole linked list into userspace (and remove entries from the list when copied).This way the whole behavior is controlled by userspace. You could create a deamon that would call the syscall every X seconds. You could also do all the costly processing in userspace.
You could also create a new device says
/dev/print-on-screen
:dev_open
would allocate the memory, andprint()
would no longer be a no-op, but feed the data in the device pre-allocated memory (in caseprint()
would be used in atomic context and all).dev_release
would throw everything outdev_read
would get you the stringsdev_write
could do something on your print-on-screen system