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

ЖАНРЫ

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

Троан Эрик В.

Шрифт:

Наиболее удобным способом является установка флага закрытия после выполнения для каждого файла, который программа оставляет открытым на длительный период времени (включая сокеты и файловые устройства), что предотвращает получение доступа к данным файлам новыми запускаемыми программами. Описание флага закрытия после выполнения можно найти в главе 11.

22.4. Запуск в качестве демона

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

1. Большинство действий по инициализации должны быть произведены до того, как программа становится фактическим демоном. Это гарантирует, что пользователь при

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

2. Текущий каталог должен быть изменен на какой-либо подходящий. Это может быть корневой каталог, но никогда не может быть тот каталог, из которого была запущена программа. Если демон этого не сделает, то, возможно, он будет работать соответствующим образом, но это не позволяет удалить тот каталог, из которого он был активизирован, поскольку он остается текущим каталогом программы. Если это возможно, то неплохо применить

chroot
на какой-то каталог. Причины обсуждались ранее в этой главе.

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

4. Затем программа должна вызвать

fork
, а родительский процесс должен вызвать
exit
, позволяя программе, запустившей демон (чаще всего командному процессору), продолжить работу.

5. Дочерний процесс, продолжающий работу, должен закрыть stdin, stdout и stderr, поскольку он не будет больше использовать терминал. Вместо повторного применения файловых дескрипторов 0, 1 и 2 лучше открывать эти файлы как

/dev/null
. Это гарантирует, что ни одна библиотечная функция, передающая отчеты о состоянии ошибок в stdout или stderr, не запишет эти ошибки в другие файлы, открытые демоном. При этом демон сможет запускать внешние программы, не беспокоясь об их выходных данных.

6. Для полного разъединения с терминалом, из которого был запущен демон, он должен вызвать

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

Библиотека С предлагает функцию

daemon
, которая обрабатывает некоторые из перечисленных задач.

int daemon(int nochdir, in tnoclose);

Данная функция сразу осуществляет ветвление, и если оно прошло успешно, родительский процесс вызывает

_exit
с кодом завершения 0. Затем дочерний процесс переходит в корневой каталог, если
nochdir
не является нулем, и перенаправляет stdin, stdout и stderr в
/dev/null
, если
noclose
не равен нулю. Перед возвратом в дочерний процесс она также вызывает
setsid
. При этом унаследованные файловые дескрипторы все равно могут оставаться открытыми, поэтому в программах, использующих
daemon
, необходимо следить за ними. Если возможно, в программе также нужно использовать
chroot
.

Часть IV

Библиотеки для разработки

Глава 23

Сопоставление строк

Осуществлять сравнение строк можно не только с помощью функции

strcmp
или даже
strncmp
. Linux предлагает несколько общих функций сопоставления строк, использование которых позволяет упростить решение задач программирования. Мы рассмотрим сначала самые простые примеры, а затем перейдем к более сложным.

23.1. Универсализация произвольных строк

В главе 14 мы говорили о том, как с помощью функции

glob
производится универсализация имен файлов, однако пользователи, знакомые с возможностями универсализации, нередко пытаются применить их и к другим разновидностям строк. Функция
fnmatch
позволяет применять правила универсализации в отношении произвольных строк:

#include <fnmatch.h>

int fnmatch(const char * pattern, const char * string, int flags);

Предложенный

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

*
Соответствует любой строке, включая пустую.
?
Соответствует любому одиночному символу.
[
Начинает список символов для сопоставления или, если следующим символом является
^
, то список символов для несовпадения. Весь список может совпадать, или не совпадать с одним символом. Список заканчивается знаком
]
.
\
Следующий символ будет интерпретироваться как литерал, а не как специальный символ.

На результаты универсализации влияет аргумент

flags
, и здесь он будет полезен, прежде всего, для универсализации имен файлов. Если вы не будете осуществлять универсализацию имен файлов, то вам, скорее всего, нужно будет присвоить аргументу
flags
значение
0
.

FNM_NOESCAPE
Обработка символа
\
как обычного, а не специального символа.
FNM_PATHNAME
Символы
/
в строке
string
не сопоставляются с последовательностью
*
,
?
, или даже
[/]
в шаблоне
pattern
; сопоставление производится только с литералом, а не специальным символом
/
.
FNM_NOESCAPE
Первый символ
.
в шаблоне pattern соответствует символу
.
в строке
string
только в том случае, если он является первым символом в строке
string
или если задано значение
FNM_PATHNAME
, а символ
.
в
string
непосредственно следует за символом
\
.

Функция

fnmatch
возвращает нулевое значение, если шаблон соответствует строке,
FNM_NOMATCH
, если шаблон не соответствует строке, или другое неопределенное значение в случае возникновения ошибки.

Пример использования функции

fnmatch
вы можете посмотреть в программе, приведенной в разделе 14.7.3 главы 14, в которой эта функция используется как часть простой реализации команды
find
.

23.2. Регулярные выражения

Регулярные выражения, используемые в программах

sed
,
awk
,
grep
,
vi
, а также во множестве других программ Unix, со временем приобрели большое значение в среде программирования Unix. Регулярные выражения можно применять и при написании программ на языке С. В этом разделе будет рассказано об их использовании и будет предложен пример простой программы синтаксического анализа файла, построенной на этих функциях.

23.2.1. Регулярные выражения в Linux

Существуют две разновидности регулярных выражений: базовые регулярные выражения (basic regular expression — BRE) и расширенные регулярные выражения (extended regular expression — ERE). Они соответствуют (в первом приближении) командам grep и egrep. Описание каждой разновидности регулярных выражений можно найти на man-странице grep, в стандарте POSIX.2 (IEEE, 1993), в [32], а также в других источниках, поэтому здесь мы не станем описывать их синтаксис, а рассмотрим только интерфейс функции, с помощью которой вы сможете применять регулярные выражения в своих программах.

Поделиться с друзьями: