Читать интересную книгу Основы программирования в Linux - Мэтью Нейл

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 204 205 206 207 208 209 210 211 212 ... 324

$ <b>./upper &lt; file.txt</b>

THIS IS THE FILE, FILE.TXT, IT IS ALL LOWER CASE.

Что если вы хотите применить этот фильтр из другой программы? Программа useupper.c принимает имя файла как аргумент и откликается сообщением об ошибке при некорректном вызове:

#include &lt;unistd.h&gt;

#include &lt;stdio.h&gt;

#include &lt;stdlib.h&gt;

int main(int argc, char *argv[]) {

 char *filename;

 if (argc != 2) {

  fprintf (stderr, &quot;usage: useupper filen&quot;);

  exit(1);

 }

 filename = argv[1];

Вы повторно открываете стандартный ввод, снова при этом проверяете наличие любых ошибок, а затем применяете функцию execl для вызова программы upper:

 if (!freopen(filename, &quot;r&quot;, stdin)) {

  fprintf(stderr, &quot;could not redirect stdin from file %sn&quot;, filename);

  exit(2);

 }

 execl(&quot;./upper&quot;, &quot;upper&quot;, 0);

He забудьте, что execl заменяет текущий процесс, если ошибок нет, оставшиеся строки не выполняются.

 perror(&quot;could not exec ./upper&quot;);

 exit(3);

}

Как это работает

Когда вы выполняете эту программу, ей можно передать файл для преобразования в прописные буквы. Работа делается программой upper, которая не обрабатывает аргументы с именами файлов. Обратите внимание на то, что вам не нужен исходный код программы upper; таким способом можно запустить любую исполняемую программу.

$ <b>./useupper file.txt</b>

THIS IS THE FILE, FILE.TXT, IT IS ALL LOWER CASE.

Программа useupper применяет freopen для закрытия стандартного ввода и связывания потока файла с файлом, заданным как аргумент программы. Затем она вызывает execl, чтобы заменить код выполняемого процесса кодом программы upper. Поскольку файловые дескрипторы сохраняются, пройдя сквозь вызов execl, программа upper выполняется так же, как при вводе ее в строке командной оболочки

$ <b>./upper &lt; file.txt</b>

Потоки 

Процессы Linux могут взаимодействовать, отправлять друг другу сообщения и прерываться друг другом. Они могут даже организоваться и совместно использовать сегменты памяти, но они остаются обособленными объектами операционной системы. Процессы не настроены на совместное использование переменных.

Существует класс процесса, именуемый потоком (thread), который доступен во многих системах UNIX и Linux. Несмотря на то, что потоки трудно, программировать, они могут быть очень важны для некоторых приложений, таких как многопоточные серверы баз данных. Программирование потоков в Linux (и вообще в UNIX) не так распространено, как применение множественных процессов, поскольку процессы Linux очень легко применять и программирование множественных взаимодействующих процессов гораздо легче программирования потоков. Потоки обсуждаются в главе 12.

Сигналы

Сигнал — это событие, генерируемое системами UNIX и Linux в ответ на некоторую ситуацию, получив сообщение о котором процесс, в свою очередь, может предпринять какое-то действие. Мы применяем термин "возбуждать" (raise) для обозначения генерации сигнала и термин "захватывать" (catch) для обозначения получения или приема сигнала. Сигналы возбуждаются некоторыми ошибочными ситуациями, например нарушениями сегментации памяти, ошибками процессора при выполнении операций с плавающей точкой или некорректными командами. Они генерируются командной оболочкой и обработчиками терминалов для вызова прерываний и могут явно пересылаться от одного процесса к другому как способ передачи информации или коррекции поведения. Во всех этих случаях программный интерфейс один и тот же. Сигналы могут возбуждаться, улавливаться и соответственно обрабатываться или (по крайней мере, некоторые) игнорироваться.

Имена сигналов задаются с помощью включенного заголовочного файла signal.h. Они начинаются с префикса SIG и включают приведенные в табл. 11.3 сигналы.

Таблица 11.3

Имя сигнала Описание SIGABORT *Процесс аварийно завершается SIGALRM Сигнал тревоги SIGFPE *Исключение операции с плавающей точкой SIGHUP Неожиданный останов или разъединение SIGILL *Некорректная команда SIGINT Прерывание терминала SIGKILL Уничтожение (не может быть перехвачен или игнорирован) SIGPIPE Запись в канал без считывателя SIGQUIT Завершение работы терминала SIGSEGV *Некорректный доступ к сегменту памяти SIGTERM Завершение, выход SIGUSR1 Сигнал 1, определенный пользователем SIGUSR2 Сигнал 2, определенный пользователем

*Могут быть также предприняты действия, зависящие от конкретной реализации.

Если процесс получает один из этих сигналов без предварительной подготовки к его перехвату, процесс будет немедленно завершен. Обычно при этом создается файл с дампом ядра. Этот файл в текущем каталоге, названный core, представляет собой образ процесса, который может оказаться полезным при отладке.

К дополнительным относятся сигналы, приведенные в табл. 11.4.

Таблица 11.4

Имя сигнала Описание SIGCHLD Дочерний процесс остановлен или завершился SIGCONT Продолжить выполнение, если процесс был приостановлен SIGSTOP Остановить выполнение (не может захватываться или игнорироваться) SIGTSTP Сигнал останова, посылаемый с терминала SIGTTIN Фоновый процесс пытается читать SIGTTOU Фоновый процесс пытается писать
1 ... 204 205 206 207 208 209 210 211 212 ... 324
На этом сайте Вы можете читать книги онлайн бесплатно русская версия Основы программирования в Linux - Мэтью Нейл.

Оставить комментарий