ляющиеся частью "ядра" в других системах. Такие функции, и среди них компи-
ляторы и редакторы, в системе UNIX являются программами
пользовательского
уровня. Наиболее характерным примером подобной программы может служить ко-
мандный процессор shell, с которым обычно взаимодействуют пользователи
после
входа в систему. Shell интерпретирует первое слово командной строки как
имя
команды: во многих командах, в том числе и в командах fork (породить
новый
процесс) и exec (выполнить порожденный процесс), сама команда
ассоциируется
с ее именем, все остальные слова в командной строке трактуются как
параметры
команды.
Shell обрабатывает команды трех типов. Во-первых, в качестве имени
команды может быть указано имя исполняемого файла в объектном коде,
полученного в результате компиляции исходного текста программы (например,
программы
на языке Си). Во-вторых, именем команды может быть имя командного файла, со-
держащего набор командных строк, обрабатываемых shell'ом. Наконец,
команда
может быть внутренней командой языка shell (в отличие от исполняемого
файла). Наличие внутренних команд делает shell языком программирования в
дополнение к функциям командного процессора; командный язык shell включает
команды организации циклов (for-in-do-done и while-do-done), команды
выполнения по условиям (if-then-else-fi), оператор выбора, команду
изменения текущего для процесса каталога (cd) и некоторые другие.
Синтаксис shell'а допускает сравнение с образцом и обработку параметров.
Пользователям, запускающим команды, нет необходимости знать, какого типа
эти команды.
Командный процессор shell ищет имена команд в указанном наборе катало-
гов, который можно изменить по желанию пользователя, вызвав shell.
Shell
обычно исполняет команду синхронно, с ожиданием завершения выполнения коман-
ды прежде, чем считать следующую командную строку. Тем не менее,
допускается
и асинхронное исполнение, когда очередная командная строка считывается и ис-
полняется, не дожидаясь завершения выполнения предыдущей команды. О коман-
дах, выполняемых асинхронно, говорят, что они выполняются на фоне других ко-
манд. Например, ввод команды
who
вызывает выполнение системой программы, хранящейся в файле /bin/who
((((() и осуществляющей вывод списка пользователей, которые в настоящий
момент работают с системой. Пока команда who выполняется, командный
процессор shell ожидает завершения ее выполнения и только затем
запрашивает у пользователя следующую команду. Если же ввести команду
who &
система выполнит программу who на фоне и shell готов немедленно принять сле-
дующую команду.
В среду выполнения каждого процесса в системе UNIX включается
текущий
каталог. Текущий для процесса каталог является начальным каталогом, имя ко-
торого присоединяется ко всем именам путей поиска, которые не начинаются
с
наклонной черты. Пользователь может запустить внутреннюю команду shell'а
cd
(изменить каталог) для перемещения по дереву файловой системы и для
смены
текущего каталога. Командная строка
cd /usr/src/uts
делает текущим каталог "/usr/src/uts". Командная строка
cd ../..
делает текущим каталог, который на две вершины "ближе" к корню
(корневому
каталогу): параметр ".." относится к каталогу, являющемуся родительским
для
текущего.
Поскольку shell является пользовательской программой и не входит в
состав ядра операционной системы, его легко модифицировать и помещать в
конкретные условия эксплуатации. Например, вместо командного процессора
Баурна
(называемого так по имени его создателя, Стива Баурна), являющегося
частью
версии V стандартной системы, можно использовать процессор команд Си, обес-
печивающий работу механизма ведения истории изменений и позволяющий збегать
повторного ввода только что использованных команд. В некоторых случаях
при
желании можно воспользоваться командным процессором shell с
ограниченными
возможностями, являющимся предыдущей версией обычного shell'а. Система
может
работать с несколькими командными процессорами одновременно.
Пользователи
имеют возможность запускать одновременно множество процессов, процессы же
в
свою очередь могут динамически порождать новые процессы и
синхронизировать
их выполнение. Все эти возможности обеспечиваются благодаря наличию
мощных
программных и аппаратных средств, составляющих среду выполнения
процессов.
Хотя привлекательность shell'а в наибольшей степени определяется его
возможнос-тями как языка программирования и его возможностями в обработке
аргументов, в данном разделе основное внимание концентрируется на среде
выполнения процес-сов, управление которой в системе возложено на
командный процессор Shell.
3.3 Элементы конструкционных блоков
Как уже говорилось ранее, концепция разработки системы UNIX
заключалась
в построении операционной системы из элементов, которые позволили бы пользо-
вателю создавать небольшие программные модули, выступающие в качестве конст-
рукционных блоков при создании более сложных программ. Одним из таких эле-
ментов, с которым часто сталкиваются пользователи при работе с
командным
процессором shell, является возможность переназначения ввода-вывода.
Говоря
условно, процессы имеют доступ к трем файлам: они читают из файла стандарт-
ного ввода, записывают в файл стандартного вывода и выводят сообщения
об
ошибках в стандартный файл ошибок. Процессы, запускаемые с терминала,
обычно
используют терминал вместо всех этих трех файлов, однако каждый файл незави-
симо от других может быть "переназначен". Например, команда
ls
выводит список всех файлов текущего каталога на устройство (в файл) стандар-
тного вывода, а команда
ls > output
переназначает выводной поток со стандартного вывода в файл "output" в теку-
щем каталоге, используя вышеупомянутый системный вызов creat. Подобным
же
образом, команда
mail mjb < letter
открывает (с помощью системного вызова open) файл "letter" в качестве
файла
стандартного ввода и пересылает его содержимое пользователю с именем
"mjb".
Процессы могут переназначать одновременно и ввод, и вывод, как, например,
в
командной строке:
nroff -mm < doc1 > doc1.out 2> errors
где программа форматирования nroff читает вводной файл doc1, в качестве фай-
ла стандартного вывода задает файл doc1.out и выводит сообщения об ошибках
в
файл errors ("2>" означает переназначение вывода, предназначавшегося
для файла с дескриптором 2, который соответствует стандартному файлу
ошибок).Програм-мы ls, mail и nroff не знают, какие файлы выбраны в
качестве файлов стандартного ввода, стандартного вывода и записи
сообщений об ошибках; командный процессор shell сам распознает символы "" и "2>" и назначает в соответствии с их указанием файлы для стандартного
ввода, стандартного вывода и записи сообщений об ошибках непосредственно
перед запуском процессов.
Вторым конструкционным элементом является канал, механизм, обеспечиваю-
щий информационный обмен между процессами, выполнение которых связано с
операциями чтения и записи. Процессы могут переназначать выводной
поток со
стандартного вывода на канал для чтения с него другими процессами, переназ-
начившими на канал свой стандартный ввод. Данные, посылаемые в канал
первыми
процессами, являются входными для вторых процессов. Вторые процессы так
же
могут переназначить свой выводной поток и так далее, в зависимости от
пожеланий программиста. И снова, так же как и в вышеуказанном случае,
процессам нет необходимости знать, какого типа файл используется в
качестве файла
стандартного вывода; их выполнение не зависит от того, будет ли файлом стан-
дартного вывода обычный файл, канал или устройство. В процессе
построения
больших и сложных программ из конструкционных элементов меньшего
размера
программисты часто используют каналы и переназначение ввода-вывода при
сборке и соединении отдельных частей. И действительно, такой стиль
программирования находит поддержку в системе, благодаря чему новые
программы могут работать вместе с существующими программами.
Например, программа grep производит поиск контекста в наборе файлов (яв-
ляющихся параметрами программы) по следующему образцу:
grep main a.c b.c c.c
где "main" - подстрока, поиск которой производится в файлах a.c, b.c и c.c
с
выдачей в файл стандартного вывода тех строк, в которых она содержится. Со-
держимое выводного файла может быть следующим:
a.c: main(argc,argv)
c.c: /* here is the main loop in the program */
c.c: main()
Программа wc с необязательным параметром -l подсчитывает число строк в
файле
стандартного ввода. Командная строка
grep main a.c b.c c.c | wc -l
вызовет подсчет числа строк в указанных файлах, где будет обнаружена подст-
рока "main"; выводной поток команды grep поступит непосредственно на
вход
команды wc. Для предыдущего примера результат будет такой: 3
Использование каналов зачастую делает ненужным создание временных
файлов.
4. ФУНКЦИИ ОПЕРАЦИОННОЙ СИСТЕМЫ
На Рисунке 1.1 уровень ядра операционной системы изображен
непосредственно под уровнем прикладных программ пользователя. Выполняя
различные элементар-ные операции по запросам пользовательских процессов,
ядро обеспечивает
функционирование пользовательского интерфейса, описанного выше. Среди функ-
ций ядра можно отметить:
. Управление выполнением процессов посредством их создания, завершения
или приостановки и организации взаимодействия между ними.
. Планирование очередности предоставления выполняющимся процессам времени