2013-12-15 4 views
0

Я стараюсь дождаться основной функции, пока нитки не закончат свою работу. Но основная функция завершает работу и выходит. Я думаю, из-за этого потоки не имеют правильных указателей/значений в переменных. (Tally and steps)Как ждать, пока потоки закончат работу, где потоки, созданные клоном в c?

Кто-нибудь знает, как использовать waitpid/подождать должным образом в этом случае?

мой код:

#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 

Код должен приращение переменной с двумя потоками , Чтобы избежать критической проблемы, я должен использовать семафоры. Но это другое упражнение. Сначала используйте его для использования функции clone() для создания двух потоков. Я не понимаю, если флаги clone() ошибочны или мой код полностью ошибочен. Я новичок в языке программирования C.

Я провел последние 12 часов поиска с помощью Google.

Благодарю за каждый ответ :).

Извините за плохой английский.

С уважением

+0

Возможный дубликат: http://stackoverflow.com/q/20442072/694576 – alk

ответ

2

По-умолчанию процесс clone() редактор не сигнализирует родителя о его конце.

Если вы хотите, чтобы родительский сигнал был сигнализирован о конце ребенка, вам необходимо четко передать сигнал, который должен быть отправлен на его конец, когда clone() ing 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 вам нужно сообщить об этом waitpid() с помощью опции __WCLONE :

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() эдов нити, чтобы закончить до следующего вызова clone(), есть нет параллельная обработка increment()

+0

Привет, как я использовал ваш код, у меня ошибка Ошибка доступа к памяти. – Kami

+0

Какая линия падает? – alk

+0

Извините, я перевел это неправильно. На английском языке ошибка, вызванная ошибкой ошибки сегментации. Ошибка возникает после того, как я вставил SIGCHILD и установил третий аргумент в ноль, waitpid. – Kami