Форкинг, сигналы и как они взаимодействуют с глобальными переменными в C - PullRequest
1 голос
/ 16 декабря 2010

Я пытаюсь понять, как fork () / ядро ​​Linux работает с глобальными переменными.

Данный код:

#include<signal.h>
#include<unistd.h>
#include<stdio.h>
#include<errno.h>
#include <sys/types.h>

pid_t pid;
int counter = 2;
void handler1(int sig)
{
 counter = counter - 1;
 printf("%d", counter);
 exit(0);
}
int main()
{
    signal(SIGUSR1, handler1); //Install Handler
    printf("%d", counter);     //Print Parent global variable
    pid = fork( );             //Fork(), child pid = 0, parent's pid = positive int.
    if (pid == 0)              //Parent skips this, child goes into infinite loop
    {
      while(1) {}; // simulate doing some work
    }
    kill(pid, SIGUSR1);        //While child is the loop, parents calls to terminate the child. 
                               //Child will stop the infinite loop, and will not proceed any 
                               //Will it call handler1 ???

    wait(NULL);                //Wait for child to be ripped
                               //Will it call handler1 second time ???
    counter = counter + 1;     //This will surely increment global variable
    printf("%d", counter);
    exit(0);
}

Выход 2123 Как ядро ​​Unix / Linux работает с глобальными переменными после вызова fork () и обработки сигналов ??? Распределяются ли они между ребенком и родителем?

Другая проблема, с которой я сталкиваюсь в этом коде, заключается в том, как kill () и wait () будут работать с глобальными переменными и какой набор они будут использовать - родительский или дочерний ?? И они будут вызывать обработчик сигнала ???

Спасибо!

Ответы [ 3 ]

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

Ребенок получает независимую копию глобальных переменных.Две копии не разглашаются .

3 голосов
/ 17 декабря 2010

После fork() весь процесс, включая все глобальные переменные, дублируется. Дочерний объект является точной копией родительского элемента, за исключением того, что он имеет другой PID, другой родительский элемент и fork() вернул 0.

Обработчик сигнала в дочернем элементе будет использовать независимую дочернюю копию глобальной переменной.

Причина, по которой вы печатаете 2 дважды, заключается в том, что вы не сбросили стандартный вывод после печати. Вот что происходит:

  • counter равно 2.
  • Родительский процесс выполняет printf("%d", counter);, который помещает "2" в выходной буфер stdout, но не очищает его. Нет выводимых данных.
  • fork() вызывается, что дублирует процесс. Теперь есть две копии переменной counter, и обе установлены на 2. Также есть два экземпляра выходного буфера stdout, каждый из которых содержит строку "2". Нет выводимых данных.
  • Родитель отправляет SIGUSR1 ребенку и блокирует wait().
  • Дочерний объект выполняет handler1(), что уменьшает копию дочернего элемента с counter до 1 и помещает "1" в выходной буфер stdout дочернего объекта (который теперь содержит "21").
  • Ребенок выполняет exit(0), что побочным эффектом сбрасывает stdout. Теперь появляется вывод "21", написанный ребенком, и ребенок выходит.
  • wait() возвращает в родительский процесс. Родитель увеличивает свою копию counter до 3, а затем печатает "3" в свой выходной буфер stdout (который теперь содержит "23").
  • Родитель выполняет exit(0), что в качестве побочного эффекта сбрасывает stdout. Теперь вывод "23" появляется, и родитель выходит.

Если вы поставите fflush(stdout); перед fork(), 2 будет напечатан только один раз, а на выходе будет "213". Рекомендуется очищать все буферизованные выходные потоки перед вызовом fork().

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

fork создает копию процесса в его текущем состоянии.Ничто не используется совместно, кроме явно отображенных ресурсов общей памяти (анонимных общих карт, общих файловых карт, блоков общей памяти sysv и блоков общей памяти POSIX).

Вы также должны знать, что пока новый процесс имеет свой собственныйкопия таблицы дескрипторов файлов, эти дескрипторы файлов ссылаются на те же «описания открытых файлов» в ядре.Они разделяют текущую позицию поиска, между прочим.

Подробнее см .:

http://www.opengroup.org/onlinepubs/9699919799/functions/fork.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...