Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

OS_method_instr

.pdf
Скачиваний:
27
Добавлен:
27.08.2015
Размер:
1.65 Mб
Скачать

#!/bin/bash

while [ -n “$1” ] ; do

echo “Имеется аргумент – ”$1 shift

done

Аргументы просматриваются в цикле while, условием выполнения которого является результат команды test с параметрами, требующими, чтобы длина строки в аргументе $1 была отлична от нуля. В строку подставляется значение первого аргумента. Если аргумент не указан, то переменная $1 имеет пустое значение, соответственно строка будет иметь нулевую длину, и цикл сразу же прекратится. Если аргумент указан, то он выводится в теле цикла, и затем выполняется команда shift, которая изменяет переменные $n, сдвигая их на одну влево (т.е. $1=$2, $2=$3 и т.д.). Значение первого аргумента при этом теряется. Когда сдвигается последний аргумент, то переменной $1 присваивается пустое значение (так как следующей за ней переменной не существует). В качестве параметра команды shift можно указать, на сколько позиций требуется сдвинуть строку аргументов. Например, shift 2 приведёт к следующему изменению: $1=$3, $2=$4 и т.п.

Если требуется определить, есть ли в аргументах определённые короткие опции, можно использовать специальную команду getopts, которая сама просматривает специальные переменные и проверяет, является ли аргумент короткой опцией.

Напомним, что опцией называется аргумент командной строки, начинающийся с символов «-» или «--». Причём, если используется один знак минус, то опция считается односимвольной или короткой, если же – два знака минус, то – многосимвольной или длинной34.

Команда getopts вызывается следующим образом:

getopts строка_опций_поиска переменная

В строке_опций_поиска указываются односимвольные опции, которые должны быть «распознаны» getopts. Например, строка acdf говорит о том, что требуется найти какую-либо из опций: -a, -c, -d или -f.

Алгоритм работы команды getopts следующий.

Последовательно просматриваются специальные переменные $1, $2, $3$#, начиная с номера, указанного в переменной OPTIND. При первоначальном запуске командной оболочки в OPTIND находится 135. Другими словами, если впервые вызвать команду getopts, то она начнёт просмотр с переменной $1.

34Длинные опции в скрипте можно «распознавать» только через специальные переменные.

35Если потребуется заново провести проверку опций, то такое присвоение должен будет сделать поль-

зователь.

51

Если очередной аргумент не пустой, и он не содержит опцию (не начинается с символа «-»), то getopts завершается с ненулевым кодом возврата.

Иначе считается, что найдена опция, и производится сравнение следующего за тире символа с содержимым строки_опций_поиска.

Если найденная опция совпадает с одним из символов в строке_опций_поиска, то соответствующий символ записывается в

переменную.

Если совпадение не обнаружено (т.е. в командной строке указана опция, которая отсутствует в строке_опций_поиска), на экран выводится сообщение об ошибке, переменной присваивается значение «?».

Если просматриваемый аргумент больше не содержит символов, то номер следующего аргумента записывается в переменную OPTIND (чтобы при следующем запуске команды продолжить просмотр аргументов). В противном случае OPTIND остаётся без изменения, а запоминается позиция внутри текущего просматриваемого аргумента (чтобы в следующий раз продолжить просматривать этот аргумент, считая его опцией и начиная со следующего символа).

В случае если найдена «распознаваемая» или «нераспознаваемая» опция, код возврата getopts равен 0. В случае если просмотрены все аргументы и больше опций нет, или очередной аргумент не является опцией, то код возврата getopts отличен от 0.

Чтобы запретить выдачу сообщения об ошибке при нахождении опции,

которая «не распознаётся», необходимо либо переменной OPTERR присвоить 0, либо в строке_опций первым символом указать «:» (двоеточие). В последнем случае getopts начинает работать в «тихом» (англ. silent) режиме, и в случае ошибки найденную «нераспознаваемую» опцию она помещает в переменную OPTARG, а в переменную помещает символ «?».

Команда getopts позволяет «распознать» опции, для которых требуется дополнительный параметр. Для этого надо в строке опций после соответствующего символа включить знак «:»36. Например, в строке a:cdf: указывается, что опции -a и -f должны дополняться обязательными параметрами,например, -a файл или -b время.

Если при «распознавании» найдена подобная опция, и за ней следует непустой аргумент, то он помещается в переменную OPTARG, а сама опция помещается в переменную, и getopts завершается.

Если опция найдена, но за ней нет аргумента, то на экран выдаётся сообщение об ошибке, в переменную помещается символ «?», и getopts завершается. В «тихом» режиме при нахождении такой опции и отсутствии у неё параметра в переменную помещается символ «:», а в переменную OPTARG помещается сама опция.

Например:

36 Обратите внимание, что в данном случае символ «:» не является первым в строке, а следует за символом. При этом в начале строки символ «:» может как присутствовать (чтобы перевести getopts в «тихий» режим), так и отсутствовать.

52

#!/bin/bash

while getopts ab:cde:f: OPTION ; do case $OPTION in

\?)

echo “Найдена \“нераспознаваемая\” опция”

;;

:)

echo “Тихий режим и найдена опция ”${OPTARG}

;;

?)

echo “Найдена опция ”${OPTION} if [ -n “${OPTARG}” ] ; then

echo “Она имеет параметр ”${OPTARG}

fi

esac

echo “OPTIND = ”${OPTIND} done

echo “Finally OPTIND = ”${OPTIND}

Скрипт содержит в себе цикл, в котором последовательно запускается команда getopts до тех пор, пока код её возврата равен 0. В качестве строки_опций_поиска команда getopts получает строку вида «ab:cde:f:». Результат будет помещаться в переменную OPTION.

Запуск скрипта с параметрами -ab -c -d -e -f -g приведёт к следующему:

[student@wp student]$./getopts.sh -ab -c -d -e –f \ >–g<Enter>

Найдена опция a OPTIND = 1

Найдена опция b

Она имеет параметр –c OPTIND = 3

Найдена опция d OPTIND = 4

Найдена опция e

Она имеет параметр –f OPTIND = 6

./getopts.sh: illegal option – g

Найдена “нераспознаваемая” опция

OPTIND = 7 Finally OPTIND = 7

При первом запуске (на первой итерации цикла) команда getopts начнёт просмотр переменной $1, в которой располагается аргумент -ab. Так как он

53

начинается с символа «-», то считается, что найдена опция. После того, как определено, что аргумент содержит опцию, проверяется, входит ли она в строку опций. В данном случае она входит в неё и не требует дополнительного параметра (так как за ней нет символа «:»). Поэтому в переменную OPTION помещается символ a, и getopts завершается. Значение переменной OPTIND не изменяется, так как аргумент содержит ещё другие символы (b).

На следующей итерации цикла getopts продолжает просматривать первый аргумент (так как OPTIND = 1). В нём также оказывается опция, но она требует параметр (в строке_опций_поиска после символа b стоит двоеточие). Поэтому getopts проверяет, указан ли следом за этой опцией параметр. В данном случае он указан и равен -c, поэтому в OPTION помещается b, а OPTARG приравнивается к -c. Переменная OPTIND при этом указывает на аргумент с номером 3, так как текущий аргумент больше не содержит символов, а 2-й аргумент относился к найденной опции.

Далее аналогично просматриваются остальные аргумента до аргумента, содержащего опцию -g. Она считается нераспознанной. Поэтому на экран выдаётся сообщение об ошибке (так как никаких указаний по его устранению не было), и в переменную OPTION помещается символ «?».

Цикл продолжается до тех пор, пока не будут просмотрены все аргументы.

4.18. Вход в систему и первоначальные настройки

Часто при входе в систему, выходе из неё или при простом запуске командной оболочки37 пользователю требуется выполнить определённый набор действий38. Для этого при запуске и при завершении командная оболочка выполняет определённый набор скриптов, располагаемых в домашнем каталоге пользователя (таблица 8).

Таблица 8. Специальные файлы командной оболочки BASH.

Файл

Назначение

.bash_history

Содержит историю всех введённых пользователем команд.

.bash_profile

Исполняется оболочкой при входе пользователя в систему.

.bash_logout

Исполняется оболочкой при выходе пользователя из системы.

.bashrc

Выполняется при простом запуске пользователем оболочки.

Обратите внимание, что все эти файлы имеют имена, начинающиеся с

.bash.

Кроме этого, в правах на файлы ~/.bash* не указана возможность их исполнения. Это потому, что командой, исполняющей эти файлы, всегда является сама командная оболочка.

37Такой запуск также называется «интерактивным».

38Например, пользователю необходимо выводить информацию, имеется ли в его электронном почтовом ящике письма, или записать в журнал время и дату, когда он вошёл в систему и т.п.

54

Таким образом, если необходимо, чтобы какая-то команда выполнялась каждый раз при входе в систему, то эту команду надо поместить в файл

.bash_profile. Например, для вывода текущей даты и времени при входе в систему в файл .bash_profile надо добавить команду date.

Контрольные вопросы

1.Что такое командная оболочка? Какие типы командных оболочек используются в ОС Linux?

2.Что такое команда? Какая информация обычно содержится в приглашении для ввода команды?

3.Что такое опция и длинная опция?

4.Какие клавиши можно использовать для редактирования командной строки в оболочке BASH?

5.Как можно ввести многострочные команды?

6.Как получить справку о команде в ОС Linux?

7.Перечислите команды для работы с каталогами.

8.Как одной командой показать содержимое указанного каталога и всех его подкаталогов?

9.Как просмотреть содержимое файла в интерактивном режиме?

10.Для чего используется команда touch?

11.Как одной командой удалить непустой каталог?

12.Перечислите команды для работы с файлами.

13.Что выполняет команда ls –l?

14.Как изменить права доступа к файлам или каталогам?

15.Как организовать последовательное выполнение нескольких команд?

16.В чём отличие использования «;» и «&&» в списках команд?

17.Какие три потока для взаимодействия с пользователем имеет исполняемая программа?

18.Как перенаправить потоки ввода-вывода? В чём отличие «>» от «>>»?

19.Какой способ взаимодействия программ называется конвейером?

20.Назовите команду для смены пароля пользователя.

21.В каком файле хранится информация о пользователе системы? Опишите формат этого файла.

22.Для чего предназначена команда mount?

23.Что такое среда окружения? Как получить список всех переменных среды окружения? Как установить новые значения для переменных среды окружения? Как удалить переменную?

24.Как создать переменную командной оболочки? Для чего используется «$» перед именем переменной? Как организовать массив? Что такое условная подстановка?

25.Какие переменные среды окружения задают внешний вид приглашения командной оболочки? Как изменить формат приглашения?

26.Расскажите об управляющих структурах, используемых в командной оболочке BASH.

55

27.Какие циклические конструкции можно использовать в командной оболочке

BASH?

28.Как определяются функции использовать в командной оболочке BASH?

29.Что такое скрипт? Как запустить скрипт на выполнение?

30.Как передать аргументы скрипту? Чем опция отличается от аргумента?

31.Какая команда служит для распознавания опций?

32.Опишите специальные файлы командной оболочки BASH.

56

ГЛАВА 5. «ПРОЦЕСС» И «НИТЬ»

«В UNIX всё, что что-то делает - процесс».

Линус Торвальдс.

Из книги «Just for fun».

Функционирование любой ЭВМ заключается в выполнении строго определённой последовательности действий, называемой программой или

задачей. «Запустить программу на выполнение» означает загрузить саму программу (написанную на понятном для ЭВМ языке) и необходимые для неё данные в оперативную память и настроить процессор (значения его внутренних регистров) так, чтобы он стал выполнять инструкции, начиная с соответствующей ячейки оперативной памяти.

В мультизадачных системах, к которым относится и ОС Linux, в оперативную память может быть загружено сразу несколько программ. При этом, чередуя выполнение на одном процессоре инструкций то одной программы, то другой, ЭВМ создаёт «иллюзию» их одновременного выполнения. Правила, по которым чередуются инструкции разных программ, определяются операционной системой (подсистема планирования процессов

или нитей). При этом программы ничего не знают о существовании друг друга39.

В многопроцессорных (многоядерных) системах каждый процесс может выполняться на собственном процессоре (ядре). При этом каждый процессор, в свою очередь, может использоваться для выполнения нескольких (псевдо)параллельных процессов.

Для того чтобы операционная система могла определить, инструкцию какой программы следует выполнить следующей, должны выполняться два условия: во-первых, после выполнения очередной инструкции одной из программ процессор должен переключиться на операционную систему40, и, вовторых, операционная система должна обладать информацией обо всех «выполняющихся» программах (место в оперативной памяти, где располагаются инструкции программы; номер последней выполненной инструкции; значения регистров процессора после выполнения последней инструкции и т.п.). Информация обо всех выполняющихся программах хранится в оперативной памяти вместе с операционной системой.

Совокупность, состоящая из программы, описывающей её информации и дополнительных служебных данных, называется процессом. Информация о программе хранится в операционной системе в виде специальной структуры, называемой дескриптором процесса. Дескриптор процесса и дополнительная информация о программе вместе называются контекстом процесса.

39Следует помнить, что защита программ реализуется как на аппаратурном уровне (защищённый режим процессора), так и на уровне операционной системы.

40Напомним, что для ЭВМ операционная система является обычной программой, также загруженной в оперативную память.

57

5.1. Типы процессов

Все запущенные процессы условно (в зависимости от выполняемой ими функции) можно разделить на три типа: системные, процессы-демоны и прикладные процессы.

Системные процессы являются частью ядра и всегда расположены в оперативной памяти. Они часто не имеют соответствующих им программ в виде исполняемых файлов и всегда запускаются особым образом при загрузке ядра системы. Системными процессами являются, например: keventd (диспетчер системных событий), kswapd (диспетчер страничного замещения – своппинга), bdflush (диспетчер буферного кэша) и т.д.

Ксистемным процессам следует отнести процесс init, являющийся первым создаваемым процессом в системе и «прародителем» всех остальных процессов.

Процессы-демоныэто неинтерактивные (т.е. не взаимодействующие с пользователями) процессы, которые выполняются в фоновом режиме. Обычно они обеспечивают работу различных подсистем Linux, например, системы терминального доступа, системы печати, системы сетевого доступа и сетевых услуг и т.п.

Кприкладным относятся все остальные процессы, выполняющиеся в системе. Как правило, это процессы, порождённые в рамках пользовательского сеанса работы.

Пользовательские процессы могут выполняться как в интерактивном, так и в фоновом режиме, но в любом случае время их жизни (и выполнения) ограничено сеансом работы пользователя. При выходе из системы все

пользовательские процессы будут уничтожены. Интерактивные процессы связаны с определённым терминалом41 и через него взаимодействуют с пользователем. Фоновые процессы выполняются независимо от пользователя и

(псевдо)параллельно. Из фонового процесса можно создать процесс-демон, для чего ему следует отключиться от терминала42.

Запустить процесс на выполнение в фоновом режиме можно одним из следующих способов:

указать в конце командной строки символ амперсанд «&»;

приостановить выполнение интерактивного процесса (нажать комбинацию клавиш Ctrl+Z43), а затем командой bg запустить его на фоновое выполнение.

Чтобы посмотреть список всех фоновых задач, выполняющихся в рамках текущего сеанса пользователя, используется команда jobs, которая также выведет и текущее состояние каждой задачи.

41Напомним, что при запуске любой программы автоматически формируются три потока: ввода, вывода и вывода ошибок (в Cи их принято обозначать как stdin, stdout, stderr). По умолчанию все эти потоки связаны

стерминалом процесса.

42Это только одно из действий, которые необходимо выполнить, чтобы процесс стал полноценным «демоном».

43Следует помнить, что указанная комбинация клавиш для разных терминалов может быть разной. Здесь рассматриваются терминалы класса linux и xterm.

58

Чтобы перевести задачу, выполняющуюся в фоновом режиме, на передний план (в интерактивный режим), надо вызвать команду fg и передать ей в качестве аргумента номер фоновой задачи (из списка, выдаваемого командой jobs).

Любая фоновая задача будет приостановлена, если ей требуется определённый доступ к консоли (например, для ввода информации).

5.2. Состояние процесса

Каждый процесс в операционной системе Linux может находиться в одном из четырёх состояний: работоспособный, спящий (или ожидающий), остановленный и завершившийся.

Работоспособный (англ. runnable) процесс. Если процесс в текущий момент времени выполняет какие-либо действия или стоит в очереди на получение кванта времени на центральном процессоре, он называется работоспособным и обозначается символом R.

Ожидающий (спящий, англ. sleeping) процесс. Это состояние обозначается символом S и возникает после того, как процесс инициирует системную операцию, окончания которой он должен дождаться. К таким операциям относятся ввод-вывод, истечение заданного интервала времени, завершение дочернего процесса и т.д.

Остановленный (англ. stopped) процесс. Остановленный процесс не использует процессор и может быть полностью выгружен из оперативной памяти. Пользователь может остановить процесс, например, чтобы дать возможность другому процессу использовать больший объём оперативной памяти или быстрее завершиться. Обычный пользователь может остановить и продолжить только свой процесс, а суперпользователь – любой процесс в системе. Операционная система автоматически останавливает фоновые процессы в случае, когда они пытаются ввести данные с терминала. Это состояние обозначается символом Т.

Завершившийся («зомби», англ. «zombie») процесс. После завершения процесса информация о нём должна быть удалена операционной системой из таблицы процессов. В Linux такая операция возможна только после того, как родительский процесс выполнит системную операцию «ожидания завершения дочернего процесса» и прочитает статус возврата. До этих пор ОС вынуждена хранить в таблице процессов запись о завершившемся процессе, хотя он реально уже не существует и не потребляет ресурсы ЭВМ. Такое состояние процесса обозначается символом Z.

5.3. Атрибуты процесса

Любой процесс в операционной системе описывается дескриптором, содержащим ряд параметров, включая:

уникальный идентификатор процесса (PID);

идентификатор родительского процесса (PPID);

59

связанный с процессом терминал (TTY);

идентификаторы пользователя (UID, RUID, EUID, FSUID, SUID) и группы (GID, RGID, EGID, FSGID, SGID), от имени которых процесс выполняется и пытается осуществлять действия в рамках операционной системы или файловой системы;

номер группы процессов (GROUP);

идентификатор пользовательского сеанса (SESSION);

и т.д.44

Уникальный идентификатор процесса (PID) – это целое число,

позволяющее ядру системы различать процессы, т.е. своего рода «имя» процесса. По сути, PID – это номер ячейки в таблице дескрипторов процессов, выполняемых под управлением операционной системы. Когда создаётся новый процесс, ядро операционной системы использует следующую свободную запись в таблице дескрипторов. Если достигнут конец таблицы, то производится поиск свободной ячейки, начиная с начала таблицы. Когда процесс завершает свою работу, ядро освобождает занятый им идентификатор и соответствующий ему дескриптор.

Каждый процесс «запоминает» своего родителя в поле PPID. Зная значения поля PID и PPID, можно построить иерархию порождения процессов, начиная с самого первого процесса в системе (он обычно имеет PID = 0). Такая иерархия называется деревом процессов. Значение поля PPID играет особую роль при завершении процесса (см. ниже).

Как известно, каждому интерактивному процессу при создании назначаются потоки для: ввода информации, для её вывода и для вывода ошибок (stdin, stdout, stderr)45. Обычно все эти потоки указывают на один терминал, который называется «связанным» с процессом, и имя этого терминала (имя файла устройства) помещается в параметр TTY.

Все процессы в операционной системе запускаются каким-либо пользователем46. Идентификатор пользователя, запустившего процесс,

помещается в параметр «реальный идентификатор пользователя» (англ. UID

или RUID, Real UID). Часто возникает необходимость, чтобы процесс был запущен одним пользователем, а имел возможность получать доступ к ресурсам, принадлежащим другому пользователю. Контроль доступа к ресурсам системы осуществляется, исходя из значения поля «эффективный идентификатор пользователя» (англ. EUID, Effective UID). Примером ситуации выполнения действий от имени другого пользователя может служить смена пользовательского пароля с помощью команды passwd. Очевидно, что если база паролей (файлы /etc/passwd или /etc/shadow) будет доступна на запись кому угодно, тогда нельзя будет говорить ни о какой безопасности системы. Поэтому passwd настроена таким образом, что независимо от того, какой пользователь её выполняет, действия будут производиться всегда от имени

44На самом деле дескриптор процесса содержит значительно больше полей. Здесь приведены только те, которые используются в данном учебном пособии.

45О переопределении потоков ввода-вывода рассказывалось в п. 4.5.

46Считается, что загрузку операционной системы выполняет суперпользователь (администратор, root).

60