Читать книгу 📗 "Операционная система UNIX - Робачевский Андрей Михайлович"
Последний тип сообщений подсказывает еще одну возможность использования системного журнала — для отладки программ, особенно неинтерактивных.
Строка
logstring%merrnoФункция openlog(3) позволяет определить ряд опций ведения журнала. Она имеет следующее определение:
void openlog(char *ident, int logopt, int facility);Строка
identlogoptLOG_PID | Позволяет указывать идентификатор процесса в каждом сообщении. Эта опция полезна при журналировании нескольких демонов с одним и тем же значением ident, например, когда демоны порождаются вызовом fork(2). |
LOG_CONS | Позволяет выводить сообщения на консоль при невозможности записи в журнал. |
Наконец, аргумент
facilityLOG_KERN | Указывает, что сообщения отправляются ядром. |
LOG_USER | Указывает, что сообщения отправлены прикладным процессом (используется по умолчанию). |
LOG_MAIL | Указывает, что инициатором сообщений является система электронной почты. |
LOG_DAEMON | Указывает, что инициатором сообщений является системный демон. |
LOG_NEWS | Указывает, что инициатором сообщений является система телеконференций USENET. |
LOG_CRON | Указывает, что инициатором сообщений является система cron(1). |
Закончив работу с журналом, следует аккуратно закрыть его с помощью функции closelog(3):
void closelog(void);Командный интерпретатор
Для примера интерактивного приложения, мы выбрали простейший командный интерпретатор. Данный пример позволяет продемонстрировать использование системных вызовов для порождения процесса, запуска программы и синхронизации выполнения процессов.
Функции приведенного командного интерпретатора сведены к минимуму: он распознает и выполняет несколько встроенных команд, остальной ввод он расценивает как внешние программы, которые и пытается запустить с помощью системного вызова exec(2).
#include <sys/types.h>#include <sys/wait.h>#include <unistd.h>extern char** environ;#define CMDSIZE 80/* Встроенные команды интерпретатора */#define CD 1#define ECHO 2#define EXEC 3 ...#define PROGRAM 1000/* Функция, которая производит анализ строки, введенной пользователем, выполняет подстановки и определяет, встроенная ли это команда или программа. В качестве аргумента функция принимает строку cmdbuf, введенную пользователем, и возвращает имя команды/программы path и переданные ей параметры arguments. Возвращаемое значение указывает на внутреннюю команду или внешнюю программу, которую необходимо запустить.*/int parse_command(char* cmdbuf, char* path, char** arguments);main { charcmd[CMDSIZE]; int command; int stat_loc; char** args; char cmdpath[MAXPATH]; while (1) { /* Выведем сообщение интерпретатора */ write(1, "$ ", 2); /* Считаем ввод пользователя и проанализируем строку */ cmdsize = read(0, cmd, CMDSIZE); cmd[cmdsize-1] =' '; command = parse_command(cmd, cmdpath, args); switch(command) { /* Если это внутренняя команда, обработаем ее */ case (CD): chdir(args[0]); break; case(ECHO): write(1, args[0], strlen(args[0])); break; case(EXEC): execve(path, args, environ); write(2, "shell: cannot execute", 21); break; ... /* Если это внешняя программа, создадим дочерний процесс, который и запустит программу */ case(PROGRAM): pid = fork(); if (pid < 0) write(2, "shell: cannot fork", 18); else if (pid == 0) { /* Дочерний процесс */ execve(path, args, environ);