我正在编写一个使用定制的屏幕打印系统的内核模块。基本上每次涉及print
时,字符串都会插入到链接列表中。
每隔X秒,我需要处理列表并在打印它们之前对字符串执行一些操作。
基本上我有两种选择来实现这样的过滤器:
1)定时器(最后重启)
2)内核线程,它休眠X秒
虽然过滤器正在执行其中没有其他东西可以使用链接列表,当然,在插入字符串时,过滤器函数应该等待。
AFAIK计时器在中断上下文中运行,因此它无法休眠,但内核线程呢?他们可以睡觉吗?如果是,是否有一些理由不在我的项目中使用它们?可以使用哪种其他解决方案?
总结一下:我的过滤功能只有3个要求:
1)必须能够printk
2)当使用列表时,尝试访问列表的其他所有内容都必须阻塞,直到过滤器函数完成执行
3)必须每X秒运行一次(不是实时要求)
答案 0 :(得分:2)
允许kthreads睡觉。 (但是,并非所有kthread都为所有客户端提供了睡眠执行。例如,softirqd不会。) 但话说回来,你也可以使用自旋锁(及其相关的成本)并且没有额外的线程(这基本上是定时器所做的,使用spinlock_bh)。这真是一个权衡。
答案 1 :(得分:1)
每次涉及
我真的不知道你的意思是print
还是printk
。但是如果你在谈论printk()
,你需要分配内存并且你遇到麻烦,因为printk()
可能在原子上下文中被调用。这使您可以选择使用循环缓冲区(因此,您应该容忍丢弃一些字符串,因为您可能没有足够的内存来保存所有字符串)。
每隔X秒,我需要处理列表并在打印字符串之前对字符串执行一些操作。
在这种情况下,我甚至不会做内核线程:如果代价太高,我会在print()
进行处理。
否则,我会创建一个新的系统调用:
sys_get_strings()
或其他东西,它会将整个链表转储到用户空间中(并在复制时从列表中删除条目)。这样整个行为就由用户空间控制。你可以创建一个每X秒调用一次系统调用的守护进程。您还可以在用户空间中进行所有昂贵的处理。
您还可以创建一个新设备/dev/print-on-screen
:
dev_open
会分配内存,而print()
将不再是无操作,但会在设备预先分配的内存中提供数据(如果使用print()
在原子上下文和所有)。dev_release
会抛出一切dev_read
会为您提供字符串dev_write
可以在您的屏幕打印系统上执行某些操作