如何在Linux内核中加入一个线程?

时间:2015-04-30 04:40:50

标签: linux multithreading linux-kernel

主要问题是:我们如何等待Linux内核中的线程完成?我看过一些关于在Linux内核中处理线程的正确方法的帖子,但是我不确定如何等待主线程中的单个线程完成(假设我们需要线程[3]完成然后继续):

#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");
}

2 个答案:

答案 0 :(得分:4)

AFAIK内核中没有pthread_join()的等价物。此外,我觉得你的模式(启动一堆线程并只等待其中一个)在内核中并不常见。话虽如此,内核确实没有可用于实现目标的同步机制。

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

信号灯

您可以创建锁定的信号量,然后在主线程中调用down。这会让它入睡。然后在退出之前,你将up这个信号量在你的线程内部。类似的东西:

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()
}

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

达成

您可以使用以下方式声明完成次数:

struct completion comp;
init_completion(&comp);

或:

DECLARE_COMPLETION(comp);

然后,您可以使用wait_for_completion(&comp);代替down()在主线程中等待complete(&comp);代替up()

以下是完整的示例:

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的字段,然后调用{{1} }或up仅当此id等于3.这在完成示例中显示。还有其他方法可以做到这一点,这只是其中之一。

谨慎提及

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

答案 1 :(得分:3)

kthread_stop()是等待线程结束的内核方式。

除等待之外, kthread_stop()还为等待的线程设置 should_stop 标志,并在需要时将其唤醒。它对于无限重复某些动作的线程非常有用。

对于单次拍摄任务,使用它们的工作通常更简单,而不是kthreads。

修改: 注意:只有在未释放kthread(task_struct)结构时才能调用 kthread_stop()

线程函数只有在找到 kthread_should_stop ()后才返回true,或者在启动线程之前调用 get_task_struct ()(并且应该调用put_task_struct()在 kthread_stop()之后。