|
Программирование >> Структура ядра и системные вызовы
Однако если в командой строке указан символ & , переменная backgrnd этой команды устанавливается в 1. Переменная backgrnd объекта CMD INFOy команды sort имеет значение: backgrnd = 1; Переменная Next используется для привязки другого объекта CMD INFO, команда которого выполняется тем же процессом shell после команды Ij текущего объекта. Это дает возможность пользователям выполнять в командной строке несколько команд, разделяя их символом Командная строка выглядит так: % Is -1; cat < /etc/passwd; date > foo& Объекты CMD INFO, выполняющие эти три команды UNIX, можно представить следующим образом:
Is cat date argv argv argv Если переменная Pipe не равна NULL, то при выполнении команды текущего объекта CMD INFO данные с ее стандартного вывода посредством канала подаются на стандартный ввод объекта CMDINFO, указанного переменной Pipe. Команды обоих объектов, текущего и указанного переменной Pipe, будут выполнены параллельно одним и тем же процессом shell. Таким образом, в команде: % cat -п /etc/motd sort -г &; date объекты CMD INFO, выполняющие эти команды, будут такими: infile= /etc/motd outfile=0 backgrnd=0 Pipe / Next cat argv infile=0 outfile=0 backgrnd=1 . Pipe=0 / Next=0 sort argv infile=0 outfile=0 backgrnd=0 Pipe=0 Next=0 argv Наконец, переменная pSubcmd используется для указания на связный список объектов CMD INFO, чьи команды выполняются во вторичном shell, отдельном от текущего процесса shell. Если pSubcmd не равна NULL, переменная argv того же объекта должна равняться О, так как задачей текущего shell для этой команды является создание вторичного shell, предназначенного для работы с объектами, на которые указывает pSubcmd. Так, в команде: % date; (Is -1 cat -n) > foo S; pwd команды будут выполняться следующими объектами: pSubcmd=0 infile=0 outfile=0 backgrnd=0 Pipe=0 argv Next pSubcmd=0 infile=0 outfile= foo backgrnd=1 Pipe=0 argv=0 Next pSubcmd=0 infile=0 outfile=0 backqrnd=0 Pipe - /argv / Next=0 date Ipwd pSubcmd=0 infile=0 outfile=0 backgrnd=0 Pipe=0 ArNext=0 Is pSubcmd=0 infile=0 outfile=0 backqrnd=0 Pipe=0 / NexVo cat В приведенном ниже заголовке shell.h объявляются класс CMD INFO и его функции-члены: I* это файл заголовков shell.h, в котором объявляется класс CMD INFO */ #ifndef SHELL H fdefine SHELL H finclude <iostream.h> finclude <string.h> finclude <assert.h> finclude <malloc.h> I* проверить переназначения ввода-вывода командных каналов */ ♦define CHECK IO(fn) if (fn) { \ cerr < Invalid ee-direct: fn endl; delete fn; fn = 0; ) class CMD INFO { public: char** argv; char* ,.,ц infile; char* outfile; int backgrnd; CMD INFO* pSubcmd; CMD INFO* Pipe; iCMD INFO*. Next; список команд и аргументов переназначенный файл стандартного ввода переназначенный файл стандартного вывода 1, если команда должна быть выполнена в фоновом режиме команды, выполняемые во вторичном shell следующая команда после I следующая команда после ; конструктор CMD INFO() ( argv = 0; infile = outfile = 0; backgrnd = 0; pSubcmd = Pipe = Next *= от деструктор ~CMD INFO() if (infile) delete infile; if (outfile) delete outfile; for (int i=0; argv && argv(i]; i++) delete argv(i]; delete argv; добавить одну строку аргументов в argv , void add arg( char* str ) int len = 1; if (!argv) fargv = (char**)malloc(sizeof(char*)*2); else { ,g;9 . while (аг.ду(Деп]) len++; len++; argv = (char**)realloc(argv,sizeof(char*)*(len+1)); ) assert(argv[len-l) = strdup(str)); argv(len] = 0; добавить имя переназначенного файла стандартного ввода или вывода void add iofile( char*& iofile, char* fnm ) if (iofile) cerr Multiple in-directj iofile vs <Je fnm endl; else iofile = fnm; - i, i. добавить командный канал void add pipe ( CMD INFO* pCmd ) ( if (Pipe) Pipe->add pipe(pCmd); else ( CHECK IO (outfile) ; CHECK IO(pCmd->infile); Pipe = pCmd; ); добавить следующую команду void add next( CMD INFO* pCmd ) ( if (Next) Next->add next(pCmd); else Next = pCmd; extern void exec cmd( CMD INFO *pCmd ); extern C int yyparseO; fendif Функция-конструктор CMD INFO::CMD INFO инициализирует все переменные вновь созданного объекта нулями. Функция-деструктор ~CMD INFO::CMD INFO освобождает динамическую память, используемую переменными argv, infile и outfile объекта, подлежащего удалению. Функция CMD INFO.\flc( fl/ вызывается для добавления лексем, составляющих команду shell, в переменную argv объекта. Эта функция использует функции динамического распределения памяти malloc и realloc для установки размера argv в соответствии с фактическим числом лексем, составляющих команду. функция CMD INFO. addjofi/e вызывается для добавления имени файла (указанного в аргументе fnm) в переменную infile или outfile объекта (указанную в аргументе iofile). Этот файл используется для переназначения стандартного ввода или вывода процесса, который будет создан для выполнения команды объекта. Функция CMD lNFO ::add next добавляет объект CMDINFO в конец связного списка Next объекта. Связный список Next задает набор команд, подлежащих выполнению в порядке имеющихся в списке записей. Функция CMD lNFO::add pipe добавляет объект CMDJNFO в конец связного списка Pipe объекта. Связный список Pipe задает набор команд, выполняемых параллельно; при этом стандартный вывод одной команды соединяется каналом со стандартным вводом следующей в списке Pipe команды. Эта функция следит и за тем, чтобы объект CMDINFO не передавал данные в канал одновременно с переназначением стандартного вывода в файл. Аналогичным образом объект CMD INFO не может принимать данные из канала и в то же время перенаправлять свой стандартный ввод в файл. После определения класса CMDJNFO программа minishell производит синтаксический анализ каждой вводимой строки команды и создает еще один или несколько связных списков объектов CMD INFO для представления соответствующих команд из входной строки. Анализирующая функция minishell состоит из лексического анализатора и синтаксического анализатора, создаваемых с помощью lex и уасс. В частности, лексический анализатор, распознающий лексемы командной строки, строится из исходного файла lex следующим образом: %{/* shell.1: исходный файл лексического анализатора lex для minishell */ tinclude <string.h> finclude shell.h ♦include y.tab.h %) %% ;[\t\v]*\n return \n; /* пропустить ; в конце строки */ [\t\v]*\n ; /* пропустить пустые строки */ ♦[ VnJXn ; /* пропустить строки комментариев */ ♦[ Vn)* ; /* пропустить встроенные комментарии */ [\t\v] . ; /* пропустить пробельные символы */ [A-Za-z 0-9/, { yylval.s = strdup (yytext) ; return NAME; /* возвратить символьную лексему */ - /* односимвольная лексема */- \п return yytext[0]; ./* программа завершения анализа команд */ int yywrapO { return 1; } Основное назначение лексического анализатора сбор лексем NAME и специальных символов, таких как < , > , , ( , ) и которые образуют одну или более команд shell в каждой вводимой строке. Лексема NAME состоит из одного или более буквенно-цифровых символов, а также символов , и / . Это может быть имя команды shell, ключ или аргумент команды. После обнаружения лексемы NAME лексический анализатор возвращает синтаксическому анализатору символьную строку лексемы (с помощью глобальной переменной yylvat) и идентификатор лексемы NAME, который определяется в y.tab.h (созданный из исходного файла уасс). Специальные символы shell < , > , , ( и ) возвращаются синтаксическому анализатору как таковые. В дополнение к сказанному отметим, что лексический анализатор игнорирует также комментарии (комментарий начинается символом # и заканчивается символом новой строки), пробельные символы, пустые строки и необязательный символ ; в конце входной строки. Наконец, функция уушар определяется в соответствии с требованиями программы lex. Эта функция вызывается, когда лексический анализатор в потоке ввода встречает признак конца файла. Функция дает указание лексическому анализатору прекратить просмотр потока ввода путем возврата единицы, чтобы синтаксический анализатор (а значит, и программа mini-shell) остановился. Синтаксический анализатор minishell предполагает, что все вводимые данные состоят из одной или более командных строк. Каждая командная строка заканчивается символом новой строки, и для ее выполнения анализатор вызывает порожденный процесс. Кроме того, командная строка может состоять из одной или более команд, разделенных символом ; . Порожденный процесс выполняет данные команды в порядке их следования. Любая из этих команд может выполняться в фоновом режиме, если в конце ее указан символ & . Эти синтаксические правила могут быть сформулированы следующим образом: <input stream> ::= [ <cmd line> Vn }+ <cmd line> ::= <shell [ & ] [ ; <shell> [&}] + Команда shell может быть простой, с вводом-выводом в канал или сложной: <shell> ::= <basic> <pipe> <complex> Простая команда состоит из имени, необязательных ключей и аргументов, а также обладает возможностью переназначения ввода и (или) вывода. Синтаксис такой команды: <basic> ::=<cmd> [<switch>]* [<arg>]* [< <file>} [> <file>] Ниже даны два примера простых команд: Is -1 /etc/passwd cat -n < srcfile > destfile
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |