Форкинг и управление процессами - PullRequest
1 голос
/ 16 декабря 2010

Информация о системе: я использую 64-битную Ubuntu 10.10 на 2-месячном ноутбуке.

Привет всем, у меня есть вопрос о функции fork () в C. Из ресурсов, которые я использую(Stevens / Rago, YoLinux и Opengroup), насколько я понимаю, когда вы разветвляете процесс, родительский и дочерний процесс продолжают выполнение следующей команды.Поскольку fork () возвращает 0 дочернему элементу, а идентификатор процесса дочернего элемента родительскому элементу, вы можете изменить их поведение с помощью двух операторов if, одного if (pid = 0) для дочернего элемента и if (pid> 0), предполагая, чтовы разветвились с помощью pid = fork ().

Теперь у меня самое странное событие.В начале своей основной функции я печатаю в stdout пару аргументов командной строки, которые были назначены переменным.Это первый оператор без присваивания во всей программе, но иногда кажется, что когда я вызываю fork позже в программе, выполняется этот оператор печати. ​​

Цель моей программы - создать "«дерево процессов», где каждый процесс имеет двух дочерних элементов, вплоть до глубины 3, таким образом, создавая всего 14 дочерних элементов исходного исполняемого файла.Каждый процесс печатает идентификатор процесса своего родителя и идентификатор процесса до и после разветвления.

Мой код выглядит следующим образом и правильно прокомментирован, аргументы командной строки должны быть "ofile 3 2 -p" (у меня нетдошел до реализации флагов -p / -c ":

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>


int main (int argc, char *argv[])
{
    if(argc != 5)//checks for correct amount of arguments
    {
        return 0;
    }

    FILE * ofile;//file to write to
    pid_t pid = 1;//holds child process id
    int depth = atoi(argv[2]);//depth of the process tree
    int arity = atoi(argv[3]);//number of children each process should have

    printf("%d%d", depth, arity);

    ofile = fopen(argv[1], "w+");//opens specified file for writing



    int a = 0;//counter for arity
    int d = 0;//counter for depth
    while(a < arity && d < depth)//makes sure depth and arity are within limits, if the children reach too high(low?) of a depth, loop fails to execute
                                  //and if the process has forked arity times, then the loop fails to execute
    {
        fprintf(ofile, "before fork: parent's pid: %d, current pid: %d\n", getppid(), getpid());//prints parent and self id to buffer
        pid = fork(); //forks program
        if(pid == 0)//executes for child
        {
            fprintf(ofile, "after fork (child):parent's pid: %d, current pid: %d\n", getppid(), getpid());//prints parent's id and self id to buffer
                    a=-1;//resets arity to 0 (after current iteration of loop is finished), so new process makes correct number of children
            d++;//increases depth counter for child and all of its children
        }
        if(pid > 0)//executes for parent process
        {
        waitpid(pid, NULL, 0);//waits on child to execute to print status
        fprintf(ofile, "after fork (parent):parent's pid: %d, current pid: %d\n", getppid(), getpid());//prints parent's id and self id to buffer
        }
        a++;//increments arity counter
    }


    fclose(ofile);
}

Когда я запускаю" gcc main.c -o ptree ", затем" ptree ofile 3 2 -p ", консоль спамится" 32"несколько раз, и файл" ofile "имеет, казалось бы, правильный формат, но он слишком велик для того, что, по моему мнению, должна делать моя программа, показывая 34 дочерних процесса, когда должно быть 2 ^ 3 + 2 ^ 2 + 2^ 1 = 14. Я думаю, что это как-то связано с утверждением, которое печатает «32», поскольку это, возможно, породило бы больше вилок, чем предполагалось.

Любая помощь будет принята с благодарностью.

1 Ответ

6 голосов
/ 16 декабря 2010

Когда вы вызываете printf, данные хранятся в буфере внутри.Когда вы разветвляетесь, этот буфер наследуется дочерним элементом.В какой-то момент (когда вы снова вызываете printf или когда вы закрываете файл), буфер очищается, и данные записываются в базовый дескриптор файла.Чтобы предотвратить наследование данных в буфере дочерним объектом, вы можете очистить FILE * перед вызовом fork, используя fflush.

...