ИВАНЬКО Методичка Операционные системы 2012. Методические указания для практических занятий и выполнения лабораторных работ для студентов, обучающихся по специальности 230400 Информационные системы и технологии
Скачать 6.11 Mb.
|
При обращении к shell-переменной необходимо перед именем ставить символ "$" для получения Значения этой переменной. Сравните две команды, по-разному набранные с клавиатуры и заметьте разницу в результатах, распечатываемых программой на экране. Запись echo x печатает исключительно те буквы, которые введены после команды echo. (Аналог в С: printf(“x”) и printf(“%d”, x)). И еще один пример. Фрагмент командного файла: выдаст на экран Что наглядно показывает, что команда echo может за один раз выводить на экран несколько переменных. Команда "set" устанавливает значения параметров. Это бывает очень удобно. Например, команда "date" выдает на экран текущую дату, скажем, "Mon Oct 13 16:46:28 2011", состоящую из пяти слов, тогда выдаст на экран Команда "set" позволяет также осуществлять контроль выполнения программы, например:
Команда "set" без параметров выводит на терминал состояние программной среды Как во всяком языке программирования в тексте на языке shell могут быть комментарии. Для этого используется символ "#". Все, что находится в строке (в командном файле) левее этого символа, воспринимается интерпретатором как комментарий. Например, Как во всяком процедурном языке программирования в языке shell есть операторы. Ряд операторов позволяет управлять последовательностью выполнения команд. В таких операторах часто необходима проверка условия, которая и определяет направление продолжения вычислений. Команда test ("[ ]") Команда test проверяет выполнение некоторого условия. С использованием этой (встроенной) команды формируются операторы выбора и цикла языка shell. Два возможных формата команды: test условие или [ условие ] Пробелы должны быть и между значениями и символом сравнения или операции (как, кстати, и в команде "expr") . Про последнюю следует сказать подробнее. Именно команда expr даёт программе возможность воспринимать ту или иную переменную именно как число. (Иными словами, если сравнивать два ЯП, Shell и С, запись echo `expr $x` будет аналогична записи printf(“%d”, x). Разница в том, что в языке Си тип данных (char, int и пр.) определяется и устанавливается сразу при объявлении переменной, а в shell тип данных определяется после того, как значение было записано в переменную и может меняться в теле программы). Пример работы с командами и операторами языка shell. Попробуйте объяснить смысл каждой строки из данного примера. Какие операции запрашивает пользователь, и какие ответы даёт система? В shell используются условия различных "типов". Условный оператор "if" В общем случае оператор "if" имеет структуру if [условие] ; echo $0 then список [elif условие then список] [else список] Fi Здесь "elif" сокращенный вариант от "else if" может быть использован наряду с полным, т.е. допускается вложение произвольного числа операторов "if" (как и других операторов). Разумеется "список" в каждом случае должен быть осмысленный и допустимый в данном контексте. Конструкции [elif условие then список] и [else список] не являются обязательными (в данном случае для указания на необязательность конструкций использованы квадратные скобки - не путать с квадратными скобками команды "test"!). пример использования оператора if: Самая усеченная структура этого оператора if условие then список fi Обратите внимание, что структура обязательно завершается служебным словом "fi". Число "fi", естественно, всегда должно соответствовать числу "if". Примеры. Пусть написан расчет "if-1" Тогда вызов расчета if-1 12 11 даст /home/sae/STUDY/SHELL, а if-1 12 13 даст if-1 : Hello! Оператор вызова ("case") Оператор выбора "case" имеет структуру: case строка in шаблон) список команд;; шаблон) список команд;; ... esac Здесь "case" "in" и "esac" - служебные слова. "Строка" (это может быть и один символ) сравнивается с "шаблоном". Затем выполняется "список команд" выбранной строки. Непривычным будет служебное слово "esac", но оно необходимо для завершения структуры. Пример. ### # case-1: Структура "case". # Уже рассматривавшийся в связи со # структурой "if" пример проще и # нагляднее можно реализовать с # помощью структуры "case". echo -n " А какую оценку получил на экзамене?: " read z case $z in 5) echo Молодец ! ;; 4) echo Все равно молодец ! ;; 3) echo Все равно ! ;; 2) echo Все ! ;; *) echo ! ;; esac Непривычно выглядят в конце строк выбора ";;", но написать здесь ";" было бы ошибкой. Для каждой альтернативы может быть выполнено несколько команд. Если эти команды будут записаны в одну строку, то символ ";" будет использоваться как разделитель команд. Обычно последняя строка выбора имеет шаблон "*", что в структуре "case" означает "любое значение". Эта строка выбирается, если не произошло совпадение значения переменной (здесь $z) ни с одним из ранее записанных шаблонов, ограниченных скобкой ")". Значения просматриваются в порядке записи. ### # case-2: Справочник. # Для различных фирм по имени выдается # название холдинга, в который она входит case $1 in ONE|TWO|THREE) echo Холдинг: ZERO ;; MMM|WWW) echo Холдинг: Not-Net ;; Hi|Hello|Howdoing) echo Холдинг: Привет! ;; *) echo Нет такой фирмы ;; esac Оператор цикла с перечислением ("for") Оператор цикла "for" имеет структуру: for имя in список значений do список команд done где "for" - служебное слово определяющее тип цикла, "do" и "done" - служебные слова, выделяющие тело цикла. Не забывайте про "done"! Фрагмент "in список значений" может отсутствовать. Пример работы с оператором done: Т.о. мы видим, что переменная i в цикле пробегает по всем значением, заданным в условии (т.е. по очереди принимает значения всех переменных, указанных в условии), и для каждого из них выполняет ту операцию, которая заказана в теле цикла. Оператор цикла с истинным условием ("while") Структура "while", также обеспечивающая выполнение расчетов, предпочтительнее тогда, когда неизвестен заранее точный список значений параметров или этот список должен быть получен в результате вычислений в цикле. Оператор цикла "while" имеет структуру: while условие do список команд done где "while" - служебное слово определяющее тип цикла с истинным условием. Список команд в теле цикла (между "do" и "done") повторяется до тех пор, пока сохраняется истинность условия (т.е. код завершения последней команды в теле цикла равен "0") или цикл не будет прерван изнутри специальными командами ("break", "continue" или "exit"). При первом входе в цикл условие должно выполняться. a=`expr $a + 1` т.е. при каждой итерации значение "a" увеличивается на 1. Оператор цикла с ложным условием ("until") Оператор цикла "until" имеет структуру: until условие do список команд done где "until" - служебное слово определяющее тип цикла с ложным условием. Список команд в теле цикла (между "do" и "done") повторяется до тех пор, пока сохраняется ложность условия или цикл не будет прерван изнутри специальными командами ("break", "continue" или "exit"). При первом входе в цикл условие не должно выполняться. Отличие от оператора "while" состоит в том, что условие цикла проверяется на ложность (на ненулевой код завершения последней команды тела цикла) проверяется ПОСЛЕ каждого (в том числе и первого!) выполнения команд тела цикла. Примеры. Здесь программа с бесконечным циклом ждет ввода слов (повторяя на экране фразу "some more"), пока не будет введено "5". После этого выдается "enough" и команда "break" прекращает выполнение цикла. 6.1 Методика выполнения. 1. Разработайте текст процедуры с использованием по заданию (см. ниже), вариант задания назначается преподавателем. 2. Отладьте, при необходимости отредактируйте и выполните процедуру. 3. Оформите процедуру с использованием вспомогательных команд и комментариев так, чтобы она легко читалась и чтобы результаты её работы легко анализировались. 6.2 Контрольные вопросы. 1. Что такое shell-процедура? Назначение? 2. Какого типа команды могут быть включены в тело процедуры? 3. Чем отличается обработка процедуры при выполнении от обработки программы на языке высокого уровня? 4. Что такое параметры? Для каких целей они используются? Какое число параметров может быть передано процедуре? 5. Какие вспомогательные команды вы использовали при оформлении процедуры? 6. Какого вида значения и как могут быть присвоены переменным языка shell? 7. Что такое локальные переменные и для каких целей их надо экспортировать в среду? 8. Как осуществляется ветвление вычислительного процесса процедуры? 9. Какого типа цикла в процедурах могут быть построены средствами языка shell? 10. Какие способы вызова процедур на исполнение вы знаете? 6.3 Варианты заданий к лабораторной работе № 6 «Введение в shell-программирование» Разработать shell-процедуру с комментариями, выполняющую ниже перечисленные функции.
Лабораторная работа №7. Управление процессами. Работа преследует цель - закрепить представление о возможностях командного языка UBUNTU по управлению процессами, которым выделяются все необходимые ресурсы вычислительной системы. Изучаются команды: ps - запрос информации о процессах текущего терминала; &- запуск фонового процесса; fg, bg - переводит процесс в активный или фоновый режим; jobs - запрос листинга списка заданий; nohup - защита фоновых процессов от прерывания выполнения при выходе из сеанса работы с системой; nice - понижение приоритета процесса; kill - прекращение выполнения процесса. Процессом называется программа в стадии выполнения. Управление процессами — задача ядра операционной системы. Для поддержания информации о процессах ядро использует специальную структуру — таблицу процессов. Каждому процессу назначается уникальное число-идентификатор процесса, которое используется ядром для однозначного определения того, какому процессу соответствует запись в таблице процессов. В ОС UBUNTU между процессами поддерживаются отношения "родитель"-"потомок". Каждый процесс может породить произвольное число процессов-потомков, но каждый процесс имеет только одного родителя, и нет ни одного процесса, который не имел бы родителя. Самый первый процесс, запускаемый ядром в ходе раскрутки системы, в системе называется init и служит для управления процессом раскрутки системы, в том числе, запуска процессов-демонов. Демоны, также известные как системные сервисы, — это процессы, производящие неинтерактивную обработку данных пользователя, то есть процесс-демон не подключен к терминальному устройству. Примером процессов-демонов могут служить серверы протоколов НТТР и FТР httpd и ftpd, соответственно, или сервер системного журнала syslogd. Часто имена исполняемых файлов программ-демонов заканчиваются буквой d. Процессу init назначается идентификатор 1, первому порожденному init процессу, 2, и так далее. В ОС UBUNTU для идентификатора процесса общеупотребительным является сокращение PID. После того, как процесс порожден, то есть ему отведена запись в системной таблице процессов, он находится в состоянии готовности, и может быть выбран планировщиком процессов операционной системы для выполнения. При выполнении операций ввода вывода, и в ряде других случаев, процесс может перейти в состояние ожидания некоторого события; тогда до наступления этого события, или поступления в процесс некоторого прерывания, он не будет выбираться для выполнения. Кроме процессов, находящихся в состояниях готовности и ожидания, в UBUNTU могут присутствовать остановленные процессы, и процессы-зомби. Останов и возобновление выполнения процессов мы обсудим позднее в ходе сегодняшнего занятия, а процессов-зомби коснемся в ходе рассмотрения системных вызовов ОС UBUNTU. Для вывода списка запущенных процессов: s Команда ps принимает следующие ключи: -а — вывод информации о процессах, запущенных от имени всех пользователей, а не только текущего; -х — вывод информации о процессах, не подключенных к терминальным устройствам, например, о процессах демонах; -u — вывод информации о ресурсах, используемых процессами; -m — сортировка списка по объему используемой процессам оперативной памяти; -r — сортировка списка по используемому процессом процессорному времени; -U <имя пользователя> — вывод процессов, запущенных от имени указанного пользователя; -p <список идентификаторов процессов> — вывод информации только об указанных процессах; идентификаторы в списке разделяются запятой. Выводимый список включает несколько столбцов; эти столбцы содержат следующую информацию: USER — имя пользователя, запустившего процесс; PID — идентификатор процесса; %CPU — процент процессорного времени, потребляемый процессом; %МЕМ — процент объема памяти, занятой процессом; СОММАND — команда, использованная для запуска процесса; ТТ — терминальное устройство, к которому подключен процесс; VSZ — объем виртуальной памяти, затребованный процессом, в блоках по 1024 байта; RSZ — реальный объем памяти, используемый процессом, в блоках по 1024 байта; START — время запуска процесса. STAT — информация о состоянии процесса; первая буква означает состояние процесса: S — процесс находится в состоянии ожидания менее 20 секунд; I — процесс находится в состоянии ожидания 20 секунд, или более; К — процесс находится в состоянии готовности; Т — процесс остановлен; Z —процесс-зомби. За первой буквой может также быть указана дополнительная информация. Например, команда: рs -u -r -х может быть использована для вывода подробной информации обо всех процессах, запущенных от имени текущего пользователя, причем список процессов будет упорядочен по степени использования процессорного времени. Для наблюдения за процессами системы: top Программа top выводит таблицу, в которой каждому процессу соответствует одна строка. Сортировкой строк можно управлять, а по умолчанию критерием для сортировки является идентификатор процесса. В отличие от программ, с которыми мы имели дело до этого, top не возвращает управление пользователю сразу после печати результата. Вместо этого, через некоторые заданные промежутки времени программа собирает информацию о процессах системы и снова выводит ее на экран. Для выхода из программы следует нажать на клавишу [Q]. Программа принимает следующие параметры: -о<параметр> — указывает показатель для сортировки строк с информацией о процессах; по умолчанию сортировка производится по убыванию; для того, чтобы сортировка проводилась по возрастанию, перед названием показателя следует поместить знак ’+ ‘ не отделяя его пробелами ни от ключа, ни от названия показателя; среди показателей наиболее интересны следующие: command — команда, которой был запущен процесс; cpu — степень использования процессорного времени; pid — идентификатор; time — время выполнения процесса; rsize — реальный используемый процессом объем памяти; vsize — объем виртуальной памяти, используемый процессом; -s <число> — указывает задержку в секундах, между обновлением информации в таблице; по умолчанию 1 секунда; -n <число> — указывает число процессов, о которых будет выведена информация. Например, следующая команда: top -n 10 -s 3 -о cpu выведет таблицу из не более, чем 10 строк, в которой процессы будут отсортированы по убыванию используемого ими процессорного времени, причем обновляться таблица будет каждые 3 секунды. Заголовок таблицы содержит следующие обозначения столбцов для показателей: PID — идентификатор процесса; ТIМЕ — процессорное время, потребленное процессом с момента запуска; %СРU — процент процессорного времени, потребляемого процессом; USERNAME — пользователь, от имени которого выполняется процесс. Одним из способов взаимодействия между процессами в UBUNTU являются сигналы; сигналы — это сообщения, которые могут быть посланы процессу при помощи системного вызова. Каждому виду сигналов в системе соответствует название и номер. Многие сигналы имеют специальный смысл. В частности, сигнал SIGTERM уведомляет процесс о необходимости завершения, сигнал SIGTERM используется для безусловного завершения процесса, сигналы SIGSTOP и SIGCONT, соответственно, останавливают и возобновляют выполнение процесса, и так далее. Для того чтобы послать сигнал процессу из программы-оболочки: kill [-s <название сигнала>] <список идентификаторов процессов> Например, чтобы остановить выполнение некоторого процесса, с идентификатором 123, можно воспользоваться следующей командой: А для его возобновления, можно применить такую команду: Если при вызове kill не указать название сигнала, то будет послан сигнал SIGTERM. Так, для завершения процесса с идентификатором 123, можно использовать команду: Для вывода всех сигналов, поддерживаемых системой, служит ключ -l: Для ожидания в течение указанного числа секунд: slеер <время ожидания> Рассмотрим следующий пример файла сценария: Приведенный процесс, порожденный приведенным примером, будет попеременно находиться в состоянии готовности и выполнения — последовательное изменение значения переменной i с 1 до 9999, — и состоянии ожидания — вызов s1еер с параметром 3. Процесс никогда не завершится самостоятельно, так как условие внешнего цикла while всегда истинно — строка "true" не пуста. Далее будем считать, что сценарий сохранен в файле lоор.sh. Программа-оболочка позволяет запускать программы в фоновом режиме. Сразу после запуска программы, указанной в команде запуска в фоновом режиме, пользователь снова получает возможность вводить новые команды в программе-оболочке, в то время как запущенная программа продолжает выполняться. Для запуска программы в фоновом режиме команда завершается символом амперсанда: ‘&'. Например, команда: . /loop.sh & запустит на выполнение вышеприведенный файл сценария loop.sh в фоновом режиме. А следующая последовательность команд: ./ loop.sh & ps выведет информацию о запущенных процессах сразу после запуска сценария loop.sh, не дожидаясь завершения его выполнения. После запуска процесса, программа-оболочка напечатает его PID. Другим способом получить PID последнего процесса, запущенного в фоновом режиме, обращение к специальной переменной окружения! Этот способ удобно применять в файлах сценариев программы-оболочки. Следующий файл сценария запускает loop.sh, выводит информацию об этом процессе, а затем завершает его. #!/bin/sh ./ loop.sh & 1оор_pid=$ ! echo started loop.sh ps -u -p $loop_pid sleep 3 echo terminating loop.sh ps –u –p $loop_pid kill $ loop_pid echo terminated loop.sh ps –u –p $loop_pid Обратите внимание, что последний вызов ps не выводит на экран информацию ни об одном процессе, так как к этому моменту, процесс, выполняющий сценарий loop.sh, уже завершен. Протяженность времени, отводимого планировщиком операционной системы процессу, зависит от приоритета процесса. Чем выше приоритет процесса, тем большую часть процессорного времени он будет получать во время выполнения. Приоритет процесса выражается числом. Чем меньше число, тем выше приоритет. По умолчанию, процессы запускаются с приоритетом породившего их процесса. Для запуска процесса со значением приоритета, отличного от приоритета процесса-предка: nice [-n <число> ] <команда> При запуске процесса, значение приоритета будет откорректировано, исходя из переданного числа. Если ключ -n не был введен в команде, то используется число 10. Чем выше число, тем меньший приоритет получит процесс. Число, передаваемое в составе ключа -n может лежать в пределах от —20 до 20, но пользователям системы, не обладающим администраторскими полномочиями, как правило, не позволяется задавать отрицательные значения. То есть, рядовой пользователь не может повысить приоритет процесса. Для изменения приоритета после запуска процесса: renice -n <число> <список идентификаторов процессов> Программа renice работает аналогично nice, с той разницей, что изменяется не приоритет создаваемого процесса, а приоритеты всех запущенных процессов, идентификаторы которых входят в разделенный пробелами список, передаваемый команде в качестве параметра. Число, в составе ключа -n прибавляется к текущему приоритету процесса. Например, в следующем примере: приоритет процесса, выполняющего сценарий loop.sh устанавливается сначала 5, а затем 10. При вводе команды в программе-оболочке, вне зависимости о того, запускается ли программа в фоновом режиме, или нет, программа-оболочка порождает дочерний процесс. Для исполнения программы самим процессом программы-оболочки: ехес <команда> Рассмотрим следующий сценарий: #!/bin/sh ps ехес ./lоор.sp Пусть, он сохранен под именем ехес.sh. ./ехеc.sh & ps Первая команда запускает на выполнение сценарий ехес. sh, что приводит к порождению нового процесса. В этом можно убедиться, изучив результат вызова ps, который производится этим сценарий. После этого сценарий запускает уже рассмотренный нами сценарий 1оор.sh. Вторая команда из приведенной выше пары вызывает рs для выдачи списка запущенных процессов. Обратите внимание на то, что нового процесса для выполнения сценария lоор.sh создано не было — его выполняет тот же процесс, который был порожден для выполнения сценария ехес.sh. В качестве еще одного примера, рассмотрим следующую команду: ехес ls Результат ее выполнения — завершение работы программы-оболочки: так как процесс, выполнявший код программы-оболочки получил инструкцию выполнять код программы ls, то завершение кода программы ls, наступающее после вывода листинга текущего каталога, приведет к завершению выполняющего ее процесса. Таким образом, процесс, изначально выполнявший код программы-оболочки, будет завершен. 7.1 Методика выполнения. 1. Вывести на экран листинг характеристик (в длинном и коротком форматах) процессов, инициализированных с вашего терминала. Проанализировать и объяснить содержание каждого поля сообщения. 2. Разработать и запустить простейшую процедуру в фоновом режиме с бесконечным циклом выполнения, предусматривающую, например, перенаправление вывода каких то сообщений в файл или в фиктивный файл, и использующую команду sleep для сокращения частоты циклов процедур. 3. Выполнить п.1. Объяснить измерения в листинге характеристик процессов. Объясните содержание PID и PPID. 4. Понизите значение приоритета процедуры. На что и как повлияет эта операция при управлении вычислительным процессом системы? Как отразятся её результаты в описателях процессов? 5. Проанализируйте листинг процессов. Какой процесс является родительским для процедуры. 6. Выйдите из системы и войдите заново. Проанализируйте листинг процессов. Объясните изменения в системе. 7. Запустите процедуру в фоновом режиме, но предусмотрите её защиту от прерывания при выходе из системы. 8. Выполните п.6. Объясните изменения PPID процедуры. 9. Завершите выполнение процесса процедуры. 10. Запустите процедуру в оперативном режиме с перенаправлением вывода в соответствующий файл. 11. Переведите задание с процедурой в фоновом режиме и проанализируйте сообщение на экран. 12. Переведите задание с процедурой в оперативном режиме и проанализируете сообщение на экран. 13. Завершите выполнение процедуры и проанализируйте сообщение на экран. 14. Проанализируйте с использованием команды history содержание лабораторной работы, продумайте ответы на нижеприведенные контрольные вопросы и сдайте выполненную работу преподавателю. После получения зачета по работе – уничтожьте все созданные файлы и корректно выйдите из системы. 7.2. Контрольные вопросы 1. Объясните понятия процесса и ресурса. Какое их значение в организации вычислительного процесса в ОС UBUNTU? 2. Какая информация содержится в описателях процессов? Как просмотреть их содержание в процессе работы с системой? 3. Какими способами можно организовать выполнение программ в фоновом режиме? 4. Какие особенности выполнения программ в фоновом режиме? Как избежать вывода фоновых сообщений на экран и прерывания выполнения фоновых программ при прекращении сеанса работы с системой? 5. Как пользователь может повлиять на распределение ресурсов между активными процессами? 6. Как можно прервать выполнение активных процессов? Какая информация для этого необходима и откуда она извлекается? |