Таким образом, порождение нового процесса уже не кажется абсолютно бессмысленным, поскольку родитель и потомок могут параллельно выполнять различные функции. В данном случае, это вывод на терминал различных сообщений, однако можно представить себе и более сложные приложения. В частности, большинство серверов, одновременно обслуживающих несколько запросов, организованы именно таким образом: при поступлении запроса порождается процесс, который и выполняет необходимую обработку. Родительский процесс является своего рода супервизором, принимающим запросы и распределяющим их выполнение. Очевидным недостатком такого подхода является то, что вся функциональность по-прежнему заложена в одном исполняемом файле и, таким образом, ограничена.
UNIX предлагает системный вызов, предназначенный исключительно для запуска программ, т.е. загрузки другого исполняемого файла. Это системный вызов
#include
int execl(const char *path, const char *arg0, ... ,
const char *argn, char * /* NULL */);
int execv(const char* path, char* const argv[]);
int execle(const char *path, char *const arg0[], ... ,
const char *argn, char* /* NULL */, char *const envp[]);
int execve(const char* path, char const argv[],
char *const envp[]);
int execlp(const char *file, const char *arg0, ... ,
const char* argn, char * /* NULL */);
int execvp(const char *file, char *const argv[]);
Все эти функции по существу являются надстройками системного вызова
Рис. 2.12. Семейство функций
В отличие от вызова
□ идентификаторы процесса PID и PPID,
□ идентификаторы пользователя и группы,
□ эффективные идентификаторы пользователя и группы (в случае, если для исполняемого файла не установлен флаг SUID или SGID),
□ ограничения, накладываемые на процесс,
□ текущий и корневой каталоги,
□ маска создания файлов,
□ управляющий терминал,
□ файловые дескрипторы, для которых не установлен флаг FD_CLOEXEC
.
Наследование характеристик процесса играет существенную роль в работе операционной системы. Так наследование идентификаторов владельцев процесса гарантирует преемственность привилегий и, таким образом, неизменность привилегий пользователя при работе в UNIX. Наследование файловых дескрипторов позволяет установить направления ввода/вывода для нового процесса или новой программы. Именно так действует командный интерпретатор. Мы вернемся к вопросу о наследовании в главе 3.
В главе 1 уже говорилось о частом объединении вызовов
При порождении процесса, который впоследствии может загрузить новую программу, "родителю" может быть небезынтересно узнать о завершении выполнения "потомка". Например, после того как запущена утилита SIGCHLD
, отправляемого ему при "смерти" потомка. Механизм сигналов мы рассмотрим в следующем разделе. Сейчас же остановимся на другом подходе.
Операционная система предоставляет процессу ряд функций, позволяющих ему контролировать выполнение потомков. Это функции
#include
#include
pid_t wait(int* stat_loc);
int waitpid(idtype_t idtype, id_t id,
siginfo_t * infop, int options);
pid_t waitpid(pid_t pid, int *stat_loc, int options);
Вильям Л Саймон , Вильям Саймон , Наталья Владимировна Макеева , Нора Робертс , Юрий Викторович Щербатых
Зарубежная компьютерная, околокомпьютерная литература / ОС и Сети, интернет / Короткие любовные романы / Психология / Прочая справочная литература / Образование и наука / Книги по IT / Словари и Энциклопедии