如何等待线程完成他们的工作,在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()