如何等待线程完成他们的工作,在c中克隆创建的线程?

我试着等待主要function,直到线程完成他们的工作。 但主要function完成其工作并退出。 我认为因为线程在变量中没有正确的指针/值。(理货和步骤)

在这种情况下,有人知道如何正确使用waitpid / wait吗?

我的代码:

#define _GNU_SOURCE #include  #include  /* for PRIu64 and uint64_t */ /* you'll need further includes */ #include  #include  #include "tally.h" #include  #include  #include  #define STACK_SIZE 32768 #define THREADS 2 struct clone_args{ uint64_t steps; uint64_t* tally; }; int incHelper(void* arg){ struct clone_args *args = (struct clone_args*)arg; uint64_t steps= args->steps; uint64_t* tally = args->tally; increment(tally,steps); (void) arg; (void) tally; (void) steps; exit(2); return 0; } int main () { uint64_t N = 10000000; uint64_t tally = 1; tally_init(); int thread_pid[THREADS]; int status; for(int i= 0; isteps = N; arguments->tally = &tally; void* arg = (void*) &arguments; thread_pid[i] = clone(incHelper, child_stack+STACK_SIZE,CLONE_VM, arg); pid_t pid = waitpid(thread_pid[i],&status,SIGCHLD); printf("C-PID [%d]\n", thread_pid[i]); (void) pid; } tally_clean(); printf( "\nTally is %" PRIu64 "\n", tally ); (void) N; (void) thread_pid; (void) tally; (void) status; printf("\n MAIN PROGRAMM END\n"); return 0; } 

增量函数:

 /* modify this function to achieve correct parallel incrementation */ void increment ( uint64_t *tally, uint64_t steps ) { printf("\nTALLY: %"PRIu64"\n",*tally); printf("STEPS: %"PRIu64"\n",steps); for( uint64_t i = 0; i < steps; i++ ) { *tally += 1; } return; } 

运行代码后得到的结果:

 C-PID [29819] C-PID [29820] Tally is 1 MAIN PROGRAMM END root@...(~/Downloads/asst3/asst3-clone)$ TALLY: 0 STEPS: 140714329004032 TALLY: 888309 STEPS: 140714329004032 

代码应该用两个线程递增一个变量。 为了避免临界问题,我应该使用信号量。 但这是另一项运动。 首先练习它使用clone()函数创建两个线程。 我不明白,如果clone()的标志错误或我的代码完全错误。 我是编程语言C的新手。

我用谷歌搜索了最近12个小时。

我感谢你的每一个答案:)。

抱歉英文不好。

问候

默认情况下, clone() ed进程不会向父进程发送有关其结束的信号。

如果您希望向父节点发送关于子节点的信号,则当clone()对传递的第3个参数进行OR运算时,您需要明确地传递要在其末尾发送的信号。

如果您使用SIGCHLD则照常使用waitpid()

在后一种情况下克隆并等待如下:

  thread_pid[i] = clone(incHelper, child_stack+STACK_SIZE, CLONE_VM | SIGCHLD, arg); pid_t pid = waitpid(thread_pid[i], &status, 0); 

如果你想在孩子的末端使用另一个信号,例如SIGUSR1你需要使用选项__WCLONE告诉它waitpid()

  thread_pid[i] = clone(incHelper, child_stack+STACK_SIZE, CLONE_VM | SIGUSR1, arg); pid_t pid = waitpid(thread_pid[i], &status, __WCLONE); 

这个

 void* arg = (void*) &arguments; 

获取arguments的地址。 由于arguments已经是所需结构的地址,因此它应该是:

 void * arg = arguments; 

注意:作为clone() ed线程的主线程waitpid() ,在下次调用clone()之前完成, 没有并行处理increment()