Майкл Джонсон - Разработка приложений в среде Linux. Второе издание
- Название:Разработка приложений в среде Linux. Второе издание
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:2007
- Город:Москва
- ISBN:978-5-8459-1143-8
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Майкл Джонсон - Разработка приложений в среде Linux. Второе издание краткое содержание
Книга известных профессионалов в области разработки коммерческих приложений в Linux представляет собой отличный справочник для широкого круга программистов в Linux, а также тех разработчиков на языке С, которые перешли в среду Linux из других операционных систем. Подробно рассматриваются концепции, лежащие в основе процесса создания системных приложений, а также разнообразные доступные инструменты и библиотеки. Среди рассматриваемых в книге вопросов можно выделить анализ особенностей применения лицензий GNU, использование свободно распространяемых компиляторов и библиотек, системное программирование для Linux, а также написание и отладка собственных переносимых библиотек. Изобилие хорошо документированных примеров кода помогает лучше усвоить особенности программирования в Linux.
Книга рассчитана на разработчиков разной квалификации, а также может быть полезна для студентов и преподавателей соответствующих специальностей.
Разработка приложений в среде Linux. Второе издание - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Поскольку cmd
запускается из оболочки /bin/sh
, то здесь применимы все обычные правила расширения команд. Ниже показан пример вызова system()
, который отображает исходные тексты С из текущего каталога.
#include
#include
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] Хотя функция popen() это делает просто, с ней связаны некоторые побочные эффекты, которые не сразу становятся очевидны. Она создает дочерний процесс, который может быть прерван перед тем, как будет вызвана pclose() , что заставит функцию wait() вернуть состояние процесса. Когда этот процесс завершится, он также сгенерирует SIGCHLD , что может привести в замешательство упрощенно написанный обработчик сигналов.
.
FILE * popen(const char *cmd, const char *mode);
cmd
выполняется через оболочку, как и в system()
. Параметр mode
должен быть "r"
, если родительский процесс желает читать командный вывод, и "w"
— для записи в стандартный ввод дочернего процесса. Следует отметить, что с помощью popen()
делать одновременно чтение и запись нельзя.
Два процесса, которые читают и пишут друг в друга, достаточно сложны [30] Этот тип обработки часто приводит к взаимоблокировкам, при которых процесс А ожидает, пока процесс В выполнит какую-то работу, в то время как процесс В ожидает процесса А, в результате чего ничего не происходит.
и выходят за рамки возможностей popen()
[31] Если вам понадобится делать это, запустите дочерний процесс с помощью fork() и exec() , а потом воспользуйтесь poll() для чтения и записи в дочерний процесс. Для этого предназначена программа под названием expect .
.
popen()
возвращает FILE*
(как это определено в стандартной библиотеке ввода-вывода ANSI/ISO), который может быть прочитан и записан подобно любому другому потоку stdio
[32] Информацию о чтении и записи в поток stdio можно найти в [15].
, либо NULL
, если операция не удается. Когда завершается родительский процесс, он может воспользоваться pclose()
для закрытия потока и прерывания дочернего процесса, если он все еще выполняется. Подобно system()
, pclose()
возвращает состояние дочернего процесса из wait4()
.
int pclose(FILE *stream);
Ниже приведен пример простой программы-калькулятора, которая использует программу bc
для выполнения всей реальной работы. Важно сбрасывать поток, полученный от popen()
, после записи в него, чтобы предотвратить буферизацию stdio
от задержки вывода (подробности о буферизации стандартных функций библиотеки stdio
можно найти в [15]).
1: /*calc.c*/
2:
3: /* Это очень простой калькулятор, который использует внешнюю команду bc
4: для выполнения всей работы. Открывает канал к bc, читает команду,
5: передает ее bc и завершается. */
6: #include
7: #include
8: #include
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: }
Подобно system()
, popen()
запускает команды через системную оболочку и должна использоваться с большой осторожностью, если вызывается из программы со специальными полномочиями.
10.6. Сеансы и группы процессов
В Linux, как и в других системах Unix, пользователи обычно взаимодействуют с группами взаимосвязанных процессов. Хотя изначально они входят через единственный терминал и используют единственный процесс (а именно — оболочку, предоставляющую интерфейс командной строки), пользователи затем запускают множество процессов в результате перечисленных ниже действий.
• Запуск неинтерактивных заданий в фоновом режиме.
• Переключение между интерактивными заданиями с помощью управления заданиями(job control), которое более подробно обсуждается в главе 15.
• Запуск множества процессов, взаимодействующих через программные каналы.
• Запуск оконной системы, вроде X Window System, которая позволяет открывать несколько терминальных окон.
Чтобы управлять всеми этими процессами, ядру необходимо группировать процессы более сложным образом, чем простое отношение "родительский-дочерний", которое мы описали. Этот способ группировки называется сеансамии группами процессов. На рис. 10.1 показано отношение между сеансами, группами процессов и процессами.

Рис. 10.1. Сеансы, группы процессов и процессы
10.6.1. Сеансы
Когда пользователь выходит из системы, ядро должно прервать все процессы, которые пользователь запустил (иначе может остаться множество процессов, которые будут ожидать ввода, а тот никогда не последует). Чтобы упростить эту задачу, процессы организуются в наборы сеансов. Идентификатор сеанса — это то же, что pid процесса, который создает сеанс с помощью системного вызова setsid()
. Этот процесс называют лидером сеанса(session leader) для данной группы процессов. Все потомки процесса являются членами сеанса, если только явно не будут удалены из него. Вызов функции setsid()
не принимает аргументов, а возвращает идентификатор нового сеанса.
Интервал:
Закладка: