организовать двустороннюю поочередную связь процесса-родителя и процесса-ребенка через pipe, используя для синхронизации сигналы sigusr1 и sigusr2. |
Процессы в операционной системе UNIX
Создание процесса в UNIX. Системный вызов fork()
В операционной системе UNIX новый процесс может быть порожден единственным способом – с помощью системного вызова fork() . При этом вновь созданный процесс будет являться практически полной копией родительского процесса. У порожденного процесса по сравнению с родительским процессом (на уровне уже полученных знаний) изменяются значения следующих параметров:
Дополнительно может измениться поведение порожденного процесса по отношению к некоторым сигналам, о чем подробнее будет рассказано на семинарах 13–14, когда мы будем говорить о сигналах в операционной системе 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, так как она не очень корректно сбрасывает буферы ввода-вывода). Проанализируйте полученный результат.
Системный вызов fork() (продолжение)
Для того чтобы после возвращения из системного вызова fork() процессы могли определить, кто из них является ребенком, а кто родителем, и, соответственно, по-разному организовать свое поведение, системный вызов возвращает в них разные значения. При успешном создании нового процесса в процесс-родитель возвращается положительное значение, равное идентификатору процесса-ребенка. В процесс-ребенок же возвращается значение 0. Если по какой-либо причине создать новый процесс не удалось, то системный вызов вернет в инициировавший его процесс значение -1. Таким образом, общая схема организации различной работы процесса-ребенка и процесса-родителя выглядит так:
pid = fork(); if(pid == -1){ ... /* ошибка */ ... } else if (pid == 0){ ... /* ребенок */ ... } else { ... /* родитель */ ... }
Написание, компиляция и запуск программы с использованием вызова fork() с разным поведением процессов ребенка и родителя
Измените предыдущую программу с fork() так, чтобы родитель и ребенок совершали разные действия (какие – не важно).