如何在Linux内核中加入线程? [英] How to join a thread in Linux kernel?

查看:327
本文介绍了如何在Linux内核中加入线程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

主要问题是:如何等待Linux内核中的线程完成?我已经看到了一些有关在Linux内核中处理线程的正确方法的文章,但是我不确定如何等待主线程中的单个线程完成(假设我们需要先完成thread [3]然后继续进行) ):

The main question is: How we can wait for a thread in Linux kernel to complete? I have seen a few post concerned about proper way of handling threads in Linux kernel but i'm not sure how we can wait for a single thread in the main thread to be completed (suppose we need the thread[3] be done then proceed):

#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kthread.h>
#include <linux/slab.h>

void *func(void *arg) {
    // doing something
    return NULL;
}

int init_module(void) {
    struct task_struct* thread[5];
    int i;
    for(i=0; i<5; i++) {
        thread[i] = kthread_run(func, (void*) arg, "Creating thread");
    }
    return 0;
}

void cleanup_module(void) {
    printk("cleaning up!\n");
}

推荐答案

AFAIK内核中没有pthread_join()的等效项.另外,我觉得您的模式(启动一堆线程并仅等待其中一个线程)在内核中并不常见.话虽这么说,那里的内核确实很少有同步机制可以用来实现您的目标.

AFAIK there is no equivalent of pthread_join() in kernel. Also, I feel like your pattern (of starting bunch of threads and waiting only for one of them) is not really common in kernel. That being said, there kernel does have few synchronization mechanism that may be used to accomplish your goal.

请注意,这些机制不能保证线程完成,它们只会让主线程知道它们已经完成了应做的工作.真正停止这一步并释放所有资源可能仍需要一些时间.

Note that those mechanisms will not guarantee that the thread finished, they will only let main thread know that they finished doing the work they were supposed to do. It may still take some time to really stop this tread and free all resources.

您可以创建一个锁定的信号灯,然后在主线程中调用down.这将使其进入睡眠状态.然后,在退出之前,您将在线程内部up此信号量.像这样:

You can create a locked semaphore, then call down in your main thread. This will put it to sleep. Then you will up this semaphore inside of your thread just before exiting. Something like:

struct semaphore sem;

int func(void *arg) {
    struct semaphore *sem = (struct semaphore*)arg; // you could use global instead

    // do something

    up(sem);
    return 0;
}

int init_module(void) {
    // some initialization
    init_MUTEX_LOCKED(&sem);
    kthread_run(&func, (void*) &sem, "Creating thread");
    down(&sem); // this will block until thread runs up()
}

这应该有效,但不是最佳解决方案.我提到这一点是因为它是一种在用户空间中也使用的已知模式.内核中的信号量是为大多数情况下使用的,并且这种情况下的争用较高而设计的.因此,创建了针对这种情况优化的类似机制.

This should work but is not the most optimal solution. I mention this as it's a known pattern that is also used in userspace. Semaphores in kernel are designed for cases where it's mostly available and this case has high contention. So a similar mechanism optimized for this case was created.

您可以使用以下方法声明完成:

You can declare completions using:

struct completion comp;
init_completion(&comp);

或:

DECLARE_COMPLETION(comp);

然后,您可以在主线程中使用wait_for_completion(&comp);而不是down()来等待,而在您的线程中可以使用complete(&comp);而不是up()来等待.

Then you can use wait_for_completion(&comp); instead of down() to wait in main thread and complete(&comp); instead of up() in your thread.

这是完整的示例:

DECLARE_COMPLETION(comp);
struct my_data {
    int id;
    struct completion *comp;
};

int func(void *arg) {
    struct my_data *data = (struct my_data*)arg;
    // doing something

    if (data->id == 3)
        complete(data->comp);

    return 0;
}

int init_module(void) {
    struct my_data *data[] = kmalloc(sizeof(struct my_data)*N, GFP_KERNEL);

    // some initialization
    for (int i=0; i<N; i++) {
        data[i]->comp = &comp;
        data[i]->id = i;
        kthread_run(func, (void*) data[i], "my_thread%d", i);
    }
    wait_for_completion(&comp); // this will block until some thread runs complete()
}

多线程

我真的不明白为什么您要启动5个相同的线程而只想等待第3个线程,但是您当然可以向每个线程发送不同的数据,并用一个字段描述它的ID,然后调用upcomplete仅在此id等于3的情况下.这在完成示例中显示.还有其他方法可以做到这一点,这只是其中之一.

Multiple threads

I don't really see why you would start 5 identical threads and only want to wait for 3rd one but of course you could send different data to each thread, with a field describing it's id, and then call up or complete only if this id equals 3. That's shown in the completion example. There are other ways to do this, this is just one of them.

在使用任何一种机制之前,请先阅读有关这些机制的更多信息.我这里没有写一些重要的细节.这些示例也经过了简化而不经过测试,它们只是为了展示整体思想.

Go read some more about those mechanisms before using any of them. There are some important details I did not write about here. Also those examples are simplified and not tested, they are here just to show the overall idea.

这篇关于如何在Linux内核中加入线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆