主要问题是:我们如何等待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");
}
答案 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 = ∁
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()之后。