Написание программы с использованием getpid() и getppid()
В качестве примера использования системных вызовов getpid() и getppid() самостоятельно напишите программу, печатающую значения PID и PPID для текущего процесса. Запустите ее несколько раз подряд. Посмотрите, как меняется идентификатор текущего процесса. Объясните наблюдаемые изменения.
Создание процесса в UNIX. Системный вызов fork()
В операционной системе UNIX новый процесс может быть порожден единственным способом – с помощью системного вызова fork() . При этом вновь созданный процесс будет являться практически полной копией родительского процесса. У порожденного процесса по сравнению с родительским процессом (на уровне уже полученных знаний) изменяются значения следующих параметров:
· идентификатор процесса – PID ;
· идентификатор родительского процесса – PPID .
Дополнительно может измениться поведение порожденного процесса по отношению к некоторым сигналам, о чем подробнее будет рассказано на семинарах 13–14, когда мы будем говорить о сигналах в операционной системеUNIX.
Системный вызов для порождения нового процесса Прототип системного вызова #include <sys/types.h> #include <unistd.h> pid_t fork(void); Описание системного вызова Системный вызов fork служит для создания нового процесса в операционной системе UNIX. Процесс, который инициировал системный вызов fork , принято называть родительским процессом ( parent process ). Вновь порожденный процесс принято называть процессом-ребенком ( child process ). Процесс-ребенок является почти полной копией родительского процесса. У порожденного процесса по сравнению с родительским изменяются значения следующих параметров: · идентификатор процесса; · идентификатор родительского процесса; · время, оставшееся до получения сигнала SIGALRM ; · сигналы, ожидавшие доставки родительскому процессу, не будут доставляться порожденному процессу. При однократном системном вызове возврат из него может произойти дважды: один раз в родительском процессе, а второй раз в порожденном процессе. Если создание нового процесса произошло успешно, то в порожденном процессе системный вызов вернет значение 0, а в родительском процессе – положительное значение, равное идентификатору процесса-ребенка. Если создать новый процесс не удалось, то системный вызов вернет в инициировавший его процесс отрицательное значение. Системный вызов fork является единственным способом породить новый процесс после инициализации операционной системы UNIX. |
В процессе выполнения системного вызова fork() порождается копия родительского процесса и возвращение из системного вызова будет происходить уже как в родительском, так и в порожденном процессах. Этот системный вызов является единственным, который вызывается один раз, а при успешной работе возвращается два раза (один раз в процессе-родителе и один раз в процессе-ребенке)! После выхода из системного вызова оба процесса продолжают выполнение регулярного пользовательского кода, следующего за системным вызовом.
Прогон программы с fork() с одинаковой работой родителя и ребенка
Для иллюстрации сказанного давайте рассмотрим следующую программу:
/* Программа 03-1.с – пример создания нового
процесса с одинаковой работой процессов
ребенка и родителя */
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main()
{
pid_t pid, ppid;
int a = 0;
(void)fork();
/* При успешном создании нового процесса
с этого места псевдопараллельно
начинают работать два процесса: старый
и новый */
/* Перед выполнением следующего выражения
значение переменной a в обоих процессах
равно 0 */
a = a+1;
/* Узнаем идентификаторы текущего и роди-
тельского процесса (в каждом из
процессов !!!) */
pid = getpid();
ppid = getppid();
/* Печатаем значения PID, PPID и вычислен-
ное значение переменной a (в каждом из
процессов !!!) */
printf("My pid = %d, my ppid = %d,
result = %d\n", (int)pid, (int)ppid, a);
return 0;
}
Листинг 3.1. Программа 03-1.с – пример создания нового процесса с одинаковой работой процессов ребенка и родителя.
Наберите эту программу, откомпилируйте ее и запустите на исполнение (лучше всего это делать не из оболочки mc, так как она не очень корректно сбрасывает буферы ввода-вывода). Проанализируйте полученный результат.