Основы многозадачности в Linux


Листинг 10.15. Пример execvpls.c



бет13/15
Дата16.11.2022
өлшемі472,04 Kb.
#158456
1   ...   7   8   9   10   11   12   13   14   15
Байланысты:
5-6 лаб раб (1)

Листинг 10.15. Пример execvpls.c
#include
#include
#include
int main (void)
{
pid_t result;
char * ls_args[] = {
"ls",
"-l",
"/",
NULL
};
result = fork ();
if (result == -1) {
fprintf (stderr, "Fork error\n");
return 1;
}
/* Child */
if (result == 0) {
execvp ("ls", ls_args);
fprintf (stderr, "Exec error\n");
return 1;
}
/* Parent */
return 0;
}
Итак, мы рассмотрели примеры работы функций семейства exec() "на все случаи жизни". Если что-то со временем забудется, держите закладку на этом разделе: хороший пример освежит вашу память лучше любого справочника.
Ожидание процесса: wait()
Мы уже говорили о том, что процессы в Linux работают независимо друг от друга. Но иногда перед программистом встает задача организации последовательного выполнения процессов.
Типичный пример реализации последовательного выполнения процессов — ожидание родителем завершения своего потомка. Возьмем, например, командную оболочку. Если мы запускаем программу не в фоновом режиме, то оболочка не выдаст приглашение командной строки до тех пор, пока данная программа не завершится.
Другой пример — это последовательный запуск родительским процессом двух и более потомков. Например, многие командные оболочки позволяют разделять несколько команд точкой с запятой, организовывая тем самым их последовательное выполнение. Рассмотрим пример
$ sleep 5 ; ls /
Эта команда "ждет" 5 с, а потом выводит содержимое корневого каталога вашей системы. Самый "варварский" способ заставить родительский процесс дождаться завершения своего потомка — выждать некоторое время. Рассмотрим пример (листинг 10.16).
Листинг 10.16. Пример lsroot.c



Никогда не делайте так, как предложено в листинге 10.16! Очевидно, что программе ls с лихвой хватит трех секунд, чтобы вывести небогатое содержимое корневого каталога. Но если в этом каталоге случайно окажется миллион файлов, то предыдущее утверждение будет весьма спорным. Есть и еще один немаловажный нюанс: если, например, программа ls выведет содержимое корневого каталога за одну десятую секунды, зачем заставлять пользователя ждать "впустую" еще 2,9 с?
Существует системный вызов wait(), который позволяет избежать создания таких нелепых программ (листинг 10.16). wait() блокирует родительский процесс до тех пор, пока не завершится один из его потомков. Этот системный вызов объявлен в заголовочном файле wait.h следующим образом:
pid_t wait (int * EXIT_STATUS);
По типу возвращаемого значения нетрудно догадаться, что wait() возвращает
идентификатор завершившегося потомка. Однако указатель EXIT_STATUS требует особого рассмотрения.
При изучении библиотечной функции system() в главе 9 упоминалось, что она возвращает статус завершившегося потомка. Пришла пора разобраться в том, что это такое. Итак, статус завершившегося потомка — это целое число, содержащее код возврата и некоторую другую информацию о том, как завершился процесс. Для извлечения этой информации существуют специальные макросы:
 WIFEXITED() — возвращает ненулевое значение, если потомок завершится посредством возврата из функции main() или через вызов exit().
 WEXITSTATUS() — возвращает код возврата завершившегося процесса. Этот макрос вызывается в том случае, если WIFEXITED() вернул ненулевое значение.
 WIFSIGNALED() — возвращает ненулевое значение, если процесс был завершен посредством получения сигнала. О сигналах речь пойдет в главе 20.
 WTERMSIG(), WCOREDUMP(), WIFSTOPPED(), WSTOPSIG() и WCONTINUED() — относятся к сигналам.
Рассмотрим теперь пример использования системного вызова wait() (листинг 10.17).




Достарыңызбен бөлісу:
1   ...   7   8   9   10   11   12   13   14   15




©engime.org 2024
әкімшілігінің қараңыз

    Басты бет