删除等待信号量的kthread的正确方法

问题描述 投票:0回答:1

我编写了一个使用内核线程和信号量的内核模块。

我从中断处理程序中为信号量调用up(...)函数,然后我的kthread开始执行。

static int interrupt_handler_thread(void *data)
{
    /* duty cycle */
    while (!kthread_should_stop()) {
        /*
         * If semaphore has been uped in the interrupt, we will
         * acquire it here, else thread will go to sleep.
         */
        if (!down_interruptible(mysem)) {
            /* proccess  gpio interrupt */
            dev_info(dev, "gpio interrupt detected\n"); 
        }
    }

    do_exit(0);

    return 0;
}

信号量和线程被初始化为module_init函数。错误检查被省略。

...
sema_init(mysem, 0);

thread = kthread_create(interrupt_handler_thread,client,"my_int_handler");
wake_up_process(thread);
...

并且在卸载模块期间,信号量和线程被删除:

    /*
     * After this call kthread_should_stop() in the thread will return TRUE.
     * See https://lwn.net/Articles/118935/
     */
    kthread_stop(thread);

    /*
     * Release the semaphore to return
     * from down_interruptible() function
     */
    up(mysem);

[当我尝试卸载模块时,会在down_interruptible()函数中将一个代码插入线程,因为它等待信号量在中断处理程序中上升。而且我的代码永远不会从kthread_stop()返回。

[似乎,我需要从gpio禁用中断,用手提高信号量并调用kthread_stop()函数。但这是一个潜在的错误,因为在手动调高信号量之后,线程开始执行,并且该线程可以在其占空比之后再次down_interruptible()

有人可以帮我吗?

PS:我知道this question,但似乎这不是我的情况。

linux-kernel semaphore kernel-module
1个回答
0
投票

为了正确操作,您的kthread在等待信号量时应检查线程的“停止”状态。不幸的是,没有down功能的“可停止”版本。

而不是kthread使用workqueue机制。 Works已经具备您需要的所有功能:

  • 您可以在中断处理程序(queue_work)中添加工作,
  • 只能同时运行一项工作,
  • 使用destroy_workqueue,您可以安全地完成所有作品。

实际上,工作队列是使用kthreads实现的。参见例如kthread_worker_fn功能的实现。

© www.soinside.com 2019 - 2024. All rights reserved.