Тема:Синхронизация процессов. Системные вызовы Wait и Waitpid.
Цель: Изучить методы синхронизации процессов с помощью функций wait и waitpid.
Порядок выполнения работы:
Выучить основные функции синхронизации процессов.
Написать и отладить программу, создающую процессы. Отработать их синхронизацию.
Проанализировать результаты и сделать вывод.
Теоретические сведения:
GETPID
getpid, getppid - считывает идентификатор процесса
СИНТАКСИС
#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void);
pid_t getppid(void);
ОПИСАНИЕ
getpid возвращает идентификатор текущего процесса (PID). Обычно это используется программами, создающими уникальные временные названия файлов. getppid возвращает идентификатор родительского процесса(PPID).
WAIT
wait, waitpid - ожидает завершения процесса
СИНТАКСИС
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);
ОПИСАНИЕ
Функция wait приостанавливает выполнение текущего процесса до тех пор, пока дочерний процесс не завершится, или до появления сигнала, который либо завершает текущий процесс, либо требует вызвать функцию обработчик. Если дочерний процесс к моменту вызова функции уже завершился (так называемый "зомби" ("zombie")), то функция немедленно возвращается. Системные ресурсы, связанные с дочерним процессом, освобождаются. Функция waitpid приостанавливает выполнение текущего процесса до тех пор, пока дочерний процесс, указанный в параметре pid, не завершит выполнение, или пока не появится сигнал, который либо завершает текущий процесс либо требует вызвать функцию обработчик. Если указанный дочерний процесс к моменту вызова функции уже завершился (так называемый "зомби"), то функция немедленно возвращается. Системные ресурсы, связанные с дочерним процессом, освобождаются. Параметр pid может принимать несколько значений:
1. < -1 означает, что нужно ждать любого дочернего процесса, идентификатор группы процессов которого равен абсолютному значению pid.
2. -1 означает ожидание любого дочернего процесса; функция wait ведет себя точно так же.
3. 0 означает ожидание любого дочернего процесса, идентификатор группы процессов которого равен идентификатору текущего процесса.
4. 0 означает ожидание дочернего процесса, чей идентификатор равен pid.
Значение options создается путем логического сложения нескольких следующих констант:
1. WNOHANG - означает немедленное возвращение управления, если ни один дочерний процесс не завершил выполнение.
2. WUNTRACED - означает возврат управления и для остановленных дочерних процессов, о статусе которых еще не было сообщено.
Если status не равен NULL, то функции wait и waitpid сохраняют информацию о статусе в переменной, на которую указывает status. Этот статус можно проверить с помощью нижеследующих макросов (они принимают в качестве аргумента буфер (типа int), - а не указатель на буфер!):
· WIFEXITED(status) - не равно нулю, если дочерний процесс успешно завершился.
· WEXITSTATUS(status) - возвращает восемь младших битов значения, которое вернул завершившийся дочерний процесс. Эти биты могли быть установлены в аргументе функции exit() или в аргументе оператора return функции main(). Этот макрос можно использовать, только если WIFEXITED вернул ненулевое значение.
· WIFSIGNALED(status) - возвращает истинное значение, если дочерний процесс завершился из-за необработанного сигнала.
· WTERMSIG(status) - возвращает номер сигнала, который привел к завершению дочернего процесса. Этот макрос можно использовать, только если WIFSIGNALED вернул ненулевое значение.
· WIFSTOPPED(status) - возвращает истинное значение, если дочерний процесс, из-за которого функция вернула управление, в настоящий момент остановлен; это возможно, только если использовался флаг WUNTRACED.
· WSTOPSIG(status) - возвращает номер сигнала, из-за которого дочерний процесс был остановлен. Этот макрос можно использовать, только если WIFSTOPPED вернул ненулевое значение.
ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
Возвращает идентификатор дочернего процесса, который завершил выполнение, или ноль, если использовался WNOHANG и ни один дочерний процесс пока еще недоступен, или -1 в случае ошибки (в этом случае переменной errno присваивается соответствующее значение).
Пример синхронизации процессов.
Если запустить данную программу без параметров, то главный процесс породит 15 дочерних процессов и завершится, не дождавшись завершения дочерних процессов.
Если запустить программу с одним и более параметром, то родительский процесс породивши 15 дочерних, будет ждать завершения всех дочерних процессов прежде чем завершиться самому.
При завершении дочернего процесса родительский процесс выводит значение и код, возвращаемые дочерним процессом.
Текст программы:
#include <stdio.h>
#include <signal.h>
int i,ret_val,ret_code; //переменная цикла возвращаемое значение и код
int pid; //идентификатор процесса
int main(int argc,char *argv[])
{
for(i=0;i<15;i++) //в цикле 15 раз порождаем новый процесс
{
pid=fork(); //и переключаемся на его выполнение
switch (pid) //анализируем идентификатор процесса
{
case -1:{ //если равен -1 - ошибка
perror("\n\tError");
return 0;
}
case 0:{ //если равен 0 - находимся в дочернем процессе
printf("\t Daughter process %i pid=%i\n",i,getpid());
sleep(1); //задержка на одну секунду
exit(i); //возвращаем родителю номер процесса
}
default:{if(argc>1)
{
ret_val=wait(&ret_code);//ожидаем завершения процесса-потомка