2015-10-11 3 views
0

Я пытаюсь вычислить контрольную сумму каждого двоичного файла в текущем каталоге, используя отдельный процесс для повышения производительности. Однако по какой-то причине мой вывод всегда неожиданен.Продолжайте создавать несколько дочерних процессов от одного и того же родителя

Как мне создать отдельный процесс для каждого файла? Должен ли я иметь весь процесс разветвления в пределах , пока (pids [i]! = -1)?

file_cnt = number of .bin files in the current dir 

pid_t pids[file_cnt]; 

for(i = 0; i < file_cnt; i++) 
{ 
    if((pids[i]=fork()) < 0) 
    { 
     printf("Error forking"); 
     return 0; 
    } 
    else if(pids[i]==0) 
    { 
     printf("Entering child \n"); 
     printf("%s ", filenames[i]); 

     //reading file 
     handle = open(filenames[i], O_RDONLY); 

     //allocating memory 
     buffer = malloc(BUFFER_SIZE); 

     checksum = 0; 

     do 
     { 
      //calculating checksum 
     } while(length); 

     printf(" -%d\n", checksum); 
     printf("Exiting child \n"); 
    } 
} 

У меня есть три файла в каталоге и мой выход выходит как:

There are 3 files: 
Entering child 
whateve2.bin -10540 
Exiting child 
Entering child 
Entering child 
whatever.bin -8399 
Exiting child 
whatever3.bin -34871 
Exiting child 
Entering child 
whatever.bin -8399 
Exiting child 
[email protected]:~/CS330$ Entering child 
whatever3.bin -34871 
Exiting child 
Entering child 
whatever3.bin -34871 
Exiting child 
Entering child 
whatever3.bin -34871 
Exiting child 
+3

Ваш код печатает 'Exiting child', но он не выходит из дочернего элемента. – melpomene

+0

Как я узнаю, когда ребенок выйдет? Разве это не в конце контрольной суммы? – Vab

+1

Если он не был убит сигналом, процесс завершается, когда он достигает конца 'main' или когда он вызывает' exit() '. – melpomene

ответ

2

Вы не вызывающий exit() в конце else блока для каждого ребенка. Из-за этого ребенок снова вернется в цикл for и выполнит следующую итерацию, снова вызовет fork(). Если есть 3 файла, родитель будет вилка 3 раза, ребенок для файла 1 будет вилка 2 раза, а ребенок для файла 2 будет вилка 1 раз.

Сразу после звонка на номер printf("Exiting child \n"); вам необходимо позвонить exit(0), чтобы завершить процесс.

Обращаясь к вашему комментарию, тот факт, что вы вызвали fork() и проверили, что возвращаемое значение не равно < 0 гарантирует, что был создан дочерний процесс, и проверка того, что возвращаемое значение равно 0, гарантирует, что это выполняемый дочерний процесс.

Помните, что fork() возвращается в два раза, если это удастся: однажды к родителю с ИДП ребенка, и один раз к ребенку с 0.

+0

Код работает безупречно. Хотя, у меня нет возможности проверить, нет или нет различные процессы вовлечены или это один большой процесс, но большое вам спасибо за вашу помощь. – Vab

+0

@Vab Вы можете проверить, используются ли разные процессы, напечатав значение 'getpid()' в дочернем разделе кода. , не стесняйтесь [принять этот ответ] (http://stackoverflow.com/help/accepted-answer), если вы сочтете это полезным. – dbush

1

Как уже отмечалось другими, вы не exit() ING в конце блока else.

Однако я хотел бы предложить улучшение: поскольку вы пытаетесь реализовать параллельную обработку, чтобы получить производительность на быстрой задаче, как об использовании потоков вместо fork() всех процессов?

Вот пример кода, который показывает, что вы можете сделать:

// adapted from https://computing.llnl.gov/tutorials/pthreads/ 
// compile with: gcc calc_checksum.c -o calc_checksum -lpthread 

#include <pthread.h> 
#include <stdio.h> 

void* calc_checksum(void* pFileNameIdx) 
{ 
    const int fileNameIdx = (int)pFileNameIdx; 
    printf("Entering child \n"); 
    // filenames should be a global variable somewhere 
    // or, better, just pass "&filenames[fileNameIdx]" instead of pFileNameIdx 
    printf("%s ", filenames[fileNameIdx]); 

    // reading file 
    handle = open(filenames[fileNameIdx], O_RDONLY); 

    // allocating memory 
    buffer = malloc(BUFFER_SIZE); 

    int checksum = 0; 

    do 
    { 
     // calculating checksum 
    } while(length); 

    printf(" -%d\n", checksum); 
    printf("Exiting child \n"); 

    free(buffer); // !! don't forget to free() the resources that you don't need anymore 

    // exit the thread 
    pthread_exit(NULL); 
} 

int main (int argc, char *argv[]) 
{ 
    // initialization code ... 
    file_cnt = number of .bin files in the current dir 

    pthread_t threads[file_cnt]; 
    int retCode; 

    for(i = 0; i < file_cnt; i++) 
    { 
     retCode = pthread_create(&threads[i], NULL, calc_checksum, (void*)i); 
     if (retCode){ 
      printf("ERROR; return code from pthread_create() is %d\n", retCode); 
      exit(-1); 
     } 
    } 

    pthread_exit(NULL); 
} 

NB: независимо от метода (fork() или PThreads): не забудьте free() память, что вы защищены с malloc().

+0

Я еще не научился тому, как работает потоки и как он отличается от многопроцессорного процесса ING. Но как только я узнаю об этом, я обязательно вернусь к вашему ответу. – Vab

+1

Вот интересная статья по теме: http://www.geekride.com/fork-forking-vs-threading-thread-linux-kernel/ – 865719