Чтение онлайн

на главную - закладки

Жанры

Разработка приложений в среде Linux. Второе издание

Троан Эрик В.

Шрифт:

10.5.1. Запуск и ожидание с помощью

system

Программам часто требуется запускать другие программы и ожидать их завершения, прежде чем продолжать свою работу. Функция

system
позволяет это делать достаточно просто.

int system (const char* cmd);

system
порождает дочерний процесс, который выполняет
exec
для
/bin/sh
, который, в свою очередь, запускает
cmd
. Исходный процесс ожидает завершения дочерней оболочки и возвращает тот же код, что
wait
[28] . Если вам не нужно оставлять в памяти оболочку (что случается редко),
cmd
должна включать
предшествующее слово
"exec"
, которое заставляет оболочку вызывать
exec
вместо запуска
cmd
как подпроцесса.

28

В процессе работы

system
блокирует
SIGCHILD
, что заставляет передавать этот сигнал программе непосредственно перед тем, как
system
вернет управление (но после того, как
system
вызовет
wait
для порожденного процесса), поэтому программы, которые используют обработчики сигналов, должны это учитывать и обрабатывать такие ложные сигналы осторожно. Функция
system
также игнорирует
SIGINT
и
SIGQUIT
, а это означает, что быстрые циклические повторные вызовы
system
может оказаться невозможно прервать ничем, кроме
SIGSTOP
и
SIGKILL
.

Поскольку

cmd
запускается из оболочки
/bin/sh
, то здесь применимы все обычные правила расширения команд. Ниже показан пример вызова
system
, который отображает исходные тексты С из текущего каталога.

#include <stdlib.h>

#include <sys/wait.h>

int main {

int result;

result = system("exec ls *.c");

if (!WIFEXITED(result))

 printf("(аварийный выход)\n");

 exit(0);

}

Команда

system
должна применяться с большой осторожностью в программах, которые запускаются со специальными полномочиями. Поскольку системная оболочка предоставляет множество мощных средств и сильно зависит от переменных окружения,
system
является уязвимым местом в плане безопасности, которым могут воспользоваться злоумышленники для проникновения в систему. Однако до тех пор, пока приложение не является демоном или программой
setuid/setgid
, вызов
system
совершенно безопасен.

10.5.2. Чтение и запись из процесса

Хотя

system
отображает результат работы команды на устройство стандартного вывода и позволяет дочерним программам читать стандартный ввод, это не всегда идеально. Часто процесс желает читать вывод другого процесса либо отправлять текст на стандартный ввод.
popen
облегчает процессам решение этой задачи [29] .

FILE * popen(const char *cmd, const char *mode);

29

Хотя функция

popen
это делает просто, с ней связаны некоторые побочные эффекты, которые не сразу становятся очевидны. Она создает дочерний процесс, который может быть прерван перед тем, как будет вызвана
pclose
, что заставит функцию
wait
вернуть состояние процесса. Когда этот процесс завершится, он также сгенерирует
SIGCHLD
, что может привести в замешательство упрощенно написанный обработчик сигналов.

cmd
выполняется через оболочку, как и в
system
. Параметр
mode
должен быть
"r"
, если родительский процесс желает читать командный вывод, и
"w"
— для записи в стандартный ввод дочернего процесса. Следует отметить, что с помощью
popen
делать одновременно чтение и запись нельзя.

Два

процесса, которые читают и пишут друг в друга, достаточно сложны [30] и выходят за рамки возможностей
popen
[31] .

30

Этот тип обработки часто приводит к взаимоблокировкам, при которых процесс А ожидает, пока процесс В выполнит какую-то работу, в то время как процесс В ожидает процесса А, в результате чего ничего не происходит.

31

Если вам понадобится делать это, запустите дочерний процесс с помощью

fork
и
exec
, а потом воспользуйтесь
poll
для чтения и записи в дочерний процесс. Для этого предназначена программа под названием
expect
.

popen
возвращает
FILE*
(как это определено в стандартной библиотеке ввода-вывода ANSI/ISO), который может быть прочитан и записан подобно любому другому потоку
stdio
[32] , либо
NULL
, если операция не удается. Когда завершается родительский процесс, он может воспользоваться
pclose
для закрытия потока и прерывания дочернего процесса, если он все еще выполняется. Подобно
system
,
pclose
возвращает состояние дочернего процесса из
wait4
.

32

Информацию о чтении и записи в поток

stdio
можно найти в [15].

int pclose(FILE *stream);

Ниже приведен пример простой программы-калькулятора, которая использует программу

bc
для выполнения всей реальной работы. Важно сбрасывать поток, полученный от
popen
, после записи в него, чтобы предотвратить буферизацию
stdio
от задержки вывода (подробности о буферизации стандартных функций библиотеки
stdio
можно найти в [15]).

 1: /*calc.c*/

 2:

 3: /* Это очень простой калькулятор, который использует внешнюю команду bc

 4: для выполнения всей работы. Открывает канал к bc, читает команду,

 5: передает ее bc и завершается. */

 6: #include <stdio.h>

 7: #include <sys/wait.h>

 8: #include <unistd.h>

 9:

10: int main(void) {

11: char buf[1024];

12: FILE *bc;

13: int result;

14:

15: /* открыть канал на bc и выйти в случае неудачи */

16: bc = popen("bc", "w");

17: if (!bc) {

18: perror("popen");

19: return 1;

20: }

21:

22: /* пригласить ввести выражение, и прочитать его */

23: printf("expr:"); fflush(stdout);

24: fgets(buf, sizeof(buf), stdin);

25:

26: /* послать выражение bc для вычисления */

27: fprintf(bc, "%s\n", buf);

28: fflush(bc);

29:

30: /* закрыть канал на bc и ожидать выхода из нее */

31: result = pclose(bc);

32:

33: if (!WIFEXITED(result))

34: printf("(аварийный выход)\n");

35:

36: return 0;

37: }

Поделиться:
Популярные книги

Усадьба леди Анны

Ром Полина
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Усадьба леди Анны

Чужая дочь

Зика Натаэль
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Чужая дочь

Светлая тьма. Советник

Шмаков Алексей Семенович
6. Светлая Тьма
Фантастика:
юмористическое фэнтези
городское фэнтези
аниме
сказочная фантастика
фэнтези
5.00
рейтинг книги
Светлая тьма. Советник

Двойник Короля

Скабер Артемий
1. Двойник Короля
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Двойник Короля

Его нежеланная истинная

Кушкина Милена
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Его нежеланная истинная

Последний Паладин. Том 2

Саваровский Роман
2. Путь Паладина
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Последний Паладин. Том 2

Измена. Наследник для дракона

Солт Елена
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Измена. Наследник для дракона

Идеальный мир для Лекаря 9

Сапфир Олег
9. Лекарь
Фантастика:
боевая фантастика
юмористическое фэнтези
6.00
рейтинг книги
Идеальный мир для Лекаря 9

Мастер темных Арканов

Карелин Сергей Витальевич
1. Мастер темных арканов
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Мастер темных Арканов

Адвокат империи

Карелин Сергей Витальевич
1. Адвокат империи
Фантастика:
городское фэнтези
попаданцы
фэнтези
5.75
рейтинг книги
Адвокат империи

Кодекс Охотника. Книга XXI

Винокуров Юрий
21. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Охотника. Книга XXI

Вечный. Книга II

Рокотов Алексей
2. Вечный
Фантастика:
боевая фантастика
попаданцы
рпг
5.00
рейтинг книги
Вечный. Книга II

Законы Рода. Том 3

Flow Ascold
3. Граф Берестьев
Фантастика:
фэнтези
аниме
5.00
рейтинг книги
Законы Рода. Том 3

Наследник

Шимохин Дмитрий
1. Старицкий
Приключения:
исторические приключения
5.00
рейтинг книги
Наследник