C语言 如何在 rmmod 上停止 Linux 内核线程?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5280693/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 08:01:42  来源:igfitidea点击:

How to stop Linux kernel threads on rmmod?

cmoduleoperating-systemkernelkernel-module

提问by pradeepchhetri

I wrote the following code to create a kernel thread:

我编写了以下代码来创建内核线程:

#include<linux/init.h>
#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/kthread.h>
#include<linux/sched.h>

struct task_struct *task;
int data;
int ret;
int thread_function(void *data)
{
    int var;
    var = 10;
    return var;
}

static int kernel_init(void)
{
    data = 20;
    printk(KERN_INFO"--------------------------------------------");
    task = kthread_create(&thread_function,(void *)data,"pradeep");
    task = kthread_run(&thread_function,(void *)data,"pradeep");
    printk(KERN_INFO"Kernel Thread : %s\n",task->comm);
    return 0;
}

static void kernel_exit(void)
{
    ret = kthread_stop(task);
}

module_init(kernel_init);
module_exit(kernel_exit);

On giving the insmod command, I am able to create a kernel thread named "pradeep" and I can see the new thread using the ps -efcommand as follows

在给出 insmod 命令时,我能够创建一个名为“pradeep”的内核线程,我可以使用ps -ef如下命令查看新线程

root      6071     2  0 10:21 ?        00:00:00 [pradeep]

and its parent is kthreadd whose PID is 2. But I am not able to stop this thread on giving rmmodcommand. It is giving the following output:

它的父级是 kthreadd,其 PID 为 2。但我无法在发出rmmod命令时停止该线程。它提供以下输出:

ERROR: Removing 'pradeep': Device or resource busy.

Can somebody please tell me how to kill this thread?

有人可以告诉我如何杀死这个线程吗?

回答by sarnold

You should use only one of kthread_create()or kthread_run():

您应该只使用kthread_create()或 之一kthread_run()

/**
 * kthread_run - create and wake a thread.
 * @threadfn: the function to run until signal_pending(current).
 * @data: data ptr for @threadfn.
 * @namefmt: printf-style name for the thread.
 *
 * Description: Convenient wrapper for kthread_create() followed by
 * wake_up_process().  Returns the kthread or ERR_PTR(-ENOMEM).
 */
#define kthread_run(threadfn, data, namefmt, ...)                      \
({                                                                     \
    struct task_struct *__k                                            \
            = kthread_create(threadfn, data, namefmt, ## __VA_ARGS__); \
    if (!IS_ERR(__k))                                                  \
            wake_up_process(__k);                                      \
    __k;                                                               \
})

So you're creating twothreads and leaking one of them:

因此,您正在创建两个线程并泄漏其中一个:

task = kthread_create(&thread_function,(void*) &data,"pradeep");
task = kthread_run(&thread_function,(void*) &data,"pradeep");

Furthermore, your thread function might be missing some details:

此外,您的线程函数可能缺少一些细节:

/**
 * kthread_create - create a kthread.
 * @threadfn: the function to run until signal_pending(current).
 * @data: data ptr for @threadfn.
 * @namefmt: printf-style name for the thread.
 *
 * Description: This helper function creates and names a kernel
 * thread.  The thread will be stopped: use wake_up_process() to start
 * it.  See also kthread_run().
 *
 * When woken, the thread will run @threadfn() with @data as its
 * argument. @threadfn() can either call do_exit() directly if it is a
 * standalone thread for which noone will call kthread_stop(), or
 * return when 'kthread_should_stop()' is true (which means
 * kthread_stop() has been called).  The return value should be zero
 * or a negative error number; it will be passed to kthread_stop().
 *
 * Returns a task_struct or ERR_PTR(-ENOMEM).
 */

I think the two choices for terminating a thread are:

我认为终止线程的两种选择是:

  1. Call do_exit()when you're done.
  2. Return a value when another thread calls kthread_stop().
  1. 完成后打电话do_exit()
  2. 当另一个线程调用时返回一个值kthread_stop()

Hopefully after fixing these two small problems, you'll have a functional thread creator / reaper.

希望在解决这两个小问题后,您将拥有一个功能性线程创建者/收割者。

回答by MSharq

I hope the below program resolves your problem.... thumbs up :-)

我希望下面的程序可以解决您的问题....竖起大拇指:-)

`#include<linux/init.h>
 #include<linux/module.h>
 #include<linux/kernel.h>
 #include<linux/kthread.h>
 #include<linux/sched.h>`

struct task_struct *task;
int data;
int ret;
int thread_function(void *data)
{
  int var;
 var = 10;
     printk(KERN_INFO "IN THREAD FUNCTION");
     while(!kthread_should_stop()){
             schedule();
             }
     /*do_exit(1);*/
  return var;

}

static int kernel_init(void)
{
   data = 20;
   printk(KERN_INFO"--------------------------------------------");
   /*task = kthread_create(&thread_function,(void *)data,"pradeep");*/
   task = kthread_run(&thread_function,(void *)data,"pradeep");
   printk(KERN_INFO"Kernel Thread : %s\n",task->comm);
   return 0;
}

static void kernel_exit(void)
{
   kthread_stop(task);
}

module_init(kernel_init);
module_exit(kernel_exit);
MODULE_AUTHOR("SHRQ");
MODULE_LICENSE("GPL");

回答by Goresh

in the code u need not use kthread_createapi as kthread_rundoes it internally.. Use either

在代码中,你不需要kthread_createkthread_run内部那样使用api .. 使用

task = kthread_create(&thread_function,(void *)data,"pradeep");
OR
task = kthread_run(&thread_function,(void *)data,"pradeep");

task = kthread_create(&thread_function,(void *)data,"pradeep");
OR
task = kthread_run(&thread_function,(void *)data,"pradeep");

Also your module is not under GPL license. That could be one cause of your issues.

此外,您的模块不受 GPL 许可。这可能是导致您出现问题的原因之一。