Far*_*had 2 linux multithreading linux-kernel
主要问题是:如何等待Linux内核中的线程完成?我已经看到了一些有关在Linux内核中处理线程的正确方法的文章,但是我不确定如何等待主线程中的单个线程完成(假设我们需要先完成thread [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");
}
Run Code Online (Sandbox Code Playgroud)
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()
}
Run Code Online (Sandbox Code Playgroud)
这应该可行,但不是最佳解决方案。我之所以提及这一点,是因为它也是一种在用户空间中使用的已知模式。内核中的信号量是针对大多数情况下使用的,并且这种情况下的争用较高。因此,创建了针对这种情况优化的类似机制。
您可以使用以下方法声明完成:
struct completion comp;
init_completion(&comp);
Run Code Online (Sandbox Code Playgroud)
要么:
DECLARE_COMPLETION(comp);
Run Code Online (Sandbox Code Playgroud)
然后你可以使用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()
}
Run Code Online (Sandbox Code Playgroud)
我真的不明白为什么您要启动5个相同的线程而只想等待第3个线程,但是您当然可以向每个线程发送不同的数据,并用一个字段描述它的ID,然后调用,up或者complete仅当该ID等于3时才调用这在完成示例中显示。还有其他方法可以做到这一点,这只是其中之一。
在使用任何一种机制之前,请先阅读有关这些机制的更多信息。我这里没有写一些重要的细节。这些示例也经过了简化而不经过测试,它们只是为了展示整体思想。
kthread_stop()是内核等待线程结束的方法。
除了等待之外,kthread_stop()还为等待的线程设置should_stop标志,并在需要时唤醒它。它对于无限重复某些操作的线程很有用。
对于单次任务,使用 Works 通常比使用 kthreads 更简单。
编辑:注意:仅当 kthread(task_struct) 结构未释放时才能调用kthread_stop() 。
任一线程函数应仅在发现kthread_should_stop () 返回 true 后返回,或者应在启动线程之前调用get_task_struct () (并应在kthread_stop() 之后调用 put_task_struct())。