Подтвердить что ты не робот

Работа вилки на языке c

Теперь у меня возникла проблема в понимании работы системного вызова fork(). Я пишу следующий код:

#include<stdio.h>
int main()
{
    int a, b;
    b=fork();

    printf("\n the value of b = %d",b);
}

Результат этого кода следующий:

Теперь я не понимаю, почему вывод такой:

После этого я просто добавляю строку в свой код, и вывод полностью отличается. мой код следующий:

int main()
{
    int a, b;
    b=fork();

Когда я запускаю код, следующий вывод  2389my имя manish

 the value of b = 0

Теперь я полностью запутался в работе вызова fork().

Мой вопрос следующий:

  • Как работает fork()?
  • Где элемент управления идет после вызова fork()?
  • Может ли какой-либо орган объяснить, почему вывод кодов, написанных в проблеме?
  • Почему вывод b, встречающийся в разных местах, означает в первом коде вывод b = 2260 находится непосредственно перед выходом b = 0, а значение b = 2389 находится не только перед b = 0?

Пожалуйста, объясните мне работу вилки в коде, написанном в проблеме, чтобы я мог его изучить.

4b9b3361

Ответ 1

Это может помочь понять, почему слово вилка использовалось для обозначения этой функции. Вы когда-нибудь слышали о "вилке на дороге"? На развилке процесс должен разделить пути.

Сначала выполняется один процесс, выполняющийся нормально, пока вы не достигнете вызова fork. Когда вызывается fork, создается новый процесс, который практически полностью идентичен исходному процессу , за исключением возвращаемого значения функции fork. Созданный процесс называется дочерним процессом, и, следовательно, процесс, породивший его, называется родительским процессом.

Поскольку вы хотите выполнять разные задачи для каждой ветки fork, это требует, чтобы вы могли отличить дочерний процесс от родительского процесса. То, где возвращается возвращаемое значение fork: fork возвращает идентификатор процесса (pid) дочернего элемента (вновь созданного процесса) родительскому; он возвращает 0 дочернему элементу. Кроме того, если выполнение fork идет не так, возвращаемое значение равно -1.

В вашем коде вы не различаете дочерний и родительский процессы, поэтому оба процесса запускают весь код, следующий за вызовом fork.

//what the child process looks like after fork is called
int main()
{
    int a, b;
    b=fork(); // <-- current line of execution: 0 is returned to b
    printf("\nmy name is manish\n");
    printf("\n my name is anil\n");
    printf("\n the value of b = %d",b);
}

// what the parent process looks like after fork is called
int main()
{
    int a, b;
    b=fork(); // <-- current line: child process id is returned
    printf("\nmy name is manish\n");
    printf("\n my name is anil\n");
    printf("\n the value of b = %d",b);
}

Как вы можете видеть, оба процесса имеют один и тот же код, следующий за fork, поэтому вывод повторяется. Возможно, если вы хотите, чтобы родительский процесс выводил Manish и child для вывода Anil, вы можете сделать что-то вроде:

int main()
{
    pid_t b; // note that the actual return type of fork is 
             // pid_t, though it probably just an int typedef'd or macro'd

    b = fork();
    if (b == -1) perror("Fork failed");
    else if (b > 0) {
        printf("My name is Manish\n"); // parent process
    else
        printf("My name is Anil\n"); // child process

    printf("The value of b is %d\n", b);
    return 0;
}

Наконец, последний комментарий, который должен быть сделан, заключается в том, что в вашем коде вывод, кажется, был выполнен сначала одним процессом целиком, а затем другим процессом в целом. Это не всегда так. Например, операционная система может позволить родительскому процессу выполнить вывод "manish", а затем заставить этот процесс ждать и передать процессор процессу дочернего процесса, который затем выполняет "manish". Тем не менее, дочерний процесс может продолжаться и выполнять "anil" и "b" выходы, завершая выполнение дочернего процесса и тем самым возвращая выполнение обратно в родительский процесс. Теперь родитель заканчивает выполнение, выведя "anil" и "b". Конечный результат запуска этой программы может выглядеть примерно так:

my name is manish     // executed by parent
my name is anil       // child
the value of b = 0    // child
my name is anil       // parent
the value of b = 2244 // parent
[email protected]:~$ 

Взгляните на страницу руководства fork. Также посмотрите waitpid для правильной обработки дочерних процессов родительскими процессами, чтобы вы не создавали зомби.

Изменить. Отвечая на ваши вопросы в комментариях, я отвечу, как вы можете просто последовательно запускать каждый процесс.

int main() 
{
     pid_t pid;
     int i;

     for (i=0; i<NUM_PROCESSES; i++)
     {
         pid = fork();
         if (pid == -1) 
         {
             perror("Error forking");
             return -1;
         }
         else if (pid > 0)
         {
             // parent process
             waitpid(-1, NULL, 0); //might want to look at man page for this
                                   // it will wait until the child process is done 
         }
         else 
         {
             // do whatever each process needs to do;
             // then exit()
             doProcess(i);
             exit(0);
         }
     }
     // do anything else the parent process needs to do
     return 0;
}

Конечно, это не лучший код, а просто для иллюстрации. Большая идея здесь - вызов waitpid, который заставляет родительский процесс ждать, пока дочерний процесс не обработает его просто fork ed, чтобы завершить работу. После завершения дочернего prcoess родитель продолжается после вызова waitpid, начиная новую итерацию цикла for и разворачивая другой (следующий) процесс. Это продолжается до тех пор, пока весь дочерний процесс не будет выполнен последовательно, и выполнение окончательно вернется к родительскому.

Ответ 2

  • Fork создает копию текущего процесса.
  • И оригинал, и копия продолжают выполняться из точки, в которой был вызван fork().
  • Поскольку ваш код выполняется дважды, ваши заявления печати также оцениваются дважды. В скопированном процессе значение b равно 0. В исходном процессе значением b является идентификатор процесса скопированного процесса.
  • Как только ваши процессы начнут работать одновременно, они будут автоматически запланированы вашей операционной системой и, следовательно, у вас нет гарантий относительно того, когда они действительно будут запущены.

Ответ 3

  • Викинг реализован ОС. Он в основном создает дочерний процесс и запускает его после fork().

  • Родительский процесс получает идентификатор процесса файлового процесса: b=fork(); b имеет идентификатор процесса. Детский процесс получает pid нуля.

  • (и 4) Поскольку оба процесса могут выполняться параллельно или быть нарезанными по времени, ваш выход будет отличаться.

Вы можете проверить это: http://en.wikipedia.org/wiki/Fork_(operating_system)

Ответ 4

Лучше начать с this.

Здесь вы найдете объяснение и пример кода.