Книга: Операционная система UNIX
Командный интерпретатор
Командный интерпретатор
Для примера интерактивного приложения, мы выбрали простейший командный интерпретатор. Данный пример позволяет продемонстрировать использование системных вызовов для порождения процесса, запуска программы и синхронизации выполнения процессов.
Функции приведенного командного интерпретатора сведены к минимуму: он распознает и выполняет несколько встроенных команд, остальной ввод он расценивает как внешние программы, которые и пытается запустить с помощью системного вызова 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);
write(2, "shell: cannot execute", 21);
} else
/* Родительский процесс */
/* Ожидаем завершения выполнения программы */
wait(&stat_lock);
break;
}
}
}
Предложенный командный интерпретатор работает в бесконечном цикле, запрашивая ввод пользователя и анализируя строку с помощью функции parse_command()
, текст которой здесь не приведен. В случае, если пользователь ввел встроенную команду интерпретатора, он выполняет команду собственными силами. В противном случае shell порождает дочерний процесс, который с помощью вызова execve(2) запускает указанную программу. В это время родительский процесс выполняет системный вызов wait(2) и приостанавливает свое выполнение до завершения работы программы, после чего на экран вновь выводится приглашение.
- Командный интерпретатор shell
- Глава 22 Командный интерпретатор bash
- Глава 3 Возможности интерпретатора shell
- 7.8 КОМАНДНЫЙ ПРОЦЕССОР SHELL
- Подстановки, выполняемые командным интерпретатором
- 16.2. Простой интерпретатор программ, управляемых образцами
- Часть III Как реализовать командный потенциал
- Интерпретаторы
- 18. Читаем, пишем, считаем, или Конструирование интерпретатора форматов
- 14. Лекция: Устройство интерпретатора языка Python.
- Пример описания интерпретатора
- 15.6.1. Миниатюрный интерпретатор языка AL0