简体   繁体   English

在Linux内核中实现正确的模块间同步

[英]Implementing correct inter-module synchronization in Linux kernel

I'm implementing a custom serial bus driver for a certain ARM-based Linux board (a custom UART driver, actually). 我正在为某个基于ARM的Linux板(实际上是一个自定义UART驱动程序)实现自定义串行总线驱动程序。 This driver shall enable communication with a certain MCU on the other end of the bus via a custom protocol. 该驱动程序应通过自定义协议启用与总线另一端的某个MCU的通信。 The driver will not (and actually must not ) expose any of its functions to the userspace, nor it is possible to implement it in userspace at all (hence, the need for the custom driver instead of using the stock TTY subsystem). 驱动程序不会(实际上也不能 )将其任何功能暴露给用户空间,也不可能在用户空间中实现它(因此,需要自定义驱动程序而不是使用库存TTY子系统)。

The driver will implement the communication protocol and UART reads/writes, and it has to export a set of higher-level functions to its users to allow them to communicate with the MCU (eg read_register() , drive_gpios() , all this stuff). 驱动程序将实现通信协议和UART读/写,并且必须将一组更高级别的函数导出到其用户以允许它们与MCU通信(例如read_register()drive_gpios() ,所有这些东西) 。 There will be only one user of this module. 该模块只有一个用户。

The calling module will have to wait for the completion of the operations (the aforementioned read_register() and others). 调用模块必须等待操作的完成(前面提到的read_register()和其他)。 I'm currently considering using semaphores: the user module will call my driver's function, which will initiate the transfers and wait on a semaphore; 我正在考虑使用信号量:用户模块将调用我的驱动程序的函数,它将启动传输并等待信号量; the IRQ handler of my driver will send requests to the MCU and read the answers, and, when done, post to the semaphore, thus waking up the calling module. 我的驱动程序的IRQ处理程序将向MCU发送请求并读取答案,并在完成后发布到信号量,从而唤醒调用模块。 But I'm not really familiar with kernel programming, and I'm baffled by the multitude of possible alternative implementations (tasklets? wait queues?). 但我对内核编程并不熟悉,而且我对众多可能的替代实现(tasklets?等待队列?)感到困惑。

The question is: is my semaphore-based approach OK, or too naïve? 问题是:我的基于信号量的方法是好还是太天真了? What are the possible alternatives? 有哪些可能的选择? Are there any pitfalls I may be missing? 我可能会遗失任何陷阱吗?

Traditionally IRQ handling in Linux is done in two parts: 传统上Linux中的IRQ处理分为两部分:

  1. So called "upper-half" is actual working in IRQ context (IRQ handler itself). 所谓的“上半部分”实际上在IRQ上下文中工作(IRQ处理程序本身)。 This part must exit as fast as possible. 这部分必须尽快退出。 So it basically checks interrupt source and then starts bottom-half. 所以它基本上检查中断源,然后开始下半部分。

  2. "Bottom-half". “下半区”。 It may be implemented as work queue. 它可以实现为工作队列。 It is where actual job is done. 这是实际工作的地方。 It runs in normal context, so it can use blocking functions, etc. 它在正常的上下文中运行,因此它可以使用阻塞函数等。

If you only want to wait for IRQ in your worker thread, better to use special object called completion . 如果您只想在工作线程中等待IRQ,最好使用称为completion特殊对象。 It is exactly created for this task. 它完全是为此任务创建的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM