2013-12-15 17 views
0

我尝试等待主要功能,直到线程完成其工作。但主要功能完成其工作并退出。我想这是因为线程在变量中没有正确的指针/值。(计数和步骤)如何等待线程完成他们的工作,由c中的克隆创建线程?

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

我的代码:

#define _GNU_SOURCE 
#include <stdio.h> 
#include <inttypes.h> /* for PRIu64 and uint64_t */ 
/* you'll need further includes */ 
#include <sched.h> 
#include <stdlib.h> 
#include "tally.h" 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/wait.h> 

#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; i<THREADS;i++){ 
       void *child_stack = malloc(STACK_SIZE); 
       struct clone_args *arguments = malloc(sizeof(struct clone_args)); 
       arguments->steps = 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 
[email protected](~/Downloads/asst3/asst3-clone)$ 
TALLY: 0 
STEPS: 140714329004032 

TALLY: 888309 
STEPS: 140714329004032 

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

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

谢谢你的回答:)。

对不起,英语不好。

问候

+0

可能的重复:http://stackoverflow.com/q/20442072/694576 – alk

回答

2

每一个默认编clone()过程中不发送关于其端部的父。

如果你想让父母知道孩子的结局,那么当clone()或ORed传递给第三个参数时,你需要明确地传递要发送的信号。

如果您使用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; 

注:由于主线程waitpid() S为clone() ED线程clone()下一个电话之前完成,有没有并行处理increment()

+0

嗨,因为我使用你的代码,我有一个无效的内存访问错误。 – Kami

+0

哪条线路崩溃? – alk

+0

对不起,我把它翻译错了。英文中称为分段错误错误。我插入SIGCHILD并将第三个参数设置为零,waitpid后发生错误。 – Kami