Новый процесс порождается системным вызовом fork(), который создает дочерний процесс - копию родительского. Прототип данной функции находится в <unistd.h>. В дочернем процессе выполняется та же программа, что и в родительском, и когда дочерний процесс начинает выполняться, он выполняется с точки возврата из системного вызова fork(). Системный вызов fork() возвращает родительскому процессу PID дочернего процесса, а дочернему процессу - 0. По коду возврата вызова fork() дочерний процесс может "осознать" себя как дочерний. Свой PID процесс может получить при помощи системного вызова getpid(), а PID родительского процесса - при помощи системного вызова getppid(). Если требуется, чтобы в дочернем процессе выполнялась программа, отличная от программы родительского процесса, процесс может сменить выполняемую в нем программу при помощи одного из системных вызовов семейства exec. Все вызовы этого семейства загружают для выполнения в процессе программу из заданного в вызове файла и отличаются друг от друга способом передачи параметров этой программе. Таким образом, наиболее распространенный контекст применения системного вызова fork() выглядит примерно так:
/* порождение дочернего процесса и запоминание его PID */
if (!(ch_pid=fork()))
/* загрузка другой программы в дочернем процессе */
exec(программа);
else /* продолжение родительского процесса */
Пример программы на языке С.
#include <stdio.h>
#include <unistd.h>/* contains fork prototype */
int main(void)
{
int pid;
printf("Hello World!\n");
printf("I am the parent process and my PID is : %d.\n",getpid());
printf("Here I am before use of forking\n");
pid = fork();
printf("Here I am just after forking\n");
if (pid == 0)
printf("I am the child process and PID is :%d.\n",getpid());
else
printf("I am the parent process and PID is: %d.\n",getpid());
return 0;
}
Примерный результат работы программы:
Hello World!
I am the parent process and my PID is : 23951.
Here I am before use of forking
Here I am just after forking
Here I am just after forking
I am the child process and my PID is :23952.
I am the parent process and my PID is: 23951.
Нормальное завершение процесса происходит при достижении конца функции main или при выполнении системного вызова exit(). При этом процесс устанавливает некоторый код своего завершения, который может быть прочитан процессом-предком. Существует общепринятое соглашение, по которому 0 означает нормальное завершение, а любое другое значение – ошибку или необычное происшествие. Множество стандартных библиотечных вызовов используют ошибки, определенные в <sys/stat.h>.
Принудительное завершение процесса извне может быть выполнено при помощи системного вызова kill(), посылающего процессу сигнал. С сигналами мы познакомимся при выполнении следующих лабораторных работ, пока же только отметим, что гарантированно "убить" процесс, имеющий PID = p, можно системным вызовом kill(p,SIGKILL).
Ожидание завершения процесса
Процесс-предок может ожидать завершения процесса-потомка (или процессов-потомков) при помощи системных вызовов wait() или waitpid(). Прототипы этих функций находятся в <sys/wait.h>. Если процесс-потомок еще не завершился, процесс-предок переводится таким системным вызовом в состояние ожидания до завершения процесса-потомка (впрочем, процесс может и не ожидать завершения потомка, а только проверить, завершился ли он). Эти системные вызовы позволяют также процессу предку узнать код завершения потомка.
Пример программы.
#include <stdio.h>
#include <sys/wait.h> /* contains prototype for wait */
int main(void)
{
int pid;
int status;
printf("Hello World!\n");
pid = fork( );
if (pid == -1)
{
perror("bad fork");
exit(1);
}
if (pid == 0)
printf("\t I am the child process.\n");
else
{
wait(&status); /* parent waits for child to finish */
printf("I am the parent process.\n");
}
return 0;
}
Результат работы программы:
Hello World!
I am the child process.
I am the parent process.
Задания на лабораторную работу:
1) 1) Программа должна создать четыре процесса и ожидать окончания их выполнения.
2) 2) Порядок создания процессов задается с командной строки (передается в виде параметров в функцию main), например:
./a.out 1 3 2 4
3) 3) Каждый процесс и основная программа должны выводить на экран сообщения о начале и завершении своей работы в следующем формате:
PID PPID “сообщение” “время сообщения”
4) 4) Для получения текущего времени используйте функцию ctime() из <time.h>.
5) 5) Процессы должны использовать функции, перечисленные по порядку:
execv(), execl(), execvp()и execlp() с любыми командами ОС Linux внутри. Вы можете также использовать любые свои программы.
6) 6) Программа должна анализировать и сообщать о причинах завершения процессов, используя переменную errno. Все значения ошибок определены в заголовочном файле <sys/errno.h> .
Содержание отчета по лабораторной работе:
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.