Книга: Операционная система 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) и приостанавливает свое выполнение до завершения работы программы, после чего на экран вновь выводится приглашение.

Оглавление книги


Генерация: 0.713. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз