Майкл Джонсон - Разработка приложений в среде Linux. Второе издание
- Название:Разработка приложений в среде Linux. Второе издание
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:2007
- Город:Москва
- ISBN:978-5-8459-1143-8
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Майкл Джонсон - Разработка приложений в среде Linux. Второе издание краткое содержание
Книга известных профессионалов в области разработки коммерческих приложений в Linux представляет собой отличный справочник для широкого круга программистов в Linux, а также тех разработчиков на языке С, которые перешли в среду Linux из других операционных систем. Подробно рассматриваются концепции, лежащие в основе процесса создания системных приложений, а также разнообразные доступные инструменты и библиотеки. Среди рассматриваемых в книге вопросов можно выделить анализ особенностей применения лицензий GNU, использование свободно распространяемых компиляторов и библиотек, системное программирование для Linux, а также написание и отладка собственных переносимых библиотек. Изобилие хорошо документированных примеров кода помогает лучше усвоить особенности программирования в Linux.
Книга рассчитана на разработчиков разной квалификации, а также может быть полезна для студентов и преподавателей соответствующих специальностей.
Разработка приложений в среде Linux. Второе издание - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Программы, которые не прерываются по сигналу SIGHUP
, получают сигнал SIGCONT
, который продолжает выполнение приостановленных процессов. Такая последовательность прерывает большинство процессов и обеспечивает оставшимся возможность работать (то есть гарантирует, что они не будет в приостановленном состоянии) [35] Обсуждение станет более понятным после того, как вы прочитаете главы, посвященные сигналам (глава 12) и управлению заданиями (глава 15).
.
Как только процесс становится висячим, он принудительно отключается от своего управляющего терминала (позволяя новому пользователю при необходимости применять этот терминал). Если продолжающие работать программы пытаются получить доступ к терминалу, эти попытки вызывают ошибки, устанавливающие errno
в значение EIO
. Процессы остаются в том же сеансе, и идентификатор сеанса не используется для новых идентификаторов процессов до тех пор, пока не завершатся все процессы данного сеанса.
10.7. Введение в ladsh
Чтобы помочь проиллюстрировать идеи, обсуждаемые в нашей книге, на протяжении последующих разделов книги мы разработаем подмножество командной оболочки Unix. В конечном итоге наша оболочка будет поддерживать следующее.
• Простые встроенные команды.
• Запуск внешних команд.
• Перенаправление ввода-вывода ( >
, |
и так далее).
• Управление заданиями.
Полный исходный текст окончательной версии этой оболочки, ladsh4.с
, представлен в приложении Б. По мере добавления в ladsh
новых средств, изменения исходного текста описываются в тексте книги. Чтобы уменьшить количество изменений, которые мы вносим между версиями, некоторые ранние версии несколько более сложны, чем было бы нужно. Эти небольшие усложнения, однако, далее в книге упрощают разработку оболочки, поэтому будьте терпеливы. Просто пока поверьте, что эти фрагменты кода необходимы; все они будут объяснены позднее.
10.7.1. Запуск внешних программ с помощью ladsh
Вот первая (и самая простая) версия ladsh
, называемая ladsh1
.
1: /*ladsh1.c*/
2:
3: #include
4: #include
5: #include
6: #include
7: #include
8: #include
9: #include
10: #include
11: #include
12: #include
13:
14: #define MAX_COMMAND_LEN 250 /* максимальная длина отдельной
15: командной строки */
16: #define JOB_STATUS_FORMAT "[%d]%-22s%.40s\n"
17:
18: struct jobSet {
19: struct job *head; /* заголовок списка запущенных заданий */
20: struct job *fg; /* текущее задание переднего плана */
21: };
22:
23: struct childProgram {
24: pid_t Pid; /* 0 на выходе */
25: char **argv; /* имя программы с аргументами */
26: };
27:
28: struct job {
29: int job Id; /* номер задания */
30: int numProgs; /* общее кол-во программ в задании */
31: int runningProgs; /* кол-во работающих программ */
32: char *text; /* имя задания */
33: char *cmdBuf; /* буфер различных argv */
34: pid_t pgrp; /* идентификатор группы процессов задания */
35: struct childProgram *progs; /* массив программ в задании */
36: struct job *next; /* для слежения за фоновыми программами */
37: };
38:
39: void freeJob(struct job *cmd) {
40: int i;
41:
42: for (i=0; inumProgs; i++) {
43: free (cmd->progs[i].argv);
44: }
45: free(cmd->progs);
46: if (cmd->text) free(cmd->text);
47: free(cmd->cmdBuf);
48: }
49:
50: int getCommand(FILE *source, char *command) {
51: if (source == stdin) {
52: printf("#");
53: fflush(stdout);
54: }
55:
56: if (!fgets(command, MAX_COMMAND_LEN, source)) {
57: if (source==stdin) printf("\n");
58: return 1;
59: }
60:
61: /* удалить завершающий перевод строки */
62: command[strlen(command) - 1] = '\0';
63:
64: return 0;
65: }
66:
67: /* Возвратить cmd->numProgs как 0, если нет никаких команд (то есть пустая
68: строка). Если найдена правильная команда, commandPtr устанавливается в
69: указатель на начало следующей команды (если исходная команда имеет более
70: одного задания, ассоциированного с ней) или NULL, если
71: больше нет команд.*/
72: int parseCommand(char **commandPtr, struct job *job, int *isBg) {
73: char *command;
74: char *returnCommand = NULL;
75: char *src, *buf;
76: int argc = 0;
77: int done = 0;
78: int argvAlloced;
79: char quote = '\0';
80: int count;
81: struct childProgram *prog;
82:
83: /* Пропустить ведущие пробелы */
84: while(**commandPtr && isspace(**commandPtr)) (*commandPtr)++;
85:
86: /* здесь обрабатываются пустые строки и ведущие символы '#' */
87: if (!**commandPtr || (**commandPtr=='#')) {
88: job->numProgs = 0;
89: *commandPtr = NULL;
90: return 0;
91: }
92:
93: *isBg = 0;
94: job->numProgs = 1;
95: job->progs = malloc(sizeof(*job->progs));
96:
97: /* Мы устанавливаем элементы argv в указатели внутри строки.
98: Память освобождается freeJob().
99:
100: Получение чистой памяти позволяет далее иметь дело с
101: NULL-завершающимися вещами и делает все остальное немного
102: яснее (к тому же, это добавляет эффективности) */
103: job->cmdBuf = command = calloc(1, strlen(*commandPtr) + 1);
104: job->text = NULL;
105:
106: prog = job->progs;
107:
108: argvAlloced = 5;
109: prog->argv = malloc(sizeof(*prog->argv) * argvAlloced);
110: prog->argv[0] = job->cmdBuf;
111:
112: buf = command;
113: src = *commandPtr;
114: while (*src && !done) {
115: if (quote==*src) {
116: quote='\0';
117: } else if (quote) {
118: if (*src == '\\') {
119: src++;
120: if (!*src) {
121: fprintf(stderr,
122: "ожидается символ после\\\n");
123: freeJob(job);
124: return 1;
125: }
126:
127: /* в оболочке, "\'" должно породить \' */
128: if (*src != quote) *buf++='\\';
129: }
130: *buf++ = *src;
131: } else if (isspace(*src)) {
132: if (*prog->argv[argc]) {
133: buf++, argc++;
134: /* +1 здесь оставляет место для NULL,
135: которым завершается argv */
136: if ((argc+1) == argvAlloced) {
137: argvAlloced += 5;
138: prog->argv = realloc(prog->argv,
139: sizeof(*prog->argv)*argvAlloced);
140: }
141: prog->argv[argc]=buf;
142: }
143: } else switch(*src) {
144: case '"':
145: case '\'':
146: quote = *src;
147: break;
148:
149: case '#' : /* комментарий */
150: done=1;
151: break;
152:
153: case '&': /* фоновый режим */
154: *isBg = 1;
155: case ';': /* множественные команды */
156: done=1;
157: return Command = *commandPtr + (src - *commandPtr) + 1;
158: break;
159:
160: case '\\' :
161: src++;
Интервал:
Закладка: