учебники, программирование, основы, введение в,

 

Управление процессами

Замечание о совместимости утилит
Несмотря на то что Solaris удовлетворяет многочисленным стандартам, некоторые программы в системе (точнее, их возможности и ключи) расходятся со стандартом XPG4. Этот стандарт (The X/Open Portability Guide, Issue 4 - XPG4) представляет собой спецификацию, описывающую программы, заголовки и интерфейсы. В частности, описывается ожидаемое поведение ряда программ UNIX и их ключи.
Что находится в каталоге /usr/bin/xpg4
В тех случаях, когда поведение и ключи программ Solaris расходились со спецификацией XPG4, изначальная версия программы под Solaris не изменялась. вместо этого программа, совместимая с XPG4 с примерно такими же функциональными особенностями и точно таким же именем, помещалась в каталог /usr/xpg4/bin. Таким образом, для того, чтобы выбрать, какие программы - оригинальные или XPG4-совместимые вы предпочитаете использовать в своей системе, достаточно указать первым в переменной среды окружения PATH тот каталог, в котором лежат нужные вам "по умолчанию" программы. Если первым указан каталог /usr/bin, то при вызове команды по ее короткому имени, например, grep, а не по полному имени файла, например, /usr/xpg4/bin/grep, будет вызываться /usr/bin/grep - оригинальная программа. Если указать в PATH первым /usr/xpg4/bin, то будет запускаться XPG4-совместимая версия. Помните, что оригинальные программы могут располагаться также в /bin, /usr/ucb и /usr/ccs/bin.
Спецификация XPG4 включает в себя спецификации программ из IEEE Std 1003.2-1992 и IEEE Std 1003.2a-1992 (которые вместе носят название POSIX 2).
Иерархия процессов в Solaris
Процессы делятся на процессы ядра и на все остальные процессы (последние называются пользовательскими процессами). Пользовательский процесс не обязательно запущен неким пользователем, то, что он - "пользовательский", означает лишь, что он не принадлежит ядру.
Само ядро Solaris представляет собой множество потоков (threads), которые выполняются параллельно. Действительно, у ядра много разных дел, было бы странно, если бы ядро пыталось все делать последовательно, а не параллельно. Термин threads часто переводят как "нить", но мы будем говорить в контексте управления процессами именно о "потоках", понимая под этим "потоки команд", в отличие от "потоков данных", которые будут рассмотрены ниже.
Потоки ядра чрезвычайно "легковесные", они обладают лишь маленькими сегментом данных и стэком. Передача управления от одного потока ядра другому не требует изменения базовых адресов виртуальной памяти. Каждый поток ядра имеет свой приоритет и может относиться к определенному классу потоков, в том числе и к классу потоков "реального времени".
Solaris реализует многоуровневую поточную модель. Ее назначение - разделить управление потоками пользовательского уровня и работу ядра. Потоки пользовательского уровня имеют свою схему приоритетов. Их планирование проводится с помощью потока-планировщика. Такой поток создается библиотекой потоков, когда многопоточное приложение компилируется и выполняется. Внутри одного пользовательского процесса могут работать свои потоки, передача управления между которыми осуществляется внутренним планировщиком этого процесса. Благодаря этому многопоточные приложения могут порождать тысячи потоков без существенной загрузки ядра. Оно будет видеть это приложение как один процесс. По сути, ядро не видит пользовательские потоки, пока они не присоединяются к легковесному процессу (lightweight process, LWP), имеющему определенное положение в операционной системе. Поток-планировщик отвечает за отображение пользовательских потоков в легковесный процесс (LWP), который связан с потоком ядра для выполнения процессором. Каждый LWP имеет поток ядра, но необязательно каждый поток ядра имеет LWP. Часть потоков ядра задействованы исключительно операционной системой, поэтому LWP здесь не требуется.

Свойства процесса
Каждый процесс имеет уникальный идентификатор, владельца и группу, представленные эффективным идентификатором пользователя и эффективным идентификатором группы, реальных владельца и группу, класс планирования и приоритет. Процесс всегда претендует на процессорное время и определенный объем оперативной памяти, которые требуются для успешной работы процесса.
Идентификаторы процесса
Процесс всегда имеет свой уникальный номер - PID (process ID). PID - это целое число в диапазоне допустимых целых чисел (для 32-разрядных систем - от 0 до 65535). Процесс с номером 0 - это обычно процесс свопинга, фактически являющийся частью кода ядра. Процесс с номером 1 - это всегда init, процесс, который порождает все остальные процессы в системе при ее старте. У всех процессов, кроме init, есть родительский процесс, и каждому процессу, кроме его собственного идентификатора PID, соответствует идентификатор родительского процесса (PPID - parent process ID).
В таблице процессов, кроме идентификаторов PID и PPID, хранятся eUID (effective UID - эффективный идентификатор пользователя) владельца процесса и eGID (effective GID - эффективный идентификатор группы) группы процесса. Фактические (реальные) владелец и группа процесса - это пользователь и группа, которые запустили процесс, а эффективные владелец и группа процесса - это те, от имени которых запущен процесс. Для определения прав доступа используются эффективные идентификаторы, а для задач управления процессом (например, посылки сигнала процессам, которые запустил определенный пользователь, см. описание команды pkill ниже) - реальные. Эти идентификаторы передаются по наследству от родительского процесса дочернему.
Передача этих идентификаторов для пользовательских процессов организована следующим образом. При входе пользователя в систему для него запускается командный процессор, этот запуск программа login обеспечивает от имени входящего пользователя. Группой процесса этого командного процессора назначается главная группа пользователя, вошедшего в систему.
Любой процесс относится к какой-либо терминальной группе, т.е. группе процессов, запущеных с одного терминала. Терминал определяется параметром TTYID.
Процесс имеет базовый и динамический приоритеты, в зависимости от приоритета запросы процесса к системе выполняются медленнее или быстрее.
Получить полный список процессов в системе с выводом их идентификаторов и ряда других параметров можно с помощью команды ps -ef.
Приоритеты процесса
Во многих системах UNIX процесс имеет базовый приоритет (NICE) и динамический приоритет (PRI). Базовый приоритет может принимать значение от -20 до +20. Чем меньше числовое значение базового приоритета NICE, тем выше приоритет. Процесс с отрицательным приоритетом -20 - самый высокоприоритетный. Динамический приоритет вычисляется планировщиком задач на основе базового приоритета по формуле, в которую входит общее потребленное процессом процессорное время. Чтобы дать возможность выполняться новым и более коротким процессам, динамический приоритет снижается с увеличением потребленного процессом времени процессора.
В Solaris применяется более сложная схема планирования приоритетов процессов, которая описывается ниже. Для процессов одного из классов планирования (с разделением времени) справедлива вышеописанная простая схема из базового и динамического приоритетов.
Каждый процесс может быть представлен одним или несколькими потоками ядра. С точки зрения ядра, объектом назначения того или иного приоритета является поток ядра. Если процесс сопоставлен только одному потоку ядра, то приоритет процесса и приоритет этого потока ядра - это одно и то же.
Приоритет базируется на классе планирования (scheduling class); всего различают четыре класса планирования: с разделением времени (timesharing), системный (system), реального времени (real-time) и планирование на основе справедливого раздела (fair Class scheduling, FCS). У процессов разных классов планирования свои уровни приоритета и свои очереди на выполнение. Стало быть, в системе мы имеем четыре очереди к процессору. Внутри каждого класса процессы, стоящие в очереди, имеют свои уровни приоритета. Эти уровни отображаются в глобальные приоритеты планирования (global scheduling priorities). Первым процессор займет процесс, который имеет наивысший глобальный приоритет. По умолчанию, процесс из класса планирования с разделением времени имеет более низкий глобальный приоритет, чем процесс из системного класса, а тот, в свою очередь, более низкий, чем процесс реального времени.
Процесс получает свой класс планирования и приоритет в наследство от процесса-родителя. Изменить класс планирования можно либо с помощью команды priocntl, либо посредством одноименного системного вызова.
Получить информацию о текущих классах планирования процессов можно с помощью команды dispadmin.
Среда окружения
Каждый процесс имеет свою среду окружения - специальную область, в которой хранятся имена переменных и их значения. Среда окружения используется для модификации поведения процесса; так, в зависимости от значения переменной TERM текстовый редактор будет выдавать разные коды управления экраном, поскольку переменная TERM используется для задания типа терминала. Переменные среды окружения могут быть помечены как экспортируемые, это означает, что такую переменную дочерний процесс унаследует от процесса-родителя. Такие переменные, как TERM, PATH, USER обычно являются экспортируемыми. Из командной строки пометить переменную как экспортируемую можно с помощью команды export:
export TERM PATH
К переменным среды окружения легко обратиться из прикладной программы на языке С - для этого предусмотрен специальный массив строк:
char *env[]
Аргументы
Каждый процесс при запуске может получить один или несколько аргументов. К аргументам можно обращаться так же, как и к переменным среды окружения, через массив строк:
char *argv[]
Число аргументов обязательно передается в каждый процесс в переменной:
int argc


Классы планирования
В Solaris 9 есть шесть классов планирования: с разделением времени (timesharing, TS), интерактивный (interactive, IA), системный (system, SYS), реального времени (real-time, RT),с фиксированным приоритетом (fixed priority, FX) и планирование на основе справедливого раздела (fair share scheduling, FSS).

Таблица 7.1. Соотношение глобальных и относительных приоритетов

Диапазон глобальных приоритетов

Очередь планирования

159–100

Процессы реального времени (0-59)

99–60

Системные процессы

59–0

Приоритеты процессов с разделением времени (0-59)

По умолчанию процессы попадают в класс с разделением времени.
С помощью команды
ps -cl
можно узнать глобальные приоритеты запущенных в данный момент процессов, а "внутренние" приоритеты процессов в разных классах планирования - с помощью команды dispadmin.
Планирование процессов реального времени
Планирование в реальном времени относится к средствам, с помощью которых процессу по мере необходимости обеспечивается квант процессора. Такая схема характерна для некоторых типов приложений, например, в робототехнике или управлении полетом. Вообще, поддержка планирования в реальном времени важна там, где требуется гарантированное время реакции системы на внешнее событие: в системах управления технологическими процессами, военных системах, коммуникационных системах и т.п. При написании приложения, которое управляет ракетой, заслонкой дозатора краски или даже простым видеотелефоном, приходится гарантировать время его реакции на прерывание, вызванное внешним событием, чтобы обеспечить разумное поведение приложения. Может выйти накладка, если ракета пролетит мимо цели, краски в крем для торта выльется больше, чем сливок, а изображения разных частей лица на видеофоне не будут синхронизированы во времени.
Существуют три варианта планирования процессов реального времени: его поддержки нет совсем, существует строгая поддержка реального времени (для приложений соблюдаются все предельные сроки) и выполняется нестрогая поддержка реального времени (предельные сроки могут быть пропущены, но поддерживается статистический минимум). Solaris - это среда с нестрогой поддержкой реального времени. А потому, для управления ракетой она может и не подойти - это зависит от алгоритма управления. Поддержка статистического минимума означает, что ракета может пролететь мимо, но зато вернется (если ее не собьют раньше или не закончится топливо).
В нестрогой среде реального времени период реакции должен иметь гарантированную конечную продолжительность (например, верхний предел времени, за которое приложение должно освободить процессор; в Solaris такой период составляет 5 миллисекунд).
В большинстве систем UNIX поддержки реального времени нет. Это связано с тем, что:

  • "промахи" обращения к памяти из-за отсутствия страниц в оперативной памяти могут вызвать непредсказуемую задержку вследствие необходимости подгрузить требуемую страницу в память из swap-раздела;
  • хотя ядро является выгружаемым (preemptable) - т.е. оно может быть смещено из процессора при запуске другого процесса, - в некоторых ситуациях все же не допускается выгрузка ядра из процессора, например, при обработке прерывания; элементы кода, которые не могут быть выгружены из процессора во время выполнения, называются "точками невыгружаемости" (nonpreemption points).

Решение первой из этих проблем в Solaris состоит в том, что все страницы процесса реального времени в памяти блокируются и их выгрузка на диск запрещается. Вторая проблема решается за счет того, что ядро Solaris - многопотоковое, обработчики прерываний реализованы как отдельные потоки, что делает возможным установить для них отдельный приоритет; более того, в Solaris есть возможность priority lending - "одалживание приоритета". Это означает, что когда более приоритетный процесс нуждается в результатах работы менее приоритетного процесса, он может "одолжить" последнему на время свой высокий приоритет для выполнения требуемой задачи.

Диспетчер
Когда поток готов к выполнению, он помещается в очередь отправки на выполнение. Каждый процессор (в многопроцессорной системе) имеет отдельный набор очередей отправки. Состояние ожидания в очереди отправки называется состоянием выполнения (RUN). Когда процессор освобождается, диспетчер берет поток с наивысшим приоритетом из очереди отправки этого процессора и помещает его в процессор. Теперь поток в состоянии "внутри процессора" (ONPROC) и может выполнять вычисления.
Поток может лишиться процессорного времени и покинуть процессор по нескольким причинам:

  • поток занимает процессор, пока не закончится отведенный ему период времени (определяемый приоритетом потока). Такой период называется квантом. Поскольку процессы с большим приоритетом выбираются чаще, то квант обычно обратно пропорционален приоритету (процессы с более высоким приоритетом имеют меньшие кванты). Когда квант исчерпан, потоку присваивается приоритет нового уровня (значение tqexp). Такой уровень почти всегда ниже приоритета потока при старте. Это сделано для обеспечения справедливости при планировании;
  • поток ждет завершения ввода-вывода или разблокировки нужного ему ресурса, тогда он переходит в состояние "сна" (SLEEP). Проснувшимся потокам назначается более высокий приоритет, чем у них был до сна, чтобы они могли "наверстать упущенное";
  • ядро прервало поток; если прерванный поток долго ожидает внимания процессора, то его приоритет повышается до значения lwait. Так потоки компенсируют ожидание в очереди после прерывания.

Проверка приоритета процесса
Выяснить, с каким легковесным процессом ассоциирован конкретный процесс и какой класс планирования ему назначен, можно с помощью команды ps и ключей -L и -с:
Вывод этой команды здесь сильно сокращен: процессов в системе на самом деле всегда значительно больше. Сейчас нам интересны прежде всего колонки LWP, CLS и PRI, в которых показаны номер легковесного процесса, класс планирования и глобальный приоритет соответственно.
Чем больше числовое значение глобального приоритета (значение PRI), тем выше глобальный приоритет процесса.
Мы видим, что многопоточные процессы (например, демон автомонтирования /usr/lib/autofs/automountd и демон протоколирования /usr/sbin/syslogd) могут одновременно иметь несколько LWP (в колонке NLWP указано количество LWP, с которыми ассоциирован процесс).
Настройка таблиц диспетчера
Таблицы диспетчера можно настроить с помощью команды dispadmin. Настройка выполняется следующим образом: вначале таблица диспетчера конкретного класса выводится в файл, затем файл редактируется в текстовом редакторе и загружается обратно в таблицу диспетчера. Вывод и загрузка таблицы осуществляется с помощью программы dispadmin.
Чтобы узнать, какие классы доступны для редактирования, следует запустить dispadmin с ключом -l и определить активные классы планирования:
dispadmin -l
CONFIGURED CLASSES ==================
SYS                    (System Class)
TS                     (Time Sharing)
FX                     (Fixed Priority)
IA                     (Interactive)
RT                     (Real Time)
Далее выводим таблицу диспетчера для выбранного класса (попробуем это на классе планирования с разделением времени - TS):
Первая строка, в которой указано значение RES, определяет, в чем измеряется время во всей таблице приоритетов данного класса. Величина RES фактически задает дискретность измерения времени для столбца ts_quantum таблицы диспетчера. Ее значение по умолчанию - 1000. Изменять дискретность не рекомендуется. Обратная к RES величина равна 0,001, и это интерпретируется как одна тысячная секунды, т.е. одна миллисекунда. Стало быть, по умолчанию время в столбце ts_quantum измеряется в миллисекундах.
Как было показано в разделе "Диспетчер" выше, смысл значений, приведенных в столбцах таблицы диспетчера, следующий:

  • ts_quantum представляет собой максимальный период времени (квант), в течение которого поток может оставаться в процессоре до того, как диспетчер изменит его приоритет;
  • ts_tqexp задает приоритет, который будет назначен потоку после того, как истечет его квант времени и он будет удален из процессора;
  • ts_slpret указывает приоритет, который будет иметь процесс, когда он будет обрабатываться после "сна", т.е. после ожидания завершения ввода-вывода или когда он дождется снятия блокировки с требуемого ему ресурса;
  • ts_maxwait указывает время в секундах, которое процесс будет оставаться в очереди, в случае, если его квант времени еще не истек; если он не использует свой квант времени в течение этого числа секунд, ему будет присвоен новый приоритет ts_lswait. Если ts_maxwait равно нулю, то принимается значение по умолчанию (одна секунда);
  • ts_lswait обозначает присваиваемый процессу приоритет, когда процесс на долгое время был вытеснен из процессора.

В таблицах диспетчера указываются относительные приоритеты (которые имеют силу внутри класса планирования). Глобальный (иначе говоря - абсолютный) приоритет вычисляется из относительного в соответствии с.
Обратите внимание на то, что более высокоприоритетные процессы имеют меньшие кванты времени. Значение maxwait для самого высокого приоритета, 59, настолько высоко, что ему придется ждать более других, если он лишится процессорного времени в пользу ядра (ядро имеет более высокий приоритет, чем любой процесс разделения времени).
Посмотрим, как работает эта схема динамического назначения приоритетов. Предположим, процесс начал выполняться с приоритетом 0. Подождав, пока ему дадут управление в течение одной секунды (ts_maxwait), процесс получил новый приоритет 50 (ts_lwait).
Вместе с новым приоритетом процесс обрел новое значение кванта (меньшее, так как чем выше приоритет, тем меньше квант, чтобы высокоприоритетные задачи не забивали процессор). Вместо прежних 200 миллисекунд процесс получил квант в 40 миллисекунд. Зато с этим приоритетом процесс получил возможность вытеснять из процессора менее приоритетные процессы.
Если процесс продолжает постоянно использовать процессорное время, не отвлекаясь на ввод-вывод (например, это вычислительный процесс программы моделирования полета ракеты), то по истечении кванта времени он получит новый приоритет 40 (ts_tqexp).
Дальнейшие назначения приоритетов показаны ниже:


приоритет

квант

40

40

30

80

20

120

10

160

0

200

50

40

40

40

30

80

и т.д.

и т.д.

Такая схема динамического назначения приоритетов позволяет быстро выполниться коротким высокоприоритетным процессам и дает возможность работать низкоприоритетным процессам. В то же время, процессы, постоянно потребляющие процессорное время, перемещаются к более низким приоритетам, получают большие кванты времени и будут больше времени проводить с низким приоритетом. Если же низкоприоритетный поток будет постоянно прерываться более высокоприоритетными, то его приоритет будет быстро повышен, как только пойдет ts_maxwait секунд. Фактически, это означает, что в сильно загруженной высокоприоритетными потоками системе низкоприоритетный поток через секунду будет становиться высокоприоритетным.
Класс реального времени (RT) описывается более простой таблицей диспетчера:
Потоки реального времени выполняются до завершения или до истечения их кванта (если в очереди стоят несколько потоков реального времени). Потокам реального времени присваивается самый высокий абсолютный приоритет, даже более высокий, чем потокам ядра, потому что относительные приоритеты отображаются в абсолютные, как показано в .

Планирование на основе справедливого раздела
В Solaris стандартный планировщик задач (диспетчер) старается предоставить процессам, которые по умолчанию запускаются с классом планирования timesharing (в режиме с разделением времени), примерно одинаковый доступ к процессору. Однако, если на самом деле некоторые процессы в системе более важны, чем другие (сервер баз данных, web-сервер крупного портала и т.п.), можно использовать иной метод планирования - планирование на основе справедливого раздела (fair share scheduler - FSS). В этом случае можно назначить группам процессов разные "порции" процессорного времени, которые те будут получать в единицу времени. Грубо говоря, можно потребовать от планировщика отдать 70% времени web-серверу, а 30% - всем остальным процессам. Если этого не сделать, время будет делиться поровну. Кроме соответствующего алгоритма, в Solaris 9 появился новый класс планирования, который тоже называется планированием на основе справедливого раздела.
В более ранних версиях Solaris этот алгоритм планирования (и соответствующий ему класс) отсутствовал, хотя в других системах аналогичный алгоритм был реализован в середине 1990-х годов, например, в IRIX 6.2.
Более детальное описание этой возможности дано по адресу http://docs.sun.com/db/doc/816-4882/6mb2ipq5n?q=scheduling+class&a=view
Распределение памяти. Swaping
В любой многопроцессной системе запущенные процессы и процессы, которые ждут возможности продолжить свое выполнение, могут в сумме занимать больший объем, чем объем установленной оперативной памяти, и поэтому в таких системах используют виртуальную память. Виртуальная память складывается из оперативной памяти и swap-разделов, размещенных на жестких дисках компьютера.
В UNIX вся память разделена на страницы определенного одинакового размера. Каждый процесс получает от системы запрошенное количество памяти, выделение памяти в UNIX осуществляется постранично. Процессы реального времени и часть кода ядра (например, та, что отвечает за обмен страницами между оперативной памятью и диском) всегда находятся в памяти, страницы остальных процессов могут быть выгружены на диск. В большинстве систем UNIX размер страницы составляет 4 Кбайт. В Solaris для x86 он ровно такой же, но на платформе SPARC может быть другой размер страницы, т.к. это свойство системы зависит от платформы. Узнать размер страницы памяти в Solaris можно по команде pagesize.
Традиционно в литературе по системам UNIX для описания процесса обмена страницами между памятью и диском используют термин "свопинг" (swaping). Этот термин в действительности означает полную выгрузку страниц процесса на диск. На самом деле менеджер виртуальной памяти в UNIX обычно выполняет "пейджинг" (paging), что означает постраничную (частичную) выгрузку процесса на диск. Свопинг выполняется в том случае, если памяти критически не хватает, чего при нормальной работе системы не наблюдается.
Алгоритм, который используется для выгрузки страниц в UNIX, называется "алгоритмом часов". Предполагается, что сканер страниц памяти время от времени указывает "стрелкой" этих "часов" на случайно выбранную страницу памяти. Как только это произошло, страница становится кандидатом на выгрузку. Если в течение определенного промежутка времени к ней не произошло обращения, ее и в самом деле выгружают на диск.
Более подробно алгоритм работы менеджера виртуальной памяти рассмотрен в лекции 17.
Для функционирования системы обязательно требуется, чтобы существовал по крайней мере один swap-раздел. При его создании рекомендуют отвести такому разделу не менее удвоенного объема оперативной памяти. Даже если вы являетесь сторонником выполнения этой рекомендации, постарайтесь подойти к ней критически: создание огромного swap-раздела, который никогда не будет использован даже наполовину, столь же нерационально, как и создание слишком маленького swap-раздела, который доведет систему до критической нехватки виртуальной памяти, что чревато неожиданным и принудительным завершением нужных процессов в системе.
При планировании дисковой подсистемы (в частности, размера swap-разделов) важно хорошо представлять, сколько памяти может потребоваться тем программам, которые будут одновременно работать в системе. В самом деле, если в системе планируется одновременно запускать сервер баз данных, web-сервер и несколько почтовых служб, можно предположить, что памяти понадобится много. Вполне реально оценить потребности в ней эмпирически - запустите по одной копии каждого демона, умножьте объем памяти, занятой каждым из них, на число предполагаемых демонов такого типа в рабочей системе и умножьте сумму получившихся чисел еще на два - для получения разумного запаса. Если такое количество оперативной памяти физически возможно установить в компьютер, вам светит счастливая звезда! Если нет, надо прикинуть, какой объем памяти критически важен (программы должны работать одновременно, а не лежать в swap-разделе поочереди или, не дай Бог, все вместе!), и решить, сколько при этом останется программ, которым все-таки придется "отдохнуть" на диске.
При нехватке памяти ядро UNIX просто уничтожает процессы, которые имеют более низкий приоритет, чтобы освободить место для других, более важных для системы процессов. Иногда ядро "убивает" процессы молча, даже не сообщая об этом на консоль, поэтому в условиях нехватки памяти мы можем неожиданно получить работающий, но не отвечающий ни на какие наши действия компьютер. Это лечится только аппаратным перезапуском.
Доступ процессов к файлам
В ходе работы процессы обращаются к внешним устройствам, файлам и каталогам. При обращении к внешнему устройству права доступа к нему определяются правами доступа к соответствующему файлу устройства. Права доступа к файлу и каталогу определяются одинаково, исходя из фактических прав доступа, определенных в файловой системе, включая расширенные права доступа (ACL).
То, какие права доступа к файлу получит процесс, зависит от эффективных идентификатора владельца (eUID ) и группы (eGID) этого процесса. При обращении процесса к файлу ядро проверяет, кем по отношению к этому файлу является владелец процесса. Если эффективный идентификатор владельца процесса совпадает с идентификатором владельца файла, то процесс получает права доступа к файлу, определенные для владельца файла. Если владелец процесса входит в группу файла, но не является владельцем файла, он получает права, определенные для группы файла. Если не имеет место ни то, ни другое, то процесс получает права доступа к файлу, определенные для "всех остальных".
Новый файл по умолчанию получает идентификаторы владельца и группы по наследству от процесса, который его создал, а права доступа к нему - по умолчанию - исходя из маски прав доступа umask.
Эффективный идентификатор группы процесса не играет роли в вычислении фактических прав доступа к файлу. Он используется исключительно для того, чтобы назначить его (по наследству) новому файлу, который будет создан процессом.

Запуск приложения от имени владельца файла приложения
Обычно эффективные идентификаторы владельца и группы процесса достаются процессу по наследству от процесса-родителя. Но в некоторых ситуациях необходимо запустить программу с правами, большими, нежели права запускающего ее пользователя. Например, вам надо изменить свой пароль. Для этого требуется осуществить запись в файл /etc/shadow. С другой стороны, нельзя давать каждому пользователю такое право: вдруг он поменяет не только свой пароль? Кто откажется сделать милый сюрприз коллеге? Как быть? Если вы подумали, что выход в том, чтобы все пароли менял только администратор, вы далеки от истины.
Идея в том, чтобы право записи в /etc/shadow дать не конкретному пользователю, а программе passwd (как нам известно, пароль меняет именно эта программа). К сожалению, в UNIX нет механизма, который позволяет давать какие-либо права отдельному процессу или приложению. Поэтому право записи в /etc/shadow дали пользователю root (назначив его владельцем этого файла и разрешив запись в файл владельцу - вы помните, как это сделать с помощью chmod?), а программу passwd разрешили всем запускать от имени ее владельца - root.
Это право (запускать программу от имени владельца) является специальным правом доступа к файлу, оно называется SUID (set User ID). Фактически, файл с установленным битом SUID, отвечающим за это право доступа, всегда запускается на выполнение с эффективным идентификатором владельца процесса, равным идентификатору владельца файла.
Как мы помним, полный вид слова прав доступа таков:
su sg  t   r  w  x  r   w  x  r   w  x
Старшие три бита - SUID (su), SGID (sg) и sticky bit (t).
Suid и Sgid
Установить бит suid или sgid можно, указав chmod права доступа в числовом виде:
chmod 4755 файл
или в мнемоническом виде:
chmod u+s файл
В некоторых системах UNIX доступна только одна из этих двух форм.
Бит установки эффективного группового идентификатора (SGID) при запуске файла на выполнение действует сходным с SUID образом: как и в случае бита SUID, установленный SGID вызывает присвоение процессу, исполняемый код которого содержится в запущенном файле, эффективного идентификатора группы, равного идентификатору группы этого файла.
В выводе команды ls файлы с установленными битами SUID и SGID отличаются от прочих тем, что в поле, где обычно стоит "x" (бит выполняемости), оказывается символ "s":
-r-xr-sr-x 1 roottty 10040 Nov 4 2002 /usr/sbin/wall
-r-sr-sr-x 1 rootsys 22168 Nov 4 2002 /usr/bin/passwd
Это означает, что присутствуют оба бита: и бит запускаемости, и бит SUID (или SGID, соответственно). Если попытаться установить бит SUID или SGID на файл, для которого в соответствующем праве доступа (владельца или группы) не будет бита запускаемости, то система не даст это сделать. Поскольку для каталога биты SUID и SGID имеют другое значение, то биты SUID/SGID и биты права поиска в каталоге могут быть установлены по отдельности. В выводе ls в правах доступа к каталогу при отсутствии права поиска и наличии битов SUID/SGID буква S в выводе прав доступа будет заглавной:
dr-Sr-xr-x  2  root  other  512  May  10  01:48  enum
-rw-r--r--  1  root  other  0    May  10  01:47  q
Обратите внимание на права доступа к каталогу enum. Объяснение смысла SUID/SGID для каталога дано в лекции 6.
Найти все файлы, у которых установлен бит SUID, можно с помощью команды
find / -perm -u+s
а файлы с установленным битом SGID - по команде
find / -perm -g+s
Чтобы не допустить взлома системы, относитесь внимательно к файлам, права доступа к которым разрешают запускать их от чужого имени. Появление таких файлов в системе может облегчить жизнь взломщику. Программа passwd, например, написана таким образом, что запускающий ее пользователь не сможет с ее помощью сделать ничего, кроме изменения собственного пароля. Поэтому ей можно доверить запускаться с правами пользователя root. Но где гарантия, что все остальные программы с установленным SUID такие же? Устанавливайте бит SUID только тем программам, которым доверяете на все сто!
Появление новых файлов с <подозрительными> правами доступа может говорить о попытке взлома системы, поэтому при инсталляции некоторых ОС автоматически устанавливается простой сценарий, использующий вышеописанную команду поиска таких файлов для отслеживания добавленных за последние сутки файлов с установленным битом SUID. Например, во FreeBSD это делается в сценарии /etc/daily, ежедневно проверяющем состояние системы.
Имеет смысл удостовериться в том, что все эти новые файлы появились по известной вам причине.
Интерактивные и фоновые процессы
Процесс в UNIX может быть интерактивным и фоновым. Процесс, который имеет доступ к вводу с терминала и к выводу на него, называется интерактивным (foreground). Таким процессом является почтовая программа mail, редактор текста vi и другие программы. Фоновый процесс не имеет доступа к вводу с терминала, и имеет условный доступ к выводу на терминал. Условие состоит в том, что вывод на терминал разрешен фоновому процессу, если терминал настроен для работы в режиме tostop. Эту настройку можно выполнить командой
stty -tostop
Обратная настройка выполняется командой
stty tostop
Если фоновый процесс пытается выводить что-либо на терминал, настроенный для работы в режиме tostop, то процессу посылается сигнал SIGSTOP. Процесс, получивший такой сигнал, останавливается (переводится в состояние STOPPED).
Если фоновый процесс начинает выполнять вывод на терминал в то время, когда вы работаете в текстовом редакторе или подобной программе, текст на экране может перемешаться. Это не беда: на фактическое содержание редактируемого файла это никакого влияния не оказывает. В большинстве полноэкранных программ под UNIX достаточно нажать Ctrl-L, чтобы обновить экран, и назойливые сообщения исчезнут.
Для запуска фонового процесса из командного интерпретатора следует дать команду, завершив ее знаком "&" (амперсэнд):
команда &
Можно запустить сборку пакета программ в фоновом режиме, и пока он собирается, выполнять другую работу:
make all &

Взаимодействие процессов

Процессы взаимодействуют друг с другом, используя при этом разные механизмы. Процессы могут асинхронно или синхронно передавать друг другу данные и управление доступом к ресурсам системы.
С каждым процессом связаны три независимых потока данных: стандартный ввод (stdin), стандартный вывод (stdout) и стандартный поток сообщений об ошибках (stderr). По умолчанию все три потока связаны с тем терминалом, с которого запущен процесс (стандартный ввод - с клавиатуры, вывод данных и ошибок - на экран). Стандартный ввод также называют входным потоком, а стандартный вывод - выходным.
Каждому из этих потоков сопоставлены внутренние дескрипторы файлов: входному потоку - 0, выходному потоку - 1, потоку сообщений об ошибках - 2. Внутренний дескриптор файла существует только в пределах того процесса, с которым он связан. Внутренние дескрипторы в разных процессах имеют одинаковые номера, но это физически разные внутренние дескрипторы - каждый процесс имеет свои собственные внутренние дескрипторы.

Перенаправление потоков

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

find / -name "some_name" > names

Символ правой угловой скобки > означает перенаправление выходного потока запущенной программы в файл. При использовании этой конструкции будет создан файл names; если файл с таким именем уже существует, то он будет уничтожен и затем будет создан новый файл с этим именем и новым содержимым.
Для добавления вывода программы в конец файла следует использовать конструкцию "две правые угловые скобки" >>

find / -name "some_name" >> names

В этом случае файл names будет создан, если он не существует, а если существует, выходной поток программы find добавится в конец файла.
Можно перенаправить текст из файла во входной поток.
Если время от времени вы отправляете письма по стандартной форме, например, уведомления пользователям о том, что их домашние каталоги превышают допустимый размер, можно подготовить такое письмо в текстовом редакторе и автоматически отправлять его из скрипта, проверяющего размер каталогов, с помощью команды

mail пользователь@компьютер < файл_с_письмом

Бывает необходимо отправить пользователям не совершенно одинаковые сообщения, а письма, в которых стандартный текст перемешан с личными обращениями и конкретными подробностями. Тогда на помощь приходит перенаправление потока посредством конструкции "документ здесь".
Это дает возможность перенаправить ввод в процесс не из файла, а прямо из командной строки (или тела скрипта):

mail пользователь@компьютер <<FINAL
Дорогой(ая) $TARGETUSER,
Вы превысили допустимый размер домашнего каталога на 
$OVERSIZE килобайт. Удалите ненужные Вам файлы, 
иначе это сделает робот!
   Системный администратор
FINAL

Такой скрипт отправит по указанному адресу письмо, в котором вместо $TARGETUSER и $OVERSIZE будут подставлены имя и превышение лимита того пользователя, которому предназначается письмо. Естественно, этим переменным следует присвоить какое-то значение перед выполнением команды, но тот фрагмент скрипта, в котором это делается, вы с легкостью додумаете самостоятельно.
Указание в тексте значков << показывает, что все, что следует непосредственно за ними до ближайшего символа-разделителя, является ограничителем текста. Символ-разделитель - это любой пустой символ: пробел, табуляция или конец строки. Все, что идет за ограничителем текста, передается во входной поток запущенного командой процесса вплоть до момента, когда в начале новой строки не встретится такой же ограничитель текста. Ограничитель может представлять собой любой набор непустых символов - неважно, просто ли это символ "точка", слово FINAL или что-то еще.
Кроме того, что потоки могут быть перенаправлены в файл или из файла, существует возможность перенаправить выходной поток одного процесса во входной поток другого. Например, направить выходной поток программы ls во входной поток программы more, чтобы длинный список файлов вывести поэкранно, можно так:

ls -l | more

Символ вертикальной черты "|" означает перенаправление выходного потока программы, команда вызова которой находится слева от этого символа, во входной поток программы, вызываемой справа.
При обработке текста часто используется конструкция, называемая конвейером, когда одновременно запускается несколько программ, которые передают данные друг другу: выходной поток первой перенаправляется во входной поток второй, выходной поток второй - во входной поток третьей и т.д.
Например, для подсчета запущенных демонов httpd можно использовать такую конструкцию:

ps -auxw | grep httpd | wc -l

Программа ps выводит список всех процессов, запущенных в системе, grep выбирает из этого списка строки, в которых есть подстрока httpd, а wc с ключом l подсчитывает, сколько строк оказалось в ее входном потоке.
Программы, запущенные в конвейере, начинают работать одновременно, поэтому данные на входе второй программы оказываются так скоро, как скоро их сможет сгенерировать первая.

Сигналы
Процессы могут взаимодействовать, посылая друг другу сигналы. Список сигналов в Solaris ограничен сорока двумя сигналами, из которых наиболее употребительны сигналы TERM, KILL и HUP. В разных вариантах UNIX может быть разное количество сигналов, стандарт POSIX 1.1 определяет тридцать один сигнал. Каждый сигнал имеет свое мнемоническое обозначение и номер. В разных системах мнемонические обозначения остаются одинаковыми, а номер может быть разным.
Обычный процесс может послать сигнал только тому процессу, который имеет такой же эффективный идентификатор владельца, т.е. запущен тем же пользователем. Процесс, работающий от имени root, может послать любой сигнал любому процессу в системе.
С помощью команды
kill
можно послать сигнал с номером номер_сигнала процессу с идентификатором PID:
kill -номер_сигнала PID
В некоторых системах UNIX есть возможность послать сигнал процессу с определенным именем посредством программы killall:
killall -номер_сигнала имя_процесса
В Solaris эта программа имеет другое значение, а именно выполняет отправку сигнала завершения всем активным процессам:
killall
А отправить сигнал процессам с определенным именем в Solaris следует командой pkill:
pkill sendmail
С помощью pkill можно отправлять сигнал завершения TERM процессу с тем или иным признаком, так что отправка сигнала процессу с определенным именем - не единственное умение pkill. Например,
pkill -HUP -G other,daemon
отправит сигнал HUP (SIGHUP) всем процессам, чья фактическая группа - other или daemon.
Вприведен список сигналов, определенный стандартом POSIX 1.1, а в- список сигналов, определенных в Solaris 9.
Кроме команды pkill системный администратор может найти удобной команду pgrep, которая заменяет конструкцию
ps -ef | grep команда
В Solaris для получения того же результата можно ввести более короткую команду
pgrep команда


Таблица 7.2. Сигналы POSIX 1.1

Сигнал

Номер

Значение

SIGHUP

1

Разрыв связи с управляющим терминалом или управляющим процессом

SIGINT

2

Прерывание с клавиатуры

SIGQUIT

3

Сигнал выхода дан с клавиатуры

SIGILL

4

Недопустимая инструкция

SIGABRT

6

Сигнал abort получен от вызванной кем-то функции abort

SIGFPE

8

exception: ошибка вычислений с плавающей запятой

SIGKILL

9

Безусловное завершение процесса

SIGSEGV

11

Неверный адрес памяти

SIGPIPE

13

Запись в несуществующий канал

SIGALRM

14

Сигнал timer от функции alarm

SIGTERM

15

Завершение

SIGUSR1

30,10,16

Определяется пользователем

SIGUSR2

31,12,17

Определяется пользователем

SIGCHLD2

20,17,18

Дочерний процесс остановлен или принудительно завершен

SIGCONT1

19,18,25

Продолжить выполнение, если оно было остановлено

SIGSTOP

17,19,23

Остановить процесс

SIGTSTP

18,20,24

Останов введен с терминала

SIGTTIN

21,21,26

Ввод с терминала для фонового процесса

SIGTTOU

22,22,27

Вывод на терминала для фонового процесса

Таблица 7.3. Сигналы Solaris 9

Название

Знач.

Действие по

Событие

SIGHUP

1

завершение

разрыв связи с терминалом

SIGINT

2

завершение

прерывание

SIGQUIT

3

аварийное завершение (core)

Quit (требование завершения)

SIGILL

4

аварийное завершение (core)

недопустимая команда процессора

SIGTRAP

5

аварийное завершение (core)

прерывание при трассировке или точка останова

SIGABRT

6

аварийное завершение (core)

аварийное принудительное завершение

SIGEMT

7

аварийное завершение (core)

прерывание эмуляции

SIGFPE

8

аварийное завершение (core)

arithmetic exception: ошибка вычислений с плавающей запятой

SIGKILL

9

безусловное завершение

требование безусловного завершения

SIGBUS

10

аварийное завершение (core)

ошибка шины

SIGSEGV

11

аварийное завершение (core)

ошибка сегментации (выход за пределы выделенной памяти)

SIGSYS

12

аварийное завершение (core)

неверный системный вызов

SIGPIPE

13

завершение

запись в несуществующий канал

SIGALRM

14

завершение

Сигнал timer от функции alarm

SIGTERM

15

завершение

завершение

SIGUSR1

16

завершение

программируемый сигнал 1

SIGUSR2

17

завершение

программируемый сигнал 2

SIGCHLD

18

действия не выполняются

изменение статуса дочернего процесса

SIGPWR

19

действия не выполняются

сбой питания или перезагрузка

SIGWINCH

20

действия не выполняются

изменение размера окна

SIGURG

21

действия не выполняются

состояние сокета (Urgent Socket Condition)

SIGPOLL

22

завершение

Pollable Event (см. streamio (7I))

SIGSTOP

23

остановка

требование остановки

SIGTSTP

24

остановка

остановка ввода с терминала

SIGCONT

25

действия не выполняются

требование продолжения

SIGTTIN

26

остановка

ввода ввод с терминала для фонового процесса

SIGTTOU

27

остановка

вывода вывод на терминал для фонового процесса

SIGVTALRM

28

завершение

Virtual Timer Expired

SIGPROF

29

завершение

Profiling Timer Expired

SIGXCPU

30

аварийное завершение (core)

достижение лимита времени использования процессора (CPU time limit exceeded)

SIGXFSZ

31

аварийное завершение (core)

превышение допустимого размера файла – getrlimit (см. getrlimit (2))

SIGWAITING

32

действия не выполняются

зарезервировано библиотекой потоков

SIGLWP

33

действия не выполняются

межпроцессный (LWP) сигнал – зарезервировано библиотекой потоков

SIGFREEZE

34

действия не выполняются

Check point Freeze

SIGTHAW

35

действия не выполняются

Check point Thaw

SIGCANCEL

36

действия не выполняются

сигнал отмены, зарезервировано библиотекой потоков

SIGXRES

37

действия не выполняются

выход за границу блока управления ресурсом

SIGRTMIN

*

завершение

первый сигнал реального времени

(SIGRTMIN+1)

*

завершение

второй сигнал реального времени

(SIGRTMAX-1)

*

завершение

предпоследний сигнал реального времени

SIGRTMAX

*

завершение

последний сигнал реального времени

Каналы и сокеты
Процессы могут обмениваться данными друг с другом, и в UNIX предусмотрены механизмы такого обмена. Прежде всего, это каналы (pipes) и сокеты (sockets), которые служат для межпроцессной коммуникации, т.е. для передачи данных между одновременно запущенными процессами.
Канал - это последовательность байт, используемая как однонаправленный поток ввода/вывода.
С точки зрения программиста, бывают именованные и неименованные каналы, и способы обращения к ним несколько отличаются. При использовании канала один процесс открывает канал для чтения, другой - для записи.
Сокет - это объект, который используется для межпроцессных коммуникаций; он существует, пока какой-либо процесс хранит дескриптор, ссылающийся на него. Сокет создается системным вызовом socket, который возвращает его дескриптор. Имеется несколько типов сокетов, которые поддерживают различные возможности передачи данных.
Для каждого процесса ядро хранит таблицу внутренних дескрипторов. По-английски эта таблица называется "descriptor table", и чтобы не путать ее с таблицей дескрипторов в файловой системе, мы называем внутреннюю таблицу дескрипторов, относящуюся к конкретному процессу, "таблицей внутренних дескрипторов". Слово "внутренних" подчеркивает то, что эти дескрипторы существуют только в пределах процесса, который пользуется ими для обращения к файлам. Эта таблица наследуется от родительского процесса, поэтому вместе с ней наследуется и доступ к объектам, на которые ссылаются дескрипторы (файлам, каналам, сокетам).
Основными способами, при помощи которых процесс может получить дескриптор, является открытие или создание объекта, а также наследование от родительского процесса. Когда процесс завершается, ядро освобождает все дескрипторы, которые использовались этим процессом. Если процесс хранил последнюю ссылку на объект - файл или канал (т.е. в файловой системе больше не содержится записей об этом объекте), то система выполняет окончательное удаление файла (канала) или уничтожение сокета.
Подробнее о сокетах можно прочесть в socket(3).
Семафоры
Семафоры - это механизм, который принято использовать для контроля доступа нескольких процессов к одному ресурсу. Есть несколько реализаций программного интерфейса (API), связанного с семафорами:

  • вариант System V IPC (inter-process communication);
  • BSD;
  • POSIX 1003.1b.

Семафор по сути - это переменная, в зависимости от значения которой доступ к тому или иному ресурсу разрешается или блокируется до его освобождения. Семафоры широко используются в Oracle. Чтобы настроить подсистему семафоров в Solaris (обеспечить достаточное количество семафоров в ядре), может потребоваться внести изменения в файл конфигурации ядра /etc/system. Для уточнения того, какие настройки требуются именно вашему программному обеспечению под Solaris, обратитесь к руководству по этому ПО.
Для Oracle8i в Oracle8i Installation Guide Release 3 рекомендуются следующие начальные значения параметров:

  • set semsys:seminfo_semmni=100
  • set semsys:seminfo_semmsl=<10 + самое большое значение PROCESSES среди ваших БД>
  • set semsys:seminfo_semmns=<столько, сколько объяснено ниже>
  • set semsys:seminfo_semopm=100
  • set semsys:seminfo_semvmx=32767

Значение seminfo_semmns рекомендуется установить равным сумме параметров PROCESSES всех баз данных сервера, причем самый большой из них должен быть просуммирован с коэффициентом 2, плюс еще 10 на каждую базу данных.
Узнать текущие значения параметров семафоров (Solaris) можно с помощью команды:
sysdef | tail -25
Текущие наборы семафоров в системе (Solaris) покажет команда:
ipcs -sb
Иногда случается, что при неверном завершении процесса семафоры остаются блокированными. Или бывает, что повторный запуск интенсивно использующего семафоры процесса сорвется из-за нехватки семафоров. В этом случае необходимо удалить соответствующие наборы семафоров командой
ipcrm -s semsetID
semsetID здесь означает идентификатор набора семафоров.

Управление процессами
Команды наблюдения за процессами
Для просмотра текущего списка и состояния процессов следует использовать программу ps. Она выдает "мгновенный снимок" таблицы процессов, которые запущены в системе.
Программа ps без аргументов сообщает список процессов, запущенных пользователем в текущей сессии. Обычно системного администратора интересуют все запущенные в системе процессы, список которых можно узнать по команде
ps -ef
В системах BSD и System V программа ps имеет разные ключи, поэтому если вы переходите от одной системы к другой, надо помнить об этих различиях или обращаться к man ps.
Разберем подробнее, какую информацию выдает программа ps:
Ниже мы описываем смысл колонок этого вывода. Некоторые колонки появятся только при использовании специфических ключей, отличных от ключей ef. Для получения еще более детальной информации следует обратиться к man ps.
UID - эффективный идентификатор владельца процесса (реальный выводится при использовании ключа -f).
В колонке F - flags (флаги) - выводятся флаги процесса, это устаревшее поле, сохраненное для совместимости.
В колонке S - state (состояние) - указывается состояние процесса. Состояния бывают следующие:

  • O (ON PROC) - процесс находится в процессоре и выполняется;
  • S (Sleeping) - процесс ждет завершения события (например, ввода-вывода);
  • R (Runnable) - процесс готов к выполнению и ждет своего кванта в очереди к процессору;
  • Z (Zombie) - процесс стал <зомби>, так как завершился, а родительский процесс не подождал его завершения;
  • T (sTopped) - процесс остановлен по сигналу остановки или в процессе трассировки.

Идентификатор PID - уникальный идентификатор процесса, используется при передаче ему сигналов.
PPID - идентификатор родительского процесса.
C - загрузка процессора на планирование задачи (устарело, выводится для совместимости).
CLS - класс планирования.
PRI - приоритет процесса; когда указан ключ -с, бо'льшие значения означают больший приоритет, без ключа -с бо'льшие значения означают меньший приоритет.
NI - значение NICE (показателя уступчивости), используется при вычислении глобального приоритета процессов в классе разделения времени.
ADDR - адрес в памяти.
SZ - размер процесса в виртуальной памяти, включая все отображенные файлы и устройства, измеряется в страницах памяти, для получения размера в килобайтах в большинстве случаев это значение надо умножить на 4, точнее - см. команду pagesize.
WCHAN - адрес события, ради которого процесс перешел в состояние сна; если поле пусто, процесс запущен.
STIME - время запуска процесса, в часах, минутах и секундах, для запущенных более суток назад процессов указываются месяцы и дни.
TTY - управляющий терминал (то же, что и терминальная группа), символ вопросительного знака "?" печатается для процесса без управляющего терминала.
TIME - число минут и секунд, указывающее, сколько времени процесс отнял у процессора.
CMD - команда, которой был запущен процесс.
При указании ключа j выводятся дополнительные сведения:
PGID - идентификатор лидера группы процессов.
SID - идентификатор процесса - лидера сессии.
При указании ключа L выводятся дополнительные сведения, причем информация выдается по одной строке на каждый легковесный процесс, обычные однопоточные процессы соотносятся только с одним легковесным процессом:
LWP - идентификатор легковесного процесса.
NLWP - число легковесных процессов для процесса.
Завершившиеся процессы, код завершения которых не был востребован родительским процессом, помечаются как "defunct".
Кроме программы ps в UNIX для получения информации о запущенных в данный момент процессах широко используется команда top:
В Solaris для удобства получения информации о процессах с определенными именами есть команда
pgrep имя
Она является эквивалентом команды
ps -ef | grep имя
С помощью pargs можно посмотреть, какие аргументы переданы конкретному процессу и какая у него среда окружения:
Вывод команды pargs значительно сокращен, ключ -e требует вывести все содержимое среды окружения, а для графических программ типа dtterm, как в нашем примере, среда окружения весьма велика.
Команда prstat позволяет в динамике, подобно команде top, отслеживать состояние процессов:
Вы можете получить информацию только о тех процессах, которые запущены вами. Пользователю root доступна информация о любых процессах.
Процессы-зомби
В Solaris 9 появилась новая программа preap, которая позволяет убрать из системы "мнимые" (defunct), не до конца завершившиеся процессы, которые также носят название "зомби" (zombie). Эти процессы совершенно безобидны, так как это - самые обыкновенные процессы, код завершения которых не был принят родительскими процессами (например, в результате преждевременного завершения родительского процесса или иного сбоя). Несмотря на безобидность, они могут попусту занимать ресурсы системы, если таких процессов будет много. Обычно процессы-зомби автоматически уничтожаются процессом init, но если этого почему-либо не произошло, можно воспользоваться программой preap, которая примет код завершения процесса-зомби и даст ему упокоиться с миром.

Команды управления процессами

Основным средством управления процессами является команда kill, передающая процессу сигналы. Также можно использовать вышеописанные программы изменения приоритета процесса, прежде всего, команду nice, для управления приоритетом.
Не следует путать команду kill с сигналом KILL - они просто тезки; с помощью одноименной команды можно передать процессу как сигнал KILL, так и любые другие сигналы.
Будучи запущенной без ключей, она передает процессу сигнал TERM, требующий завершения процесса:

kill [-ключи] номер_процесса

Например, для завершения процесса sendmail можно выполнить следующие действия:

:
ps auxw | grep sendmail 
root  2057 0.0 0.2 2664 444 ? S Jul08 3:24 sendmail: 
                               accepting connections

Как видно, sendmail имеет PID 2057. Посылаем сигнал, требующий завершения процесса:

kill 2057 

И повторяем последнее действие для проверки (контрольный выстрел):

kill 2057
kill: (2057) - No such pid 

Сообщение No such pid говорит о том, что процесс уже завершился.
Программу kill можно использовать для передачи любых сигналов. Чтобы передать некий сигнал, надо указать в качестве ключа числовое или мнемоническое обозначение этого сигнала.
Например, после изменений, внесенных в файл конфигурации /etc/inetd.conf, следует потребовать от демона inetd перечитать этот файл конфигурации.
Это можно сделать, послав демону сигнал HUP (номер один), так как известно, что этот демон перечитывает файлы конфигурации, если получает сигнал с номером 1. Вначале надо узнать идентификатор процесса, которому будем посылать сигнал:

ps -ef | grep inetd 
root   156     1  0  17:43:44     ?   0:00  /usr/sbin/inetd -s
root   4555  760  0  19:15:16  pts/5  0:00  grep inetd

Мы видим два процесса, в строках информации о которых есть слово inetd. Первая строка, grep inetd - это тот самый процесс grep, который мы только что сами запустили. Программы ps и grep запустились одновременно, и ps показал "мгновенный снимок" таблицы процессов.
Строка grep inetd в таком случае должна была бы показываться всегда, но на практике иногда мы не видим ее при запуске такой команды. Проведите эксперимент: возможно, что в вашей системе (это зависит от ее скорости и текущей загрузки) вы никогда не увидите строку grep или наоборот, будете ее видеть всегда.
Это связано с тем, что физически запуск grep происходит чуть-чуть позже, чем ps, последняя может успеть завершиться раньше, чем grep начнется (ведь таблица процессов может оказаться маленькой и работы у ps будет мало). Тогда строки про grep в списке найденных процессов не будет.
Теперь пошлем сигнал процессу inetd :

kill -1 156

Помните, не все демоны и не во всех системах по сигналу HUP перечитывают свой файл конфигурации. Прежде чем посылать демону сигналы, выясните, как он на них собирается реагировать: почитайте в man о его повадках.
Владелец процесса может посылать сигналы своему процессу, но привилегированный пользователь (root) может отправить любой сигнал любому процессу.
Посылка сигнала KILL (номер 9) вызывает безусловное немедленное завершение процесса:

kill -9 PID

или

kill -KILL PID

При выполнении команды kill лучше указывать мнемонические обозначения сигналов, а не числовые: в разных системах UNIX сигналы с одним и тем же числовым номером могут иметь разный смысл. Впрочем, можно смело руководствоваться вышеприведенными таблицами в разделе "сигналы" в отношении сигналов в Solaris.
Для посылки сигнала нескольким процессам одновременно следует использовать программы pkill или killall (их подробное описание приведено в разделе "Сигналы" выше в этой лекции).
При запуске процесса можно менять его базовый приоритет внутри класса планирования. Это возможно только для класса планирования разделения времени. Обычный пользователь может только понижать приоритет процесса, а привилегированный пользователь может менять NICE в обе стороны. Для этого используется команда nice, которая в разных системах имеет разные ключи и немного разный синтаксис.
В Solaris она выглядит так:

nice -n приращение команда

например

nice -n 5 ls

Это "5" воспринимается как увеличение значения NICE на 5, т.е. снижение приоритета на 5 единиц. Пользователь root может дать команду вида nice -n -4 ls. Это будет воспринято как увеличение базового приоритета, т.е. уменьшение значения NICE на 4.
Базовый приоритет уже запущенного процесса можно менять командой renice:

renice -n приращение PID

Команда renice может быть использована также для изменения приоритета группы процессов по разным признакам, для уточнения обратитесь к man renice.

Работа с заданиями

Заданием называют запущенные одной командой несколько программ (в частном случае это может быть и одна программа). Для управления заданиями можно использовать встроенные команды командных интерпретаторов. Так, в большинстве из них есть команды jobs, bg и fg - для получения информации о заданиях, переключении задания в фоновый или интерактивный режим соответственно.
Более подробно о работе с заданиями говорится в лекции 9.

Планирование запуска процессов

Вынесете ли вы сегодня мусор или пойдете в магазин, поедете на заправку кормить своего железного коня бензином или просто ляжете спать пораньше - так или иначе, какое-нибудь дело вы сегодня сделаете. Дела, которые вы делаете, могут быть однократными (купить щенка) или регулярными (погулять с собакой). Может быть, "однократные" - не совсем точное прилагательное, потому что щенка вы можете купить и раз, и два, и еще много раз в жизни. Но вряд ли это дело можно назвать регулярным - не станете же вы раз в год ровно в полночь 13 марта покупать щенка.
Все-таки станете? Вы не сатанист, часом?
Еще приятнее запланировать выполнение нерегулярного или регулярного дела так, чтобы его делал кто-то другой. Например, сообщите сыну, что вы просите его завтра в полдень отправиться в клуб собаководов и купить там щеночка. Однократно. А потом (когда купит) скажите, что вы запланировали его (сына) прогулки с ним (щеночком) ежедневно - на годы вперед.
Системный администратор, даже если у него нет сына и щеночка, тоже не лишен радостей планирования. Так, для планирования однократных действий в любом UNIX используется программа at, а для регулярных - crontab.

at

Для планирования однократного запуска задач в строго определенное время (точность - одна минута) используется программа at. Она создает и изменяет список задач для выполнения, размещая его в каталоге /var/spool/cron/atjobs/. В Solaris это именно такой каталог, в других системах местоположение очереди задач может быть иным. Список задач ежеминутно инспектируется демоном cron, который отвечает за своевременный запуск задач. Во многих других системах UNIX демон cron не отвечает за задания, запланированные с помощью at, а для последних имеется специальный демон-запускатель - atd.
Чтобы at могла верно запланировать задачи, следует указать ей время и дату запуска задачи:

at time date

Параметр time может быть задан в форме HH:MM (часы:минуты), или словом midnight, noon, now, или временем с суффиксом AM или PM в североамериканском формате. Дата должна быть либо в формате название_месяца день [год], либо MMDDYY, либо MM/DD/YY, либо DD.MM.YY. Также можно указать время в виде now+ n единицы, где единицы - это minutes, hours, days, weeks. Можно указать для времени суффикс today или tomorrow.
Указание time без date означает выполнение задачи в текущие сутки, а если time сегодня уже прошло, - назавтра в указанное время.
Программа at принимает список задач для выполнения во входной поток.
at -l (или atq) распечатывает список поставленных в очередь задач.
at -r позволяет удалить задачу по идентификатору, который показывает at -l.
В некоторых системах at -r называется atrm. В Solaris приемлемы оба варианта.
Суперпользователь всегда может воспользоваться at.
Обычному пользователю разрешается использовать at в случае, если его имя указано в файле /usr/lib/cron/at.allow. Если этого файла нет, то проверяется, нет ли имени пользователя в /usr/lib/cron/at.deny (если есть, ему запрещается использование at). Если ни одного из этих двух файлов нет, пользоваться at разрешается только пользователям, которым назначена роль solaris.jobs.user (по умолчанию - root). Если есть только файл /usr/lib/cron/at.deny и он пуст, то по умолчанию всем разрешено пользоваться at. В файлах at.deny и at.allow имена пользователей пишутся по одному в строке.
Задания at и crontab заблокированного пользователя не запускаются - демон cron запустит задания только того пользователя, который имеет легальный доступ в систему в настоящее время, как отражено в файле /etc/shadow.
Задание, запущенное на выполнение демоном cron, выполняется от имени пользователя, который поставил задание в очередь. Стандартный вывод и стандартный поток ошибок задания cron высылает почтой этому пользователю. Можно указать иное место для вывода информации с помощью ключа m команды at или с помощью параметра в файле crontab (см. ниже). Запланированные задачи выполняются в среде командного процессора /bin/sh без назначения управляющего терминала (т.е. вне терминальной группы, связанной с конкретным терминалом).
Проведем небольшой эксперимент. Вначале убедимся, что каталог, где сохраняются задания at, пуст:

#ls /var/spool/cron/atjobs/
#

Проверим время и дату:

date
Сбт 15 Май 2004 19:10:29

Запланируем создание файла в корневом каталоге через две минуты:

at 1912
at> touch /tuition
at> <Ctrl-D>
commands will be executed using /sbin/sh
job 1084633920.a at Сбт Май 15 19:12:00 2004

В каталоге, где собираются задания в очереди на выполнение, появился новый файл:

ls /var/spool/cron/atjobs/
1084633920.a

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

at -l
user = root   1084633920.a  Сбт Май 15 19:12:00 2004

Пока в корневом каталоге файла tuition нет:

ls /
bin     devices        lib     opt     tmp     xfn
boot    etc     lost+found     platform       TT_DB
cdrom   export  mnt     proc    usr
core    home    net     sbin    var
dev     kernel  nsmail  test    vol

Почему? Да время еще не наступило:

date
Сбт 15 Май 2004 19:11:42

Дожидаемся заданного времени и (о чудо!) файл /tuition появился! Смотрите:

date
Сбт 15 Май 2004 19:12:12
 
ls /
bin     devices        lib     opt     tmp     vol
boot    etc     lost+found     platform       TT_DB   xfn
cdrom   export  mnt     proc    tuition
core    home    net     sbin    usr
dev     kernel  nsmail  test    var

cron

Демон cron ежеминутно инспектирует таблицу запланированных задач и выполняет те задачи, время которых наступило (в Solaris - не более 100 задач в минуту). Программа at нужна, как видно из раздела "at" выше, для планирования однократных задач, а программа crontab служит для планирования периодически запускаемых процессов. Они подготавливают таблицу заданий для cron.
У каждого пользователя есть своя таблица crontab. Ее можно отредактировать командой crontab -e. По этой команде вызывается текстовый редактор (обычно - vi), а в качестве файла для редактирования окажется таблица crontab. Если вы раньше не задавали никаких периодических задач, файл будет пустым.
Формат таблицы crontab: каждая строка описывает одну задачу, в строке содержится шесть полей:

mm      hh      dd      mo      dw      command

mm - минуты от 0 до 59;
hh - часы от 0 до 23;
dd - числа от 1 до 31;
mo - месяцы от 1 до 12;
dw - дни недели от 0 до 7, 0 и 7 - это воскресенье;
command - команда командному процессору, которую надо запустить (возможно, с аргументами).
Каждое числовое поле в таблице может содержать число, несколько чисел через запятую, диапазон (начало и конец диапазона через дефис) или звездочку. Звездочка в соответствующем поле означает "каждую единицу времени", например в поле часов она означает "каждый час".
Если в строке указаны определенное число месяца и определенный день недели, то для выполнения команды достаточно, чтобы наступило либо это число, либо этот день недели.
Так, строка

12 10 * * 0 rm -rf /var/log/*.[0-9]

означает, что в 10:12 каждое воскресенье нужно удалять файлы *.[0-9] из /var/log.
Однако, если было бы написано

12 10 10 * 0 rm -rf /var/log/*.[0-9]

то требовалось бы выполнять такое удаление "в 10:12 по воскресеньям и десятым числам", а не "в 10:12 десятого числа, если оно приходится на воскресенье".
Как и в случае с at, команда запускается от имени владельца таблицы, в качестве командного процессора используется /bin/sh.
В первых строках таблицы могут быть установлены переменные среды окружения. Наиболее полезной может оказаться переменная среды окружения PATH:

PATH=/usr/bin:/usr/sbin:/usr/local/bin

В ней можно задать каталоги, которые по умолчанию не входят в PATH.
Кроме PATH можно установить переменные SHELL и HOME, а также MAILTO. По умолчанию HOME (домашний каталог) берется из /etc/passwd. Переменная LOGNAME устанавливается автоматически при запуске команды. Ей присваивается имя пользователя, от имени которого запускается команда. В BSD-системах она может называться USER, в Solaris есть обе переменные. LOGNAME и USER нельзя переопределить, HOME и SHELL - можно. Программа cron отправит сообщение владельцу таблицы crontab, если найдет повод это сделать (например, произошла ошибка выполнения команды). Если переменная MAILTO существует и ее значение отлично от пустой строки, то cron расценит это значение как имя адресата, которому надо послать письмо вместо пользователя, запланировавшего задачу. Если значение переменной MAILTO - пустая строка, то почта послана не будет. Установка любой переменной среды окружения в таблице crontab осуществляется так:

имя_переменной = значение

пробелы вокруг знака равенства необязательны, а пробелы после значения будут трактоваться как часть значения. Поэтому значение лучше заключать в апострофы или кавычки для явного указания пробелов в начале и конце значения.
Для просмотра таблицы crontab используйте команду crontab -l, для удаления таблицы - crontab -r. Можно создать файл с таблицей crontab заранее и установить ее в систему командой

crontab имя_файла_таблицы. 

Такая команда потенциально опасна: если раньше существовали какие-либо команды в таблице crontab, то они потеряются навсегда.

Регулярно выполняемые системные скрипты

В Solaris нет стандартно принятых по умолчанию регулярно выполняемых скриптов. Однако рекомендуется их создать и расположить в каталоге /var/admin/cron/ или /etc/periodic/.

crontab -e 
22 * * * * /var/admin/cron/hourly 
22 22 * * * /var/admin/cron/daily 
2 22 * * 0 /var/admin/cron/weekly 
2 2 1 * * /var/admin/cron/monthly

В скрипт hourly рекомендуется включать проверку состояния сетевого подсоединения (ping), проверку и при необходимости установку прав доступа к почтовым ящикам пользователей, проверку состояния основных демонов (syslog, sendmail, named, sshd) с помощью ps, архивацию и обновление файлов протоколов (log rotation), которые достаточно выросли за час (рекомендуемый размер файла протокола для архивации - 1-2 мегабайта, но вы можете выбрать иное, исходя из удобства последующего анализа этого файла).
В скрипт daily включают проверку очереди сообщений (не слишком ли велика - запустите mailq), синхронизацию системного времени (ntpdate, rdate).
В скрипт weekly включают проверку свободного места на диске (если у вас это приходится делать чаще, чем раз в неделю, имеет смысл подумать о покупке нового диска, а может быть, и двух сразу), проверку файлов passwd, shadow, hosts.allow и hosts.deny, файлов конфигурации ftpd, sendmail, протоколов utmp и wtmp на предмет прав доступа и размера.
Ежемесячный скрипт monthly обычно содержит архивацию и обновление тех файлов протоколов, которые растут медленно.
Вы можете включить в эти скрипты свои задачи, которые являются специфическими для конкретной системы - проверку конфигурации smbd для файлового сервера samba, проверку дисковых квот пользователей, контроль появления свежих файлов с установленным битом SUID и так далее.

 

 
На главную | Содержание | < Назад....Вперёд >
С вопросами и предложениями можно обращаться по nicivas@bk.ru. 2013 г.Яндекс.Метрика