Продолжайте создавать несколько дочерних процессов от одного и того же родителя

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

Как мне создать отдельный процесс для каждого файла? Должен ли я выполнять весь процесс разветвления в пределах while(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 
vab@Vaibhav:~/CS330$ Entering child 
whatever3.bin  -34871
Exiting child 
Entering child 
whatever3.bin  -34871
Exiting child 
Entering child 
whatever3.bin  -34871
Exiting child

person Vab    schedule 11.10.2015    source источник
comment
Ваш код печатает Exiting child, но не выходит из дочернего элемента.   -  person melpomene    schedule 12.10.2015
comment
Как я узнаю, когда ребенок выходит? Разве это не конец контрольной суммы?   -  person Vab    schedule 12.10.2015
comment
Если он не уничтожен сигналом, процесс завершается, когда он достигает конца main или когда он вызывает exit().   -  person melpomene    schedule 12.10.2015
comment
Итак, я должен добавить выход (), когда я закончу вычисление контрольной суммы? Но как мне убедиться, что я использую отдельный процесс для вычисления контрольной суммы для каждого файла в каталоге?   -  person Vab    schedule 12.10.2015
comment
всегда проверяйте (!=NULL) значение, возвращаемое функцией malloc(), чтобы убедиться, что операция прошла успешно. всегда проверяйте (›=0) возвращаемое значение из open(), чтобы убедиться, что операция прошла успешно.   -  person user3629249    schedule 12.10.2015
comment
каждый дочерний элемент должен close() ввести входной файл и передать распределенную память в free() и вызвать exit(0);   -  person user3629249    schedule 12.10.2015
comment
контрольная сумма обычно не является значением со знаком. поэтому он должен быть объявлен как unsigned int checksum; и должен быть напечатан как %8X. почему перед спецификатором формата в операторе printf() стоит «-»?   -  person user3629249    schedule 12.10.2015
comment
@user3629249 user3629249 В моем коде есть все эти меры по проверке ошибок. Я просто не ставил их в вопросе, потому что думал, что это не имеет отношения к вопросу. Хотя спасибо за бдительность.   -  person Vab    schedule 12.10.2015
comment
@user3629249 user3629249 Я хочу, чтобы форматирование было таким: имя файла -размер файла Моя контрольная сумма в полном порядке, и я использовал для нее все правильные объявления. Меня беспокоит только многопроцессорность.   -  person Vab    schedule 12.10.2015
comment
Я пытаюсь вычислить контрольную сумму каждого двоичного файла Учитывая имя переменной 'checksum' (которое подразумевает конкретное значение, которое не является размером файла. (размер файла легко получить с помощью stat() функция) В размещенном коде не указано, как вычисляется поле «контрольная сумма», поэтому я использовал подразумеваемое значение слова в своих комментариях   -  person user3629249    schedule 13.10.2015


Ответы (2)


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

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

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

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

person dbush    schedule 11.10.2015
comment
Код, кажется, работает безупречно. Хотя у меня нет возможности проверить, задействованы ли разные процессы или это один большой процесс. Но большое спасибо за вашу помощь. - person Vab; 12.10.2015
comment
@Vab Вы можете убедиться, что используются разные процессы, напечатав значение getpid() в дочернем разделе кода. Кроме того, не стесняйтесь принять этот ответ, если он показался вам полезным. - person dbush; 12.10.2015

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

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

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

// 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);
}

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

person maddouri    schedule 11.10.2015
comment
Я еще не изучил, как работает многопоточность и чем она отличается от многопроцессорной обработки. Но как только я это узнаю, я обязательно вернусь к вашему ответу. - person Vab; 12.10.2015
comment
Вот интересная статья на эту тему: geekride.com/fork -forking-vs-threading-thread-linux-kernel - person maddouri; 12.10.2015