Процессы
Что такое процесс
Процесс — программа в стадии выполнения со всеми регистрами и счётчиком команд. У каждого процесса есть адресное пространство — набор адресов ячеек памяти, необходимых для его выполнения.
system()
int system(char *com);
Запускает новую программу в рамках потока и приостанавливает выполнение текущей до её завершения.
char *com— указатель на командную строку.- Возвращает 1 при успехе, -1 при ошибке.
system("cp a.c b.c");
system("./a.exe");
Не используется в системных утилитах — множит процессы.
execl()
int execl(char *path, char *arg_0, ..., char *arg_n, NULL);
Замещает текущий процесс новым. Программа досрочно заканчивает выполнение.
char *path— полное имя программы.char *arg_0— нулевой аргумент (имя самой программы).NULL— признак конца списка аргументов.- Возвращает -1 только в случае ошибки (иначе не возвращает управление).
execl("./a.exe", "a.exe", NULL);
execl("/bin/cp", "cp", "a.c", "b.c", NULL);
fork()
int fork(void);
Создаёт дочерний процесс — точную копию родительского, за исключением:
- Дочерний процесс получает уникальный PID.
- У дочернего процесса другой PPID (идентификатор родителя).
- Дочерний процесс получает свою копию дескрипторов родителя.
Возвращает 0 дочернему процессу, PID дочернего — родителю, -1 при ошибке.
int p = fork();
if (p > 0) {
/* процесс-отец */
} else if (p == 0) {
/* процесс-сын */
} else {
/* авария */
}
Осторожно с fork() в бесконечных циклах — можно создать fork-бомбу.
wait() и waitpid()
int wait(int *s);
Используется в процессе-отце для ожидания завершения процесса-сына. Возвращает PID завершившегося сына, в аргумент записывает причину завершения.
int s;
if (fork() == 0) {
execl("/bin/ls", "ls", NULL);
} else {
wait(&s);
}
Завершение процесса
В UNIX процесс может быть завершён двумя способами:
- Системным вызовом
_exit()или библиотечной функциейexit(). - Сигналом (их более 40, бывают внешние и внутренние).
int _exit(int arg); int exit(int arg); /* #include <stdlib.h> */
Разница между _exit() и exit():
| _exit() | exit() |
|---|---|
| Системный вызов | Библиотечная функция |
| Не выталкивает буферы ввода/вывода | Выталкивает буферы ввода/вывода |
/* _exit не выталкивает буфер printf */
printf("Hello ");
write(1, "my friend", 9);
_exit(1);
/* Вывод: my friend */
/* exit выталкивает буфер printf */
printf("Hello ");
write(1, "my friend", 9);
exit(1);
/* Вывод: my friendHello */
Только
write() и read() работают без буферизации.
Структура пользовательского процесса
- Контекст процесса — информация о текущем состоянии.
- Статический сегмент данных — глобальные и статические переменные.
- Процедурный сегмент — программный код.
- Динамический сегмент — динамические структуры данных (куча).