Печатать в порядке прекращения?

У меня есть программа, которая генерирует случайное число n, а затем зацикливается n раз.

На каждой итерации он рандомизирует значение sleeptime и вызывает fork. Дочерний процесс спит в течение sleeptime секунд, затем завершается со значением переменной индекса.

Затем родитель снова зацикливается, ожидая завершения каждого процесса. Когда каждый процесс завершается, я пытаюсь вывести pid и childid процесса, но здесь у меня возникают проблемы. PID печатаются по порядку, а childid остается равным 0.

Что я делаю неправильно?

int main(int argc, char* argv[])
{

    //  Wire up the timer
    long time = elapsedTime(0);

    /*  Generate a random number between MINFORKS and MAXFORKS
     */
    unsigned int seed = generateSeed(0);
    int n = rand_r(&seed) % MAXFORKS + MINFORKS-1;

    /*  Log next step
     */
    time = elapsedTime(1);
    printf("%li: Number of forks = %i\n", time, n);

    /*  Hang on to the PIDs so we can wait for them after forking
     */
    pid_t *PIDs = (pid_t *)(malloc(sizeof(*PIDs)*n));


    /*  Fork n times
     */
    for (int i = 0; i < n ; i++)
    {
        /*  Call fork() and retain the returned identifier
         */
        pid_t processIdentifier = fork();

        /* Randomize the child sleep time
         */
        seed = generateSeed(0);
        int sleeptime = rand_r(&seed)  % MAXPAUSE + MINPAUSE;

        /*  Check for errors
         */
        if (processIdentifier == -1) {
            printf("Error: %i", errno);
        }


        if (!processIdentifier)
        {
            /*  We're in the child process,
             *  sleep and then exit with
             *  i as the error code.
             */

            usleep(sleeptime);
            _exit(i);
        }
        else
        {
            /*  We're in the parent:
             *  Store the PID and
             *  print out the results.
             */

            PIDs[i] = processIdentifier;

            time = elapsedTime(1);
            printf("%li: Child %i, pid = %i, forked, waits %i usec\n", time,  i, processIdentifier, sleeptime);

        }
    }

    /* Log next step
     */
    time = elapsedTime(1);
    printf("%li: Finished forking, going to wait.\n", time);

    /*
     *  Loop through the processes and wait for them
     *  to terminate. Then print the childid, and the
     *  the pid.
     */

    for (int i = 0; i < n; i++)
    {

        /*  Get the PID we want to track
         */
        pid_t pid = PIDs[i];

        /*  Wait for the child process
         *  and grab it's status info
         */
        int status = NULL;


        waitpid(pid, &status, 0);

        int childid = -1;
        if(WIFEXITED(status))
        {
            childid = WTERMSIG(status);
        }

        /*  Log the results
         */
        time = elapsedTime(1);
        printf("%li: Child %i, pid = %i, terminated\n", time, childid, pid);
    }

    /*  All done!
     */
    time = elapsedTime(1);
    printf("All done. It only took %li milliseconds!", time);   
}

Отказ от ответственности, это домашнее задание (ссылка здесь, может исчезнуть в любой момент), но я уже сделал почти все Это. У меня просто проблемы с пониманием этого аспекта.


person Moshe    schedule 24.05.2013    source источник


Ответы (2)


Ваш код ожидает PID в том порядке, в котором вы их предоставляете в своих последовательных waitpid() вызовах. Если вместо этого вы передадите -1 в качестве первого параметра для waitpid() (или если вы просто вызовете wait()), вы получите первый дочерний элемент, о котором вам сообщит ядро, а не тот, о котором вы специально просили уведомлять. Проверьте возвращаемое значение, чтобы увидеть, какой это дочерний элемент (или если произошла ошибка).

childid остается 0, потому что вы извлекаете WTERMSIG из состояния ожидания, а не WEXITSTATUS.

person jxh    schedule 24.05.2013

for (int i = 0; i < n; i++)
{
    pid_t pid = PIDs[i];
    int status = NULL;
    waitpid(pid, &status, 0);

Поэтому сначала он ждет завершения первого процесса, а затем выводит информацию из этого процесса.
Затем он ждет завершения второго процесса, а затем выводит информацию из этого процесса.
Затем он ждет для завершения третьего процесса...

И вам интересно, почему они сообщаются по порядку?

вместо этого передайте -1 в waitpid, что, по словам этой страницы, приведет к ожиданию любой дочерний поток вместо определенного потока.

Кроме того, прямо перед печатью у вас есть int childid = -1;. Не уверен, почему.

person Mooing Duck    schedule 24.05.2013