Статья: Теория вычислительных процессов и структур
REEEt
WEEEEEEERSIIIONN
Файл, полученный в результате работы программы:
1. 4
2. 5
3. 16
итого: 3 строки 25 символов
7. Написать программу поиска заданного пользователем файла в текущем каталоге. Предусмотреть контроль ошибок.
8. Написать программу сравнения двух заданных пользователем файлов по их содержимому. Предусмотреть контроль ошибок.
9. Написать программу сравнения двух заданных пользователем каталогов.
Предусмотреть контроль ошибок.
Лабораторная работа №2
Создание процессов
Цель работы - организация функционирования процессов заданной структуры и исследование их взаимодействия.
Теоретическая часть
Для создания процессов используется системный вызов fork:
#include <sys/types.h>
#include <unistd.h>
pid_t fork (void);
В результате успешного вызова fork ядро создаёт новый процесс, который является почти точной копией вызывающего процесса. Другими словами, новый процесс выполняет копию той же программы, что и создавший его процесс, при этом все его объекты данных имеют те же самые значения, что и в вызывающем процессе.
Созданный процесс называется дочерним процессом, а процесс, осуществляющий вызов fork, называется родительским.
После вызова родительский процесс и его вновь созданный потомок выполняются одновременно, при этом оба процесса продолжают выполнение с оператора, который следует сразу же за вызовом fork.
Идею, заключённую в вызове fork, быть может, достаточно сложно понять тем, кто привык к схеме последовательного программирования. Ниже приведен пример, иллюстрирующий это понятие (рис. 2.1). На рисунке рассматриваются три строки кода, состоящие из вызова printf, за которым следуют вызов fork и ещё один вызов printf. Рисунок разбит на две части: До и После. Часть рисунка До показывает состояние до вызова fork. Существует единственный процесс А (его обозначили буквой А только для удобства, для системы это ничего не значит). Стрелка, обозначенная РС (Program counter – программный счётчик), указывает на выполняемый в настоящий момент оператор. Так как стрелка указывает на первый оператор printf, на стандартный вывод выдаётся тривиальное сообщение One.
Часть рисунка После показывает ситуацию сразу же после вызова fork. Теперь существуют два выполняемых одновременно процесса: А и В. Процесс А – это тот же самый процесс, что и в части рисунка До. Процесс В – это новый процесс, порождённый вызовом fork. Этот процесс является копией процесса А, кроме одного важного исключения – он имеет другое значение идентификатора (процесса pid), но выполняет ту же самую программу, что и процесс А, т. е. те же три строки исходного кода, приведённые на рисунке. В соответствии с введенной выше терминологией процесс А является родительским процессом, а процесс В – дочерним. Две стрелки с надписью РС в этой части рисунка
Рис. 2.1. Вызов fork
показывают, что следующим оператором, который выполняется родителем и потомком после вызова fork, является вызов printf. Другими словами, оба процесса А и В продолжают выполнение с той же точки кода программы, хотя процесс В и является новым процессом для системы. Поэтому сообщение Two выводится дважды.
Вызов fork не имеет аргументов и возвращает идентификатор процесса pid_t. Родитель и потомок отличаются значением переменной pid: в родительском процессе значение переменной pid будет ненулевым положительным числом, для потомка же оно равно нулю. Так как возвращаемые в родительском и дочернем процессе значения различаются, то программист может задавать различные действия для двух процессов.
Следующая короткая программа более наглядно показывает работу вызова fork и использование процесса: