Процессы

Что такое процесс

Процесс — программа в стадии выполнения со всеми регистрами и счётчиком команд. У каждого процесса есть адресное пространство — набор адресов ячеек памяти, необходимых для его выполнения.

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() работают без буферизации.

Структура пользовательского процесса

  • Контекст процесса — информация о текущем состоянии.
  • Статический сегмент данных — глобальные и статические переменные.
  • Процедурный сегмент — программный код.
  • Динамический сегмент — динамические структуры данных (куча).
← Назад к списку тем