Дерево каталогов
Файлы в UNIX разложены по каталогам. Каталоги образуют древовидную структуру: есть корневой каталог, который обозначается знаком "/" (слэш), и его подкаталоги. В каждом из последних есть свои подкаталоги и т.д. Ограничений на число файлов в каталоге нет. Разные каталоги ("ветви" дерева каталогов) могут размещаться на разных дисках, это незаметно для пользователя. Чтобы обратиться к файлу, не нужно знать о том, на каком физическом устройстве или разделе диска он записан. Это значит, что лихорадочный поиск по дискам С:, D: E:, K:, R:, Y: не знаком человеку, работающему с UNIX. Он лихорадочно ищет потерянные файлы в густой кроне UNIX-каталогов, начиная от корня.
Между прочим, забавно, что уже много лет все упорно называют деревом структуру каталогов, у которой корень находится наверху, а его ближайшие отростки-подкаталоги называются каталогами верхнего уровня: Кто из нас видел деревья, растущие кронами вниз?
Файлы разделов дисков в Solaris
Мы предполагаем, что читатель знаком с физическим устройством жестких дисков, поэтому здесь не объясняются термины "головка", "дорожка", "цилиндр", "сектор" и другие. Все они являются общими для описания любых жестких дисков в любых компьютерах, независимо от архитектуры или используемой операционной системы.
Жесткий диск принято делить на разделы (в Solaris их называют slices). Раздел - это группа расположенных рядом цилиндров. Смысл разделения диска на разделы состоит в том, чтобы:
минимизировать расстояние, которое потребуется головке диска для считывания фрагментов одного файла;разделить данные разных типов, чтобы обезопасить системные данные от возможной порчи пользовательскими программами;зарезервировать под системные нужды достаточное пространство на диске так, чтобы несистемные файлы не могли его занять.
В Solaris на одном физическом жестком диске может быть до восьми разделов, которые принято нумеровать цифрами от 0 до 7.
Каждому разделу соответствует свой файл устройства в каталоге /dev/dsk. Пространство под разделы выделяется цилиндрами. Раздел однозначно определяется номерами начального и конечного цилиндров. В Solaris принята следующая концепция именования таких файлов устройств: в имени устройства учитываются номер контроллера, SCSI ID (target number), номер диска (LUN - Logical Unit Number) и номер раздела на диске (см. рис. 5.1). Если это диск IDE, то роль SCSI ID играет пара master/slave (соответственно, 0/1). Для встроенных дисков SCSI и любых дисков IDE номер диска равен 0. Это иллюстрирует рис. 5.2.
Рис. 5.1. Формирование имени устройства - раздела SCSI-диска
Рис. 5.2. Конфигурация с IDE-устройствами
Так, для системы с дисками SCSI /dev/dsk/c0t0d0s0 будет указывать на нулевой контроллер SCSI (c0), диск со SCSI ID 0 (t0), диск номер 0 на этом SCSI контроллере (d0), нулевой раздел на этом диске (s0).
Как показано на рис. 5.2, при создании файла устройства для раздела, который находится на IDE-диске, в названии файла учитываются номер адаптера IDE (как правило, в компьютерах x86 используют системные платы с одним адаптером, который поддерживает два канала IDE), номер канала (он кодируется как SCSI ID, как показано в табл. 5.1), номер диска (всегда d0) и номер раздела (первый раздел на диске - s0 и т.д., подобно разделам на SCSI-дисках).
0 | primary master |
1 | primary slave |
2 | secondary master |
3 | secondary slave |
Сказанное выше об именовании файлов устройств дисков IDE относится к системам на платформе SPARC. На платформе х86 файлы устройств, соответствующие разделам дисков IDE, именуются несколько иначе. Файлы, соответствующие разделам fdisk, обозначаются cNdMpK, где после с идет номер контроллера, после d - номер диска, а после p - номер раздела fdisk. На каждом из разделов fdisk может быть создано несколько подразделов (slices), если этот раздел fdisk является разделом типа Solaris. Любой раздел fdisk имеет свой тип, он указывается в таблице Master Boot Record (MBR), в которой описаны все разделы fdisk-диска.
По умолчанию при установке Solaris на IDE-диск на платформе IA (x86) программа-установщик создает два раздела fdisk - загрузочный (примерно 20 Мб) с программой-загрузчиком и раздел, на котором будут находиться все остальные части системы, а также пользовательские файлы. Первый раздел fdisk имеет тип FAT, а второй - тип Solaris. На втором разделе создаются подразделы (slices). Они именуются по такому же принципу, как и разделы на дисках систем SPARC, но без указания SCSI ID: c0d0s0, c0d0s1 и т.д.
Каждому файлу из каталога /dev/dsk соответствует файл устройства прямого доступа (raw disk) в каталоге /dev/rdsk:
# ls /dev/dsk c0d0p0 c0d0s1 c0d0s15 c0d0s7 c1t0d0p3 c1t0d0s12 c1t0d0s4 c0d0p1 c0d0s10 c0d0s2 c0d0s8 c1t0d0p4 c1t0d0s13 c1t0d0s5 c0d0p2 c0d0s11 c0d0s3 c0d0s9 c1t0d0s0 c1t0d0s14 c1t0d0s6 c0d0p3 c0d0s12 c0d0s4 c1t0d0p0 c1t0d0s1 c1t0d0s15 c1t0d0s7 c0d0p4 c0d0s13 c0d0s5 c1t0d0p1 c1t0d0s10 c1t0d0s2 c1t0d0s8 c0d0s0 c0d0s14 c0d0s6 c1t0d0p2 c1t0d0s11 c1t0d0s3 c1t0d0s9
# ls /dev/rdsk c0d0p0 c0d0s1 c0d0s15 c0d0s7 c1t0d0p3 c1t0d0s12 c1t0d0s4 c0d0p1 c0d0s10 c0d0s2 c0d0s8 c1t0d0p4 c1t0d0s13 c1t0d0s5 c0d0p2 c0d0s11 c0d0s3 c0d0s9 c1t0d0s0 c1t0d0s14 c1t0d0s6 c0d0p3 c0d0s12 c0d0s4 c1t0d0p0 c1t0d0s1 c1t0d0s15 c1t0d0s7 c0d0p4 c0d0s13 c0d0s5 c1t0d0p1 c1t0d0s10 c1t0d0s2 c1t0d0s8 c0d0s0 c0d0s14 c0d0s6 c1t0d0p2 c1t0d0s11 c1t0d0s3 c1t0d0s9
В Solaris принято, что раздел номер 2 (slice 2) представляет собой весь диск, т.е. является репрезентацией всего диска в целом, со всеми его разделами. Иначе говоря, на диске на самом деле может быть создано до 7 разделов, а восьмой (раздел 2) всегда охватывает все эти разделы вместе. Поэтому в разделе 2 нельзя создать файловую систему и записывать туда файлы: он служит для системных надобностей. В частности, в структурах, адресуемых через раздел 2, хранятся сведения о диске в целом: реальный размер, число цилиндров и т.п.
Замечание о разных типах имен устройств можно проиллюстрировать на примере именования разделов диска. Так, разделам SCSI-диска со SCSI ID, равным 6, присоединенным к нулевому контроллеру, будут соответствовать логические имена устройств (разделов диска) от /dev/dsk/c0t6d0s0 до /dev/dsk/c0t6d0s7, физические имена от /devices/pci@1f,0/pci@1,1/scsi@6/sd@0,0:a до /devices/pci@1f,0/pci@1,1/scsi@6/sd@0,0:g. При этом диску в целом будет соответствовать экземплярное имя sd6.
Файлы устройств Solaris
Каждому физическому устройству в Solaris обязательно соответствует файл устройства. Файл устройства по сути - это указатель на область кода ядра, в которой находится драйвер устройства. Файлы устройств располагаются в каталоге /dev и его подкаталогах. Такое расположение является стандартным для всех систем UNIX. Однако на самом деле в Solaris все файлы в каталоге /dev являются символическими ссылками на "настоящие" файлы устройств, которые располагаются в подкаталогах каталога /devices. Там эти файлы сгруппированы по отношению к своему месту в конфигурации компьютера. Подробнее это рассматривается ниже в разделе "Каталог /devices". О символических ссылках говорится также в лекции 5 раздела "Ссылки".
Файлы устройств имеют специальные типы: файл символьного устройства и файл блочного устройства.
Вывод программы ls иллюстрирует это:
ls -l /devices/pseudo/ ... crw-rw-rw- 1 root sys 26, 0 Мар 17 10:56 ptsl@0:ttyp0 crw-rw-rw- 1 root sys 26, 1 Мар 17 10:56 ptsl@0:ttyp1 crw-rw-rw- 1 root sys 26, 2 Мар 17 10:56 ptsl@0:ttyp2 crw-rw-rw- 1 root sys 26, 3 Мар 17 10:56 ptsl@0:ttyp3 ... ls -l /devices/pci@0,0/pci-ide@7,1/ide@0 ... brw-r----- 1 root sys 102, 0 Мар 17 10:56 cmdk@0,0:a crw-r----- 1 root sys 102, 0 Мар 17 10:56 cmdk@0,0:a,raw brw-r----- 1 root sys 102, 1 Мар 24 21:19 cmdk@0,0:b crw-r----- 1 root sys 102, 1 Мар 17 10:56 cmdk@0,0:b,raw ...
Файл устройства является псевдофайлом, он не размещен на диске, о нем есть только запись, которая используется при доступе к устройству. Первое число, которое стоит в поле длины файла в выводе программы ls для файлов устройств, - это major-номер, а второе, после запятой - minor-номер. Первый из них означает номер типа устройств и одновременно - позицию в ядре, в которой следует искать драйвер устройства. Второй - номер экземпляра устройства данного типа. Поэтому файлы однотипных устройств в вышеприведенном выводе ls имеют одинаковые major-номера.
Устройство каждого типа имеет свой major-номер. Major-номера назначаются автоматически программой add_drv. Соответствие имени драйвера и major-номера определяется в файле /etc/name_to_major.
В Solaris каждое устройство имеет три разных имени: логическое имя, физическое имя и экземплярное имя.
Логические имена - это имена файлов устройств, которые хранятся в /dev.
Физические имена - это имена файлов устройств, хранящихся в /devices.
Экземплярные имена - это укороченные физические имена устройств, которые ядро назначает устройствам.
Ниже рассмотрен пример назначения всех перечисленных типов имен.
Элементы файловой системы
Файловая система каждого из разделов диска состоит из нескольких структурных элементов. Это суперблок, таблица индексных дескрипторов, блоки описания файлов, блоки, содержащие списки управления доступом к файлам (ACL - Access Control Lists), каталоги и собственно файлы.
Термин "файловая система" в литературе используется для обозначения трех разных понятий:
Во-первых, файловая система - это набор правил и конструкций, описывающих то, как сохраняются файлы на диске. В этом смысле мы употребляем, например, выражение "файловая система FAT32", и "файловая система" здесь тождественна понятию "тип файловой системы".Во-вторых, файловая система - это совокупность всех файлов, хранимых в компьютере.В-третьих (и это значение термина характерно именно для UNIX-систем) файловая система - это совокупность всех файлов на разделе диска или устройстве.
В этой книге мы будем говорить о файловых системах во всех трех смыслах, и там, где из контекста неясно, что именно имеется в виду, будем отдельно оговаривать, в каком смысле мы употребляем это выражение.
Файловая система UFS содержит четыре основных компонента с управляющей информацией: загрузочный блок, суперблок, таблицу индексных дескрипторов (i-node table) и каталоги. Кроме того, в Solaris (начиная с версии 2.5, с 1995 года1)) в файловой системе хранятся списки управления доступом (ACL). Хранение списков ACL обеспечивают так называемые теневые индексные дескрипторы (shadow inodes).
В System V каждый раздел жесткого диска форматируется (размечается) для размещения на нем файловой системы UNIX, в BSD - один раздел жесткого диска разбивается на подразделы, каждый из которых форматируется. Мы называем "разделом UNIX" такой размеченный в формате файловой системы UNIX раздел или подраздел.
Загрузочный блок (boot block) - это, как правило, часть метки диска (disk label). В загрузочном блоке записана маленькая программа, которая при старте системы загружает ядро ОС с диска в оперативную память. Загрузочный блок располагается в первом секторе диска. Загрузочный блок имеет смысл только для первого раздела жесткого диска, однако место для него резервируется в каждом разделе.
Суперблок содержит общую информацию о файловой системе как совокупности файлов на данном разделе жесткого диска, в частности, размере раздела UNIX, числе свободных и занятых блоков и индексных дескрипторов, флаге целостности файловой системы. Этот флаг устанавливается при успешном завершении работы с файловой системой, например, при корректной остановке операционной системы. В случае, если компьютер выключили рубильником, не дождавшись корректной остановки системы, при следующем старте системы программа fsck автоматически начнет проверку дисков и выдаст сообщение "clean flag is not set in superblock". Копии суперблока записываются в нескольких блоках внутри каждого раздела для большей надежности. В файловой системе UFS записывается по одной копии суперблока на каждую группу цилиндров. Если выяснится, что оригинал суперблока в начале раздела поврежден, будет использована копия суперблока.
Таблица индексных дескрипторов (i-node table) содержит дескрипторы файлов. Дескриптор файла содержит сведения о типе файла, размещении файла на диске, правах доступа к нему, UID владельца файла, GID группы файла, время последнего доступа к файлу, время последней модификации файла, время последней модификации самого индексного дескриптора. Подробнее структура таблицы индексных дескрипторов рассмотрена в подразделе "Таблица индексных дескрипторов: детали".
Размер индексного дескриптора фиксирован и составляет в Solaris в UFS 128 байт.
Размер таблицы индексных дескрипторов фиксирован и задается при создании файловой системы на разделе. Программе mkfs (и, соответственно, newfs) можно явно указать требуемое количество байт данных, которые должны приходиться на один индексный дескриптор, что определит количество индексных дескрипторов на разделе. Например, если раздел состоит из 1000000 байт, и число байт на дескриптор составляет 1000, то будет создано 1000 индексных дескрипторов.
Каталог /devices
Каталог /devices отражает аппаратную конфигурацию компьютера. Дерево его подкаталогов строится в соответствии с реальными подключениями устройств к шинам и контроллерам. Поэтому для компьютеров различных архитектур структура дерева подкаталогов /devices будет разной. Содержание этих подкаталогов будет разным для разных компьютеров, даже если они имеют одинаковую архитектуру, потому что компьютеры могут иметь разную конфигурацию: неодинаковое количество жестких дисков, различные контроллеры интерфейсов (SCSI, IDE), по-разному подсоединенные к ним диски. Например, для компьютера x86 дерево может быть таким:
./pseudo ./isa ./isa/fdc@1,3f0 ./isa/i8042@1,60 ./pci@0,0 ./pci@0,0/pci8086,7191@1 ./pci@0,0/pci-ide@2,1/ide@0 ./pci@0,0/pci-ide@2,1/ide@1 ./pci@0,0/pci-ide@2,1
Это пример дерева каталогов Solaris 9, установленного на ноутбук IBM ThinkPad 390X.
Полный список всех устройств компьютера, с которыми система Solaris готова работать, содержится в файле /etc/path_to_inst.
Файл /etc/path_to_inst содержит соответствия физических имен устройств и номеров экземпляров устройств (тех, что называются minor-номерами устройств). Чтобы эти соответствия сохранялись от загрузки к загрузке, система записывает их в файл /etc/path_to_inst. Этот файл во время загрузки доступен только для чтения, он может быть изменен с помощью программ add_drv(1M) и drvconfig(1M).
Обычно системному администратору незачем изменять этот файл. Для просмотра полного списка устройств следует использовать команду prtconf:
prtconf
Для просмотра списка устройств, фактически работающих в системе, используйте
prtconf | grep -v not
Это позволяет отфильтровать в выводе prtconf строки, содержащие слово "not", например, "device not attached". Более подробно об изменении аппаратной конфигурации и добавлении драйверов устройств говорится в лекции 1 курса "Администрирование ОС Solaris".
Количество индексных дескрипторов в файловой системе
Количество индексных дескрипторов в создаваемой файловой системе типа UFS можно задать посредством указания параметра с ключом -i:
newfs -i nbpi raw_deivce_name
Например
newfs -i 2048 /dev/rdsk/c0d0p0
Параметр nbpi обозначает число байтов, приходящихся на один индексный дескриптор1), что при известном объеме диска однозначно определяет число индексных дескрипторов в файловой системе.
Программы mkfs и newfs поддерживают еще ряд ключей, которые позволяют гибко описывать параметры создаваемой файловой системы.
Man lofiadm (как работать с образом диска)
Для работы с образом диска, записанным в файл, может оказаться полезной программа lofiadm, которая позволяет настроить обращение к файлу как к блочному устройству.
Эта программа управляет драйвером lofi, который позволяет связать файл с блочным псевдоустройством. После этого содержимое файла будет доступно посредством обращения к файлу этого блочного устройства. У системы будет полное впечатление, что это и есть устройство и его можно монтировать с помощью mount, проверять на корректность записей на нем с помощью fsck и т.п.
Программу lofiadm следует использовать для добавления таких псевдоустройств, удаления связи файла и псевдоустройства и вывода информации о таких устройствах в системе.
Например, можно смонтировать образ компакт-диска стандарта ISO, лежащего в файле ex.iso:
lofiadm -a /home/ivan/ex.iso /dev/lofi/1
Затем можно смонтировать новое устройство в системе:
mount -F hsfs -o ro /dev/lofi/1 /mnt
и проверить, видно ли оно:
df -k /mnt Filesystem kbytes used avail capacity Mounted on /dev/lofi/1 512418 512418 0 100% /mnt
Для демонтирования псевдоустройства и его удаления из системы следует дать следующие команды:
umount /mnt lofiadm -d /dev/lofi/1
Обратите внимание на возможность создания файловой системы на псевдоустройстве и появлении устройства прямого доступа (rlofi, аналогично rdsk) после выполнения lofiadm -a:
lofiadm -a /export/home/test /dev/lofi/1 newfs /dev/rlofi/1 newfs: construct a new file system /dev/rlofi/1: (y/n)? y /dev/rlofi/1: 71638 sectors in 119 cylinders of 1 tracks, 602 sectors 35.0MB in 8 cyl groups (16 c/g, 4.70MB/g, 2240 i/g) super-block backups (for fsck -F ufs -o b=#) at: 32, 9664, 19296, 28928, ...
К файлу, который смонтирован в качестве псевдоустройства с помощью lofiadm, нельзя обращаться напрямую, как к файлу. Это аналогично тому, что нельзя напрямую обращаться к диску для записи файла, а следует делать это через драйвер файловой системы. Надлежит устанавливать такие права доступа к файлам, монтируемым как устройства, чтобы предотвратить несанкционированный доступ к ним как к обычным файлам.
После перезагрузки связь файла и псевдоустройства теряется; если требуется сделать ее постоянной, надо написать скрипт, который будет запускаться при загрузке и добавлять соответствующее псевдоустройство в систему, а затем его монтировать.
Возможность управлять псевдоустройствами зависит от прав доступа к файлу /dev/lofictl. По умолчанию правом монтирования и демонирования псевдоустройств обладает только root.
Монтирование дискет и прочих сменных носителей
Для монтирования дискет, компакт-дисков и других сменных носителей в Solaris имеется специальная программа vold (Volume Management daemon). Она следит за тем, вставлен ли компакт-диск, дискета или, к примеру, zip-диск в соответствующее устройство. Как только диск оказывается в устройстве, vold вызывает программу volcheck, чтобы проверить, действительно ли в привод установили новый диск, а затем программу rmmount для монтирования диска в заранее определенную точку монтирования. Программа rmmount выясняет тип файловой системы вставленного диска, и, если этот тип поддерживается, монтирует диск. Список предопределенных точек монтирования можно посмотреть с помощью
man rmmount
Поведение rmmount определяется файлом конфигурации /etc/rmmount.conf.
Программу rmmount можно запускать и вручную. Кроме того, можно использовать команду volrmmount для форсирования операций перемонтирования или демонтирования файловой системы на сменном носителе. Более подробно об этой команде говорится в man volrmmount.
Монтирование и демонтирование файловых систем
При старте системы после загрузки ядра и запуска процесса init инициируется проверка тех файловых систем, которые следует проверить и смонтировать автоматически. Их список содержится в файле /etc/vfstab1). Типичный файл /etc/vfstab выглядит так:
#device device mount FS fsck mount Mount #to mount to fsck point type pass at boot Options # Fd - /dev/fd fd - no - /proc - /proc proc - no - /dev/dsk/c0d0s1 - - swap - no - /dev/dsk/c0d0s0 /dev/rdsk/c0d0s0 / ufs 1 no - /dev/dsk/c0d0p0:boot - /boot pcfs - no - /dev/dsk/c0d0s7/ dev/rdsk/c0d0s7 /export/home ufs 2 yes - swap - /tmp tmpfs - yes -
Те файловые системы, которые в столбце mount at boot отмечены как yes, будут проверены и смонтированы при старте системы. Файловую систему можно смонтировать в любой момент, надо лишь указать ей в качестве точки монтирования пустой каталог, который уже создан и доступен в системе. Операцию монтирования и демонтирования файловой системы может осуществить только root.
Монтирование файловой системы выполняется командой mount:
mount device mount_point
Например
mount /dev/dsk/c0d1s0 /test
Для монтирования файловой системы, которая описана в /etc/vfstab, можно не указывать имя файла устройства, а сразу указать точку монтирования. Такую "сокращенную" команду mount можно применять только для монтирования файловых систем, перечисленных в /etc/vfstab.
При монтировании файловой системы следует явно указывать ее тип, если он отличается от UFS.
Демонтирование файловой системы делает ее недоступной для чтения и записи, файлы, которые расположены на демонтируемом разделе, конечно же, остаются на месте. Просто после демонтирования они не видны: точка монтирования снова превращается в пустой каталог, как это было до монтирования в нее диска или раздела.
Нельзя демонтировать занятую файловую систему. Занятой считается такая файловая система, файл которой открыт в настоящее время кем-то из пользователей, или каталог которой является текущим каталогом кого-то из работающих в системе пользователей.
Чтобы все-таки демонтировать файловую систему, следует найти и устранить причину ее занятости. Часто для этого достаточно просто самому выйти из того каталога, который собираешься демонтировать. Это типичная ошибка системного администратора: пытаться демонтировать /usr в тот момент, когда находишься в /usr/admin или подобном подкаталоге, который лежит в том же разделе, что и /usr.
Демонтирование файловой системы выполняется командой umount:
umount mount_point
Например
umount /mnt
Обычные индексные дескрипторы
Обычные индексные дескрипторы (i-nodes) используются повсюду во всех системах UNIX. В Solaris существует специальный тип индексных дескрипторов - теневые индексные дескрипторы. Они служат для хранения информации о расширенных правах доступа к файлам и каталогам.
Поддерживаемые типы файловых систем
Основной ("родной") файловой системой Solaris является UFS (Unix File System). Всего Solaris 9 поддерживает 13 файловых систем, перечисленных в таблице 5.2.
UFS | обычная | диск | родная файловая система Solaris |
VxFS | обычная | диск | журналируемая система от Veritas Corp |
QFS | обычная | диск | файловая система от LSC Inc. |
pcfs | обычная | диск | MSDOS FAT и FAT32 |
hsfs | обычная | диск | файловая система High Sierra (для CD-ROM); она же - ISO9660 |
tmpfs | обычная | память | использует оперативную память и область свопинга |
nfs | псевдосистема | сеть | файловая система для монтирования каталогов на других компьютерах (подобно разделяемым каталогам Windows) |
cachefs | псевдосистема | другая ФС | использует локальный диск для кэширования удаленной файловой системы NFS |
autofs | псевдосистема | другая ФС | использует динамические объекты для монтирования других файловых систем |
specfs | псевдосистема | драйверы | файловая система файлов устройств /dev |
procfs | псевдосистема | ядро | /proc - отображение процессов в структуру ФС |
sockfs | псевдосистема | сеть | соединения типа "сокет" |
fifos | псевдосистема | файлы | программные каналы (pipe API) |
В довольно старых версиях UNIX поддерживалась всего одна файловая система. С увеличением разнообразия носителей возникла необходимость поддержки разнородных файловых систем на носителях разной природы. Так в 1985 году компания Sun Microsystems пришла к реализации концепции виртуальной файловой системы.
Виртуальная файловая система представляет собой абстрактную файловую систему, которая позволяет операционной системе одинаковым образом обращаться к файловым системам разных типов.
К 1985 году операционные системы фирмы Sun использовали Berkeley Fast Filesystem (FFS). Эта файловая система базировалась на концепции индексных дескрипторов, которая органично трансформировалась в концепцию виртуальных индексных дескрипторов в новой файловой системе UFS, вобравшей в себя структуру FFS и новые идеи организации виртуальной файловой системы. Взаимодействие независимого от конкретного типа файловой системы уровня виртуальной файловой системы и файловых систем строго определенных типов иллюстрирует рисунок 5.5.
Рис. 5.5. Структура виртуальной файловой системы Solaris
Файловая система UFS с 1985 года претерпела некоторые изменения. Так, начиная с выпуска Solaris 9 8/03 поддерживаются многотерабайтные разделы, в то время как до этого UFS в Solaris могла работать только с разделами размером до 1 Тб. В настоящее время большие разделы поддерживаются только в 64-разрядной версии Solaris 9.
Файловые системы UFS, VxFS и QFS, поддерживаемые в Solaris, отличаются по некоторым важным параметрам, влияющим на их надежность и производительность. Различные файловые системы обладают разными алгоритмами выделения пространства под файлы, а также механизмами журналирования.
UFS | блоками (block) | да |
VxFS | экстентами (extent) | да |
QFS | экстентами (extent) | нет |
Выделение пространства блоками позволяет минимизировать фрагментацию файловой системы, в то время как выделение пространства экстентами (большими частями пространства диска, состоящими из многих блоков) - снизить объем служебной информации, которая записывается на диск.
В файловой системе UFS размер блока может составлять от 512 байт до 8192 байт, по умолчанию в Solaris принят размер 8192 байт
В Solaris поддерживается журналирование (logging) файловых систем UFS и VxFS. Журналирование позволяет записывать в журнал информацию обо всех начатых транзакциях. Если транзакция (т.е. операция записи на диск) по каким-то причинам не была завершена (например, отключилось питание), то после перезапуска системы файловая система будет автоматически возвращена в состояние, в котором она была до начала транзакции. Подобную функциональность предоставляет файловая система ext3fs в Linux, reiserfs для FreeBSD и Linux и некоторые другие.
В последние годы непременным условием использования файловой системы стала поддержка современных дисков больших объемов и больших файлов. Если несколько лет назад "большим" назывался диск объемом в 1 гигабайт, то сейчас дисковые массивы объемом в несколько терабайт становятся обычными для систем среднего класса. Скоро они придут в системы малых офисов и в дома, а сети предприятий начнут работать с серверами, в которых установлены дисковые массивы, содержащие десятки и сотни терабайт информации. Что на это отвечают создатели файловых систем для UNIX?
С 1991 года файловая система UFS претерпела заметные изменения - появилась версия UFS2, которая пока поддерживается только во FreeBSD 5.0. В Solaris модификация файловой системы позволила достичь предела поддерживаемого дискового объема одного раздела UFS в 1 терабайт.
Проверка файловых систем
Широко известная из систем Windows программа scandisk имеет аналог в UNIX - программу fsck. В Solaris fsck по умолчанию проверяет все файловые системы, перечисленные в /etc/vfstab. Обычно имеет смысл запускать fsck вручную с указанием конкретной файловой системы:
fsck /dev/dsk/c0d0s7
Программа fsck проверяет файловую систему и, если находит ошибки, исправляет их. Обнаружив ошибки, об исправлении которых она не может принять самостоятельное решение, fsck выдает сообщение об этом на терминал, с которого ее запустили, и ждет решения администратора.
Если в настоящий момент файловая система смонтирована, fsck не начинает ее проверку. Это правило можно обойти, если потребовать от fsck обращаться к диску как к символьному устройству, а не как к блочному:
fsck /dev/dsk/c0d0s7 /dev/dsk/c0d0s7 is a mounted file system, ignored fsck /dev/rdsk/c0d0s7 ** /dev/rdsk/c0d0s7 ** Currently Mounted on /export/home ** Phase 1 - Check Blocks and Sizes ** Phase 2 - Check Pathnames ** Phase 3 - Check Connectivity ** Phase 4 - Check Reference Counts ** Phase 5 - Check Cyl groups 2 files, 9 used, 3823540 free (20 frags, 477940 blocks, 0.0% fragmentation)
Разбиение диска на разделы
Каждый диск состоит из нескольких разделов. Все разделы, кроме раздела для свопинга, имеют точки монтирования. Вся файловая система UNIX представляет собой единое дерево. К нему можно присоединять (монтировать) новые "ветви".
Предположим, что для начала у нас есть только корень дерева (корневой раздел). Он изображен большим эллипсом. Мы можем присоединить к нашей файловой системе еще один раздел (в нем хранятся какие-то каталоги, но пока он не имеет имени в нашей файловой системе). Присоединяемый раздел обозначен малым эллипсом:
Рис. 5.3.
Для присоединения мы должны указать, в какое место существующей файловой системы (точку монтирования) следует смонтировать новый раздел. После монтирования все каталоги нового раздела будут доступны в качестве подкаталогов точки монтирования. При этом истинная структура файловой системы оказывается прозрачной для пользователя. После того как раздел смонтирован, пользователь не отличит каталоги одного раздела от каталогов другого. Предположим, мы смонтировали раздел в каталог /usr :
Рис. 5.4.
Посмотреть, какие разделы в какие точки монтирования присоединены, можно командой mount:
mount / on /dev/dsk/c0d0s0 read/write/setuid/intr/largefiles/xattr/onerror=panic/dev= 1980000 on Sat Jan 31 20:08:40 2004 /boot on /dev/dsk/c0d0p0:boot read/write/setuid/nohidden/nofoldcase/dev=19a3010 on Sat Jan 31 20:08:38 2004 /proc on /proc read/write/setuid/dev=2d80000 on Sat Jan 31 20:08:39 2004 /etc/mnttab on mnttab read/write/setuid/dev=2e40000 on Sat Jan 31 20:08:39 2004 /dev/fd on fd read/write/setuid/dev=2e80000 on Sat Jan 31 20:08:42 2004 /var/run on swap read/write/setuid/xattr/dev=1 on Sat Jan 31 20:08:45 2004 /tmp on swap read/write/setuid/xattr/dev=2 on Sat Jan 31 20:08:48 2004 /export/home on /dev/dsk/c0d0s7 read/write/setuid/intr/largefiles/xattr/onerror=panic/dev= 1980007 on Sat Jan 31 20:08:48 2004 /floppy/noname on /vol/dev/diskette0/noname read/write/setuid/nohidden/nofoldcase/dev=1740002 on Sat Jan 31 21:34:36 2004
Обратите внимание на то, что если каталог является точкой монтирования, то он находится на отдельном разделе, а если нет - то он расположен на том же разделе, что и родительский каталог. Например, каталог /usr расположен на отдельном разделе, а каталог /etc - в том же разделе, что и каталог /.
Разбиение диска на разделы производится в двух случаях: при установке системы и при подключении нового диска. Разбиение на разделы следует спланировать так, чтобы в будущем размеры разделов были достаточны для установки программ и размещения файлов данных. В Solaris должны быть созданы как минимум два раздела: корневой (root) раздел, монтируемый в файловой системе в корень ее дерева и обозначаемый символом "/" (слэш), и раздел для свопинга. Последний не имеет точки монтирования, так как не принадлежит к файловой системе и не размечается, а используется для прямых чтения страниц с диска и записи страниц на диск.
Для более надежной и быстрой работы системы принято, кроме упомянутых разделов, создавать разделы с точками монтирования /usr, /export/home и, возможно /opt. Далее мы будем называть разделы по именам точек монтирования (например, раздел /usr).
В корневом каталоге системы располагается несколько файлов и ряд обязательных для работы системы подкаталогов. Это подкаталоги /bin, /sbin, /dev, /devices, /etc, /tmp. Кроме того, обычно есть подкаталоги /usr и /opt, а также /export, они обычно являются точками монтирования других разделов.
Корневой каталог в типичной установке Solaris (набор программ Entire Distribution - подробнее см. лекции 3 и 4) занимает 200 Мб (при условии, что каталоги /usr, /var и /export/home размещены в других разделах). При установке системы ему следует выделить 300 Мб - с запасом. Каталог /usr займет не меньше 1400 Мб, /var - не менее 100 Мб. Для каталога /var имеет смысл выделить больше места, т.к. именно в нем будут содержаться быстро растущие в размере файлы протоколов, почтовые ящики пользователей и прочее. Приведенные объемы разделов справедливы для варианта установки с набором программ Entire Distribution.
Вообще говоря, перед планированием разделов следует подумать о том, как будет использоваться компьютер под управлением Solaris. Если это будет сервер Oracle, надо зарезервировать один неразмеченный (неотформатированный) раздел под базы данных Oracle. Если планируется сделать почтовый сервер, то следует отвести под раздел /var достаточно места для размещения всех почтовых ящиков в каталоге /var/mail, а если это будет файловый сервер, надо сделать отдельный большой раздел для хранения файлов пользователей (например, /export/home).
Таким образом, фактическое пространство, которое следует отвести под каталог /var, зависит от назначения компьютера. Исходя из собственного опыта, я всегда создаю для /var раздел размером как минимум 256 Мб в системах с небольшой нагрузкой (почтовый сервер, http-cache и ftp для сети из 10-50 компьютеров) и до 2-3 Гб в системах со средней нагрузкой (почтовый сервер, http-cache, СУБД типа MySQL, web-сервер с 5-10 виртуальными хостами в сети из 50-150 компьютеров).
При установке системы программа-установщик предложит вам разумные значения по умолчанию. Если специфика устанавливаемой системы требует изменений, можно нажать кнопку Modify в окне Lay Out File Systems и затем изменить размеры разделов там, где требуется. Окно Lay Out File Systems появляется ближе к концу работы установщика, после выбора типа установки. О типах установки (установка базового комплекта, установка полного комплекта ПО Solaris и т.п.) подробнее рассказано в лекциях 3 и 4.
При установке нового диска его разметку поможет провести программа format. Эта программа также может использоваться для получения информации о геометрии диска, для низкоуровнего форматирования SCSI-дисков и восстановления некоторой служебной информации после сбоев.
Разметка нового диска
Предположим, мы подключили новый диск, и это IDE primary slave диск. Для того чтобы создать на нем файловую систему, потребуется создать на новом диске разделы (по крайней мере один) и затем в каждом из разделов создать новую файловую систему.
Создание разделов на диске выполняется с помощью команды format или fdisk. Последняя применяется только для платформы x86. Однако из format можно вызвать fdisk, и предпочтительнее делать именно так. Почему - будет ясно из следующего описания.
После подключения нового диска нет надобности перенастраивать ядро Solaris, если диски этого типа в системе уже есть. Например, если у вас уже есть один IDE-диск и система с ним уже работает, незачем перезапускать систему с ключом r или создавать файл /reconfigure и перезапускаться для обнаружения нового устройства. Достаточно создать новые файлы устройств в каталогах /devices и /dev. Для этого в более ранних версиях Solaris использовалась программа disks, а в Solaris 9 следует запустить devfsadm. При запуске без параметров новый диск будет обнаружен и требуемые файлы будут добавлены в каталоги /devices, /dev/dsk и /dev/rdsk.
Теперь любая программа работы с диском, требующая файл устройства в каталоге /dev/rdsk, уже может работать с диском. Запустим программу format. В меню программы следует выбрать диск, а затем выбрать запуск fdisk. После этого мы будем работать в среде программы fdisk. Ее интерфейс нам знаком по другим системам, нужно лишь обратить внимание на то, что есть возможность создавать разделы нескольких типов. Если мы добавляем дополнительный диск для работы с ним из среды Solaris, то следует выбрать тип Solaris. Раздел на новом диске не должен быть помечен как "активный", если только с него не будет загружаться какая-нибудь система в будущем.
Можно запустить программу fdisk самостоятельно, без предварительного вызова программы format, но последняя все равно будет нужна на следующем этапе.
После создания раздела следует выйти из fdisk и в программе format выбрать partition->print.
Если определен размер только одного подраздела (partition), а именно - подраздела номер 2, это говорит о том, что для созданного раздела fdisk следует определить подразделы. Если это отвечает вашим намерениям, достаточно создать всего один подраздел размером с весь раздел fdisk. Это можно сделать через меню Partition программы format. Выбрав partition->номер подраздела (например, 0), будет легко задать его размер.
Теперь необходимо выбрать пункт label для записи получившейся таблицы разделов на диск.
После этого можно создать новую файловую систему на получившемся подразделе. Помните: разделы fdisk для Solaris - это лишь место для размещения подразделов типа Solaris (slices). А на этих подразделах как раз и существует файловая система UFS и располагаются файлы и каталоги. Файловую систему на новом диске создадим командой newfs.
Программа mkfs позволяет создавать файловые системы разных типов, включая UFS, а newfs является более удобным интерфейсом к mkfs исключительно для создания файловых систем UFS:
# newfs /dev/rdsk/c0d1s0 newfs: construct a new file system /dev/rdsk/c0d1s0: (y/n)? y /dev/rdsk/c0d1s0: 2060352 sectors in 2044 cylinders of 16 tracks, 63 sectors 1006,0MB in 128 cyl groups (16 c/g, 7,88MB/g, 3776 i/g) super-block backups (for fsck -F ufs -o b=#) at: 32, 16224, 32416, 48608, 64800, 80992, 97184, 113376, 129568, 145760, 161952, 178144, 194336, 210528, 226720, 242912, 258080, 274272, 290464, 306656, 322848, 339040, 355232, 371424, 387616, 403808, 420000, 436192, 452384, 468576, 484768, 500960, 516128, 532320, 548512, 564704, 580896, 597088, 613280, 629472, 645664, 661856, 678048, 694240, 710432, 726624, 742816, 759008, 774176, 790368, 806560, 822752, 838944, 855136, 871328, 887520, 903712, 919904, 936096, 952288, 968480, 984672, 1000864, 1017056, 1032224, 1048416, 1064608, 1080800, 1096992, 1113184, 1129376, 1145568, 1161760, 1177952, 1194144, 1210336, 1226528, 1242720, 1258912, 1275104, 1290272, 1306464, 1322656, 1338848, 1355040, 1371232, 1387424, 1403616, 1419808, 1436000, 1452192, 1468384, 1484576, 1500768, 1516960, 1533152, 1548320, 1564512, 1580704, 1596896, 1613088, 1629280, 1645472, 1661664, 1677856, 1694048, 1710240, 1726432, 1742624, 1758816, 1775008, 1791200, 1806368, 1822560, 1838752, 1854944, 1871136, 1887328, 1903520, 1919712, 1935904, 1952096, 1968288, 1984480, 2000672, 2016864, 2033056, 2049248,
Смонтируем получившуюся файловую систему в каталог /test:
# mount -F ufs /dev/dsk/c0d1s0 /test # ls test lost+found
Обратите внимание, при создании файловой системы в ней сразу создается каталог lost+found, это делается для того, чтобы при автоматическом восстановлении файлов после сбоя (при перезагрузке, например) программе fsck было куда записать потерявшиеся фрагменты файлов. Кроме того, в некоторые блоки (их список выводится при работе newfs или mkfs) записана резервная копия суперблока новой файловой системы.
Таблица индексных дескрипторов: детали
В ранних версиях UNIX таблица индексных дескрипторов занимала фиксированное пространство в начале устройства; в файловых системах UFS современных систем эта таблица распределена по диску, потому что каждая часть таблицы отвечает за часть диска.
В файловых системах, которые основаны на FFS (ext2, ext3, UFS), диск разбит на группы цилиндров. Каждая группа цилиндров имеет свою копию суперблока, битовую карту свободных блоков этой группы цилиндров и таблицу индексных дескрипторов для файлов, расположенных на цилиндрах этой группы. Такая структура хороша тем, что, во-первых, ускоряется доступ к системным структурам данных, во-вторых, повышается устойчивость к сбоям диска. При повреждении одного участка поверхности диска теряется только небольшая часть служебной информации о файлах и диске (такая информация в документации часто называется метаданными - metadata).
Если метаданные расположены рядом с пользовательскими данными, уменьшается расстояние, на которое перемещаются головки жесткого диска при переходе от служебной информации к запрошенным данным. К тому же при переходе от одного цилиндра к другому времени уходит значительно больше, чем при считывании данных в пределах одного цилиндра.
Каждому файлу соответствует индексный дескриптор. Он хранит информацию о различных атрибутах файла и его размещении на диске. В индексном дескрипторе записаны:
тип файла;права доступа к файлу;идентификатор владельца файла;идентификатор группы файла;время последней модификации файла;время последнего доступа к файлу;время последней модификации самого индексного дескриптора;число повторных использований индексного дескриптора (т.е. случаев, когда файл был стерт и его индексный дескриптор был использован для хранения данных о другом файле);длину файла в байтах (для файлов устройств это поле имеет смысл сочетания major- и minor-номера устройства, см. раздел "Файлы устройств Solaris");идентификатор файловой системы, в которой расположен файл;количество ссылок на файл;число блоков файла (требуется для поддержки работы с файлами, содержащими большие области, заполненные символами с кодом "ноль", т.е. пустое пространство; такие файлы называются holey files - файлы с пустотами);номер теневого индексного дескриптора (если требуется);структура из 15 номеров блоков, описывающая размещение файла на диске; каждый номер блока занимает 4 байта.
Структура, описывающая физическое размещение файла на диске, в UFS представляет собой последовательность из номеров блоков.
Если файл занимает более двенадцати блоков (т.е. его длина больше 12*8192 =98304 байт), то предпоследние три номера обозначают не номера блоков данных, а номера косвенных блоков (indirect blocks), в которых хранятся указатели на следующие блоки данных и, возможно, на следующие косвенные блоки.
Первые двенадцать номеров блоков содержат просто номера блоков данных. Тринадцатый номер - это номер косвенного блока первого уровня. В блоке первого уровня содержится до 2048 адресов блоков данных (речь идет о 8192-байтных блоках).
Четырнадцатый номер блока содержит номер косвенного блока второго уровня. Косвенный блок второго уровня содержит 2048 номеров косвенных блоков первого уровня, таким образом, через косвенный блок второго уровня адресуется до 20482 блоков данных.
В пятнадцатый номер блока записан номер косвенного блока третьего уровня. Косвенный блок третьего уровня содержит 2048 номеров косвенных блоков второго уровня, так что через косвенный блок третьего уровня адресуется до 20483 блоков данных.
Файл не может располагаться на разных разделах UNIX. Файл может быть фрагментирован, хотя файловая система построена так, чтобы свести фрагментацию к минимуму. Теоретически рекомендуется не заполнять файловую систему более, чем на 70%, чтобы не увеличивать фрагментацию при работе.
Максимальный размер файла может быть легко посчитан, так как мы знаем правила адресации блоков данных. Если размер блока равен 512 байт, то напрямую адресуемые из индексного дескриптора блоки в сумме дают размер 12 ? 8192 байта = 98304 байта.
Адресуемые через номер косвенного блока первого уровня - 2048 ? 8192 байта = 16777216 байт.
Адресуемые через номер косвенного блока второго уровня - 20482 ? 8192 байта = 34359738368 байт.
Адресуемые через номер косвенного блока третьего уровня - 20483 ? 8192 байта = 70368744177664 байта.
Вместе получается примерно 64 Тбайт. Однако Solaris 9, насколько об этом можно судить по доступным фактам, не поддерживает файлы размером более 1 Тбайт на данный момент.
Все современные системы UNIX используют 128-байтный индексный дескриптор, который вмещает больше информации и номер блока в нем занимает не 3 байта (как в прошлом), а 4. Поэтому адресовать можно весьма большие разделы.
28 байт в таком дескрипторе отводится под разные расширения, включая место для 32-разрядных идентификаторов владельца и группы файла, а также под 64-разрядные поля времен модификации. Введение 64-разрядных полей времени в UNIX вместо прежних 32-разрядных нужно для того, чтобы избежать "проблемы 2031 года", т.к. именно в этом году перестанет хватать 32 байт для представления времени в системах UNIX. Разработчики обоснованно полагают, что до тех пор все существующие системы UNIX будут заблаговременно переведены на 64-разрядную архитектуру.
Теневые индексные дескрипторы
Теневые индексные дескрипторы (shadow i-nodes) содержат информацию, позволяющую получать доступ к расширенным правам доступа (ACL) файла или каталога. Этот тип файловых дескрипторов существует в реализации файловой системы UFS в Solaris, начиная с версии 2.5.1. Solaris 9 поддерживает теневые индексные дескрипторы для файловых систем UFS (Unix File System), NFS (Network File System версий 2 и 3), CacheFS (Cache File System). Расширенные права доступа могут быть назначены в отношении каталогов, обычных файлов, символических ссылок и именованных каналов (FIFO).
Если файлу назначены расширенные права доступа (например, с помощью команды setfacl), то будет создан теневой индексный дескриптор для этого файла и в обычный индексный дескриптор этого файла будет записана ссылка на теневой индексный дескриптор. Теневой индексный дескриптор не имеет специального формата, он представляет собой точно такой же индексный дескриптор, как и обычный, но с указанием в поле типа дескриптора на то, что он - теневой.
Расширенные права доступа хранятся в специальном файле, который создается в момент назначения таких прав. Теневой дескриптор указывает на этот специальный файл. В Solaris разрешено создавать не более 1024 записей в таком файле - следовательно, расширенные права доступа могут содержать не более 1024 специфических определений прав. Этого с избытком хватает для установки каких угодно специфических прав доступа. Каждая запись ACL занимает 12 байт, поэтому обычно эти записи не требуют много места на диске. Однако при назначении специфических прав доступа большому числу объектов в файловой системе следует помнить о том, что для этого требуется дополнительный объем дисковой памяти.
Для назначения и просмотра расширенных прав доступа используются команды setfacl и getfacl, о которых более подробно рассказывается в лекции 6.
дайте команду format. Виден ли
Подключите новый IDE-диск, дайте команду format. Виден ли диск системе?Выполните программу devfsadm, снова запустите format. Стал ли виден новый диск? Почему?
Действия с файлами и каталогами
Обычный (regular) файл может содержать текст или двоичные данные.
Создать текстовый файл можно в любом текстовом редакторе или перенаправив вывод какой-либо программы в файл. Часто для создания какого-нибудь тестового короткого файла так и делают. Например, после установки web-сервера можно проверить, корректно ли он откликается на внешний запрос, только если у нас уже есть файл index.html, который он должен выдать в ответ на запрос. Быстрее всего создать этот файл так:
#cat > index.html <HTML> <BODY> Hello everybody! </BODY> </HTML> ^D #
Пустой файл можно создать командой touch, которая изначально была придумана для изменения времени модификации файла на текущее системное время:
touch filename
Эта операция бывает нужна при сборке программы из нескольких файлов, если мы хотим, чтобы были перекомпилированы все исходные тексты (по умолчанию компилируются только свежие).
Файлы копируют командой cp:
cp file1 file2
Переименование файла выполняет команда mv:
mv file1 file2
Командой mv файл можно переместить в другой каталог:
mv file /usr/progs/useless/
Если вы переносите или копируете файл или несколько файлов в каталог, то имя каталога правильнее указывать с завершающим слэшем в конце имени (например, /usr/progs/useless/). Это явным образом указывает на то, что имеется в виду именно каталог.
Если произошла ошибка и последний аргумент команды оказался не каталогом, а файлом, программа сообщит об этом. Если слэш не указать, то в случае ошибки старое содержимое файла, в который копируется новая информация, будет безвозвратно утеряно.
Файлы удаляют с помощью команды rm. В системах UNIX не предусмотрена возможность восстановления удаленных файлов (unerase), поэтому все, что стерто, пропадает навсегда. Системы UNIX в структуре файловой системы не имеют "мусорной корзины" (trash), в которую файлы попадают перед окончательным удалением. Правда, большинство графических сред обеспечивают такую "корзину", но только для тех файлов, которые были удалены программами, специально написанными с учетом этой возможности среды. Так, в Solaris в CDE есть своя корзина. В нее попадают те файлы и каталоги, которые были удалены программами, знающими об этой корзине. Как правило, о ее существовании подозревает только File Manager CDE. Возможность восстановления стертых файлов предоставляется не операционной системой, а графической оболочкой CDE, поэтому не стоит рассчитывать, что любой файл можно восстановить из корзины CDE. Например, если файл был удален командой rm из командной строки xterm (эмулятор тер минала для графической среды), то его уже не восстановить. Команда rm не знает о существовании корзины в CDE, даже если запускается в окне терминала в графическом режиме.
Вывести файл на экран можно командами cat, more, less, pg, page.
Программы cat и more есть в любой системе UNIX, другие перечисленные выше команды - это варианты команды more и присутствуют не всегда. Назначение more и ее "коллег" - поэкранный вывод длинных файлов. При выводе информации программа more останавливается, заполнив экран содержимым очередной страницы файла, и ждет команды. При нажатии "Enter" выводится следующая строка, при нажатии "пробела" - следующая страница. Можно искать подстроку в тексте, по команде
/подстрока
Клавишами <Ctrl-B>, <Ctrl-F> можно перемещаться назад и вперед на одну страницу, клавиша q служит для выхода из программы во время просмотра текста.
Дерево каталогов
Все файлы в UNIX организованы древовидно: всегда существует корневой каталог, который обозначается "/". В нем есть подкаталоги. Обычно используются подкаталоги, перечисленные в табл. 6.1.
Каталог /bin в Solaris является символической ссылкой на каталог /usr/bin.
Характерным свойством Solaris является выделение отдельного каталога /exports, в котором сосредотачиваются разделяемые по сети подкаталоги, доступные для пользователей других компьютеров. Каталог /opt, куда устанавливается некоторое дополнительное программное обеспечение (от optional, необязательное) тоже есть в системах Solaris, но отсутствует во многих других системах UNIX.
lrwxrwxrwx | 1 root | root | 9 | Янв 22 14:54 | bin -> ./usr/bin |
drwxr-xr-x | 1 root | root | 16384 | Янв 1 1970 | boot |
drwxr-xr-x | 2 root | root | 512 | Янв 29 14:42 | cdrom |
drwxr-xr-x | 14 root | sys | 3584 | Мар 16 15:49 | dev |
drwxr-xr-x | 5 root | sys | 512 | Янв 22 15:03 | devices |
drwxr-xr-x | 51 root | sys | 3584 | Мар 16 15:49 | etc |
drwxr-xr-x | 3 root | other | 512 | Янв 28 17:38 | exports |
drwxr-xr-x | 3 root | nobody | 512 | Янв 28 16:57 | floppy |
dr-xr-xr-x | 1 root | root | 1 | Мар 16 15:49 | home |
drwxr-xr-x | 12 root | sys | 512 | Янв 22 14:56 | kernel |
drwx------ | 2 root | root | 8192 | Янв 22 14:53 | lost+found |
drwxr-xr-x | 2 root | sys | 512 | Янв 22 14:54 | mnt |
drwxr-xr-x | 3 root | sys | 512 | Янв 22 15:48 | opt |
dr-xr-xr-x | 63 root | root | 30912 | Мар 16 15:52 | proc |
drwxr-xr-x | 2 root | sys | 1024 | Янв 22 15:51 | sbin |
drwxrwxrwt | 6 root | sys | 368 | Мар 16 15:50 | tmp |
drwxr-xr-x | 34 root | sys | 1024 | Янв 28 19:16 | usr |
drwxr-xr-x | 32 root | sys | 512 | Янв 22 15:57 | var |
Каталог для временных файлов /tmp монтируется в Solaris на отдельную виртуальную файловую систему типа tmpfs. Это особый тип файловой системы. Если в системе есть свободная оперативная память, то драйвер tmpfs хранит данные, записанные на файловую систему этого типа, в оперативной памяти, а не диске. Если объем свободной памяти сокращается и она начинает требоваться другим программам, файлы из tmpfs записываются на раздел свопинга. Получается, что файлы, размещенные в файловой системе типа tmpfs, всегда занимают остаток оперативной памяти системы, для того чтобы она использовалась эффективно. Если свободной памяти нет, tmpfs размещается в пространстве свопинга.
Это автоматически приводит к тому, что записанные в файловую систему tmpfs файлы теряются после перезагрузки. Поэтому не следует хранить в /tmp какие-либо полезные файлы.
Скорость работы файловой системы tmpfs высока, т.к. часто все ее файлы физически расположены в оперативной памяти. Вследствие этого кэширование файлов на tmpfs не производится: они и так хранятся не на диске.
Казалось бы, использование tmpfs таит в себе резерв увеличения производительности любого приложения, поскольку достаточно записать данные в каталог /tmp и работать с ними там, чтобы скорость доступа к данным возросла многократно. На самом деле это не так, потому что чтение и запись любых дисков кэшируется, и лишь для некоторых приложений использование tmpfs оправдано. Несомненно увеличивается быстродействие компиляторов и других программ с большими объемами промежуточных файлов - но они и так используют /tmp для хранения временной информации в процессе работы.
По умолчанию Solaris применяет tmpfs только для /tmp. При этом система избегает существенного объема дискового ввода-вывода, так как /tmp используется для временных файлов различных программ.
Внимание: создание отдельного раздела /tmp на диске приведет к тому, что /tmp не будет создан системой автоматически с типом файловой системы tmpfs и производительность системы может уменьшиться!
Фрагментация
Любая файловая система так или иначе ищет компромисс между бесконтрольной фрагментацией, как в системе FAT, и полным запретом на фрагментацию, как в файловой системе ОС RT-11. Одной из проблем FAT является необходимость регулярно дефрагментировать раздел, а в файловой системе RT-11 приходилось регулярно выполнять программу squeese, которая записывала друг за другом, последовательно, все файлы, разбросанные по диску. Фрагментация FAT приводила к снижению производительности ввода-вывода, а запрет на фрагментацию в RT-11 делал невозможным запись на диск большого файла, даже если на диске имелось полно участков, размер которых был лишь немногим меньше его длины, так как файл должен был быть записан только в последовательно расположенные блоки.
В файловой системе проблема фрагментации решается очень изящно. Фактически, фрагментация диска редко превышает 1-2% от его объема, что в мире Windows считается превосходным показателем.
Как удается достичь такого? Нужно ли что-то делать системному администратору, чтобы фрагментация не мешала производительности в UNIX?
Надо отметить, что термин "фрагментация" в UNIX означает явление, совсем не похожее на фрагментацию в FAT. В UFS, если на диск записывается файл размером меньше блока, ему выделяется фрагмент блока, но фактически "резервируется" целый блок, и файл, таким образом, имеет резерв для расширения до размера блока. Файлы размером больше блока записываются в свободные (по-возможности, последовательные) блоки файловой системы. Однако размер файла не всегда кратен длине блока, поэтому последний из блоков, в которые записан файл, будет, скорее всего, заполнен не до конца. В этот блок в UFS можно записать фрагмент другого файла. В этом смысле "фрагментом" файла в UFS называется часть файла, меньшая по размеру, чем блок. Фрагменты одного файла не могут храниться в разных блоках. Это иллюстрирует рис. 6.1.
Рис. 6.1. Фрагментация в UFS
Индексный дескриптор хранит достаточно информации для того, чтобы идентифицировать не только блок, но и номер фрагмента в блоке, когда речь идет о размещении файла на диске.
Фрагментации в том смысле, в котором она мучает пользователей Windows, в файловой системе UFS не бывает, так как драйвер файловой системы сам заботится о том, чтобы размещать файл по-возможности в пределах одного цилиндра.
Чтобы выяснить, много ли фрагментов (в понимании UFS) на разделе, можно использовать команду fsck -n.
Для уменьшения числа фрагментов (в понимании FAT), т.е. частей файла, записанных на разделе в разных цилиндрах вдали друг от друга, и для записи файла в последовательные блоки следует воспользоваться коммерческими программами дефрагментации (см., например, http://www.eaglesoft.com/products.html - только для платформы SPARC) или выполнить резервное копирование всех файлов раздела и обратное их восстановление посредством программ ufsdump/ufsrestore.
Имена файлов и каталогов
На имена файлов и каталогов распространяются одинаковые ограничения. Так, длина имени файла не должна превышать 255 символов, полное имя файла (т.е. путь от корня файловой системы до файла) не должен быть длиннее 1023 символов.
Имена файлов и каталогов в UNIX состоят из латинских букв верхнего и нижнего регистра, цифр и знаков препинания. Регистр букв имеет значение! Буквы верхнего и нижнего регистра в UNIX считаются разными символами, имена Alliance и alliance - это разные имена, хотя и отличаются всего лишь регистром одной буквы.
Из знаков препинания рекомендуется использовать только точку ".", тире "-" и подчеркивание "_". Использование других знаков (запятых, скобок, звездочки, решетки, вопросительного и восклицательного знаков и других) теоретически возможно, но неудобно. Дело в том, что командные процессоры и стандартные системные функции в UNIX интерпретируют такие знаки специальным образом (а именно, как шаблоны имен файлов или модификаторы команд в командном процессоре). Обращаться к файлу с именем ,/?*&^q-+|! придется тоже специальным образом, а это быстро надоест.
В UNIX не используется понятие "расширение имени файла", так как точка считается равноправным символом в имени. Следовательно, имя several.news.from.New.York смотрится в UNIX не более экзотично, чем index.html. UNIX не делает предположений о содержимом или назначении файла в зависимости от его имени и того, какие символы стоят справа от самой правой точки в имени.
Для того чтобы узнать, что содержится в файле, не открывая его, можно использовать программу file:
file bad.words English text
Программа file использует специальный файл образцов - /etc/magic. Он содержит сведения о том, как должен выглядеть файл, чтобы его можно было отнести к какому-либо известному типу: текст (text), текст программы на языке С (C program), исполняемый код (executable file), данные (data) и т.д.
Имя может быть полным (абсолютным) или относительным. Полное имя файла - это имя с указанием пути к файлу от корневого каталога, например, /usr/local/squid/etc/squid.conf. Полное имя легко идентифицировать: оно всегда начинается с символа "/".
Относительное имя файла может быть очень коротким, например, просто f. Если в имени файла вообще нет знака "/" (слэш), то имя относится к файлу текущего каталога. Если слэш есть (но не в начале имени - например, squid/etc/squid.conf), то все, что находится слева от первого в имени слэша, расценивается как подкаталог текущего каталога.
Полное имя любого файла не должно быть длиннее 1023 символов. Однако, для обращения к файлу, расположенному очень глубоко в структуре каталогов, следует перейти в промежуточный каталог командой cd и оттуда обратиться к файлу по относительному имени. Скажем, вместо
vi /usr/home/ivan/projects/united_states/texas/cowboys/horses/ red/seats/sellers_training
можно обратиться к тому же файлу так:
cd /usr/home/ivan/projects/united_states vi texas/cowboys/horses/red/seats/sellers_training
Кстати, обратите внимание на ввод многострочных команд: при необходимости перехода на другую строку при вводе длинной команды следует использовать символ экранирования (обратный слэш) "\". Следующий за ним символ перевода строки в таком случае будет интерпретирован как пустой символ, а не как символ завершения команды.
Полное имя файла также называют "путем к файлу", "путем файла" или "путевым именем файла".
Символ "~" (тильда) в большинстве командных интерпретаторов обозначает домашний каталог пользователя. Например, команда
cd ~anna/
требует перейти в домашний каталог пользователя anna, а знак "~" без имени пользователя означает домашний каталог текущего пользователя. Впрочем, интерпретатор sh знак ~ так не воспринимает, пользуйтесь bash!
Индексные дескрипторы
Формат таблицы индексных дескрипторов и самих дескрипторов обсуждался в лекции 5. Следует сказать, что непосредственное изменение индексного дескриптора невозможно, так как модификацию дескриптора выполняют различные программы в процессе своей работы. Нет необходимости вмешиваться в содержимое индексного дескриптора напрямую. Для восстановления таблицы индексных дескрипторов после сбоя следует воспользоваться программой fsck.
Изменение размеров раздела
Для изменения размеров раздела UFS можно воспользоваться программой growfs. Если же изменить размер раздела по какой-либо причине не представляется возможным, следует установить новый диск и перенести часть информации на него, возможно, создав соответствующие символические ссылки на переполненном разделе. Подробнее об изменении размеров разделов дисков и повышении их производительности сказано в лекции 7 курса "Администрирование ОС Solaris".
Как узнать, сколько места осталось на диске?
Оценить, как в текущий момент используется диск, поможет программа df:
df / (/dev/dsk/c0d0s0): 1787406 blocks 419477 files /boot (/dev/dsk/c0d0p0:boot): 19452 blocks -1 files /proc (/proc ): 0 blocks 2896 files /etc/mnttab (mnttab ): 0 blocks 0 files /dev/fd (fd ): 0 blocks 0 files /var/run (swap ): 1265832 blocks 30240 files /tmp (swap ): 1265832 blocks 30240 files /export/home (/dev/dsk/c0d0s7 ): 7647080 blocks 481212 files
Чтобы получить более удобную картину, в которой размер занятых блоков приводится в килобайтах, следует дать команду df -k:
df -k Filesystem kbytes used avail capacity Mounted on /dev/dsk/c0d0s0 1857844 964142 837967 54% / /dev/dsk/c0d0p0:boot 11234 1508 9726 14% /boot /proc 0 0 0 0% /proc Mnttab 0 0 0 0% /etc/mnttab Fd 0 0 0 0% /dev/fd Swap 632924 20 632904 1% /var/run Swap 633208 304 632904 1% /tmp /dev/dsk/c0d0s7 3823549 9 3785305 1% /export/home
Команда
df -o i
сообщит о количестве свободных и занятых индексных дескрипторов на разделе. Обратите внимание на то, что в других вариантах UNIX это делается с помощью команды
df -i
Для оценки размеров подкаталогов любого каталога используйте du. Например, для определения того, сколько места на дисках занимают подкаталоги корневого каталога, дайте команду du -s /*:
du -s /* 2 /bin 3011 /boot 87255 /cdrom 1424 /core 3068 /dev 76 /devices 6262 /etc 26 /export 6 /floppy 4 /format.log 1 /home 20702 /kernel 2 /lib 16 /lost+found 2 /Mail 2 /mnt 1 /net 2 /nsmail 14 /opt 3822 /platform 730131 /proc 50 /qq 2 /qqqq 34154 /sbin 640 /tmp 46 /TT_DB 1811752 /usr 46138 /var 0 /vol 19 /xfn
В этой команде ключ -s указывает, что следует выдать суммарные значения по всем подкаталогам, а аргумент /* требует, чтобы была посчитана статистика по всем подкаталогам и файлам корневого каталога. Без указания ключа -s программа du сообщит о том, сколько места занимает каждый из "листьев" дерева каталогов, т.е. выдаст длинный и подробный список всех подкаталогов вообще, включая подкаталоги подкаталогов подкаталогов...
Каталоги
Слово "каталог" употребляется наряду со словом "директория" (directory). В терминологии большинства Windows-систем то же самое обозначает слово "папка" (folder). Среди системных администраторов UNIX принято употреблять термин "каталог".
Каталог представляет собой файл особого типа, который содержит таблицу из двух столбцов: в первом значится имя файла, во втором - номер индексного дескриптора, который описывает файл. В одном каталоге не может быть файлов или подкаталогов с одинаковыми именами.
Каталог может содержать и файлы, и подкаталоги. Пустой каталог создается командой mkdir. Удалить пустой каталог можно командой rmdir, непустой каталог удаляется командой
rm -rf каталог
Например, по команде
rm -rf /usr/local/squid/
будут удалены каталог /usr/local/squid, а также все файлы в нем и все его подкаталоги.
Перенести или переименовать каталог можно командой mv, для копирования каталогов вместе с подкаталогами используется команда cp -Rp.
Список файлов и подкаталогов в каталоге выдает команда ls. Если запустить ls без параметров, она выдаст только список имен фaйлов. Эта команда имеет множество ключей, из которых наиболее полезны перечисленные в табл. 6.2.
l (long) | вывести полную информацию о файле |
a (all) | вывести все файлы, в том числе те, чьи имена начинаются с точки |
i (i-nodes) | вывести номера индексных дескрипторов |
t (time) | отсортировать файлы по времени последней модификации |
При создании каждого каталога в нем всегда появляются две записи - "." (точка) и ".." (две точки). "Точка" ссылается на сам текущий каталог, а "две точки" - на родительский каталог. В корневом каталоге обе эти записи указывают на корневой каталог.
По умолчанию программа ls выводит информацию обо всех файлах, за исключением тех, чьи имена начинаются с символа "." (точка). При указании ключа -a эти файлы тоже включаются в общий список.
Файлам, которые содержат важную конфигурационную или служебную информацию, традиционно дают имена, начинающиеся с символа "точка". Таковы, например, файлы .profile, .xsession, .bashrc, .history и другие.
Перейти из одного каталога в другой можно по команде
cd каталог
Команда cd без аргументов вызывает переход в домашний каталог текущего пользователя и эквивалентна cd ~.
Вывод на экран полного имени текущего каталога выполняется командой pwd.
Минимальное свободное пространство
При создании файловой системы часть раздела диска резервируется на всякий случай. Эта доля задается параметром minfree (параметр free при запуске программы mkfs) и по умолчанию составляет 10% общего объема файловой системы. Ко "всяким случаям" относят переполнение диска, т.е. превышение выделенного лимита пространства размещенными на разделе файлами, необходимость срочно найти свободный дисковый блок, когда диск почти заполнен, и тому подобное. В современных системах, когда файловые системы размером в сотни гигабайт - явление обычное, 10% свободного объема составляет значительный объем дискового пространства.
Чтобы уменьшить такие колоссальные издержки, значение minfree достаточно установить равным 1%. Кстати, при установке Solaris 9 на мой ноутбук ThinkPad 390X с диском размером 4 Гбайт, по умолчанию файловая система была создана именно с таким minfree. Несмотря на это, документация на mkfs_ufs утверждала, что 10% является значением по умолчанию. При создании файловой системы минимальное свободное пространство можно задать так:
mkfs_ufs -o free=1
или так:
newfs -m 1
Изменить параметры файловой системы UNIX можно с помощью программы tunefs.
После того как на диске осталось свободного пространства менее, чем указано в minfree, запись на диск сможет выполнить только root.
Оптимизация размеров разделов
Вопрос об оптимизации дисковой подсистемы обычно встает как неизбежный результат отсутствия детального планирования системы в целом. Поэтому первым правилом, которое следует соблюдать системному администратору, желающему видеть свою систему быстрой и надежной, будет "планируй все заранее".
Когда требуется установить новый сервер Solaris, стоит подумать, чем этот сервер будет занят. В современном мире задачи компьютеров меняются быстрее, чем оборудование. Если пять лет назад почтовый сервер, обслуживающий сто пользователей, мог работать на медленном компьютере с диском 1 Гбайт, то нынче с почтой связано намного больше задач, чем просто прием, передача и хранение. Современный почтовый сервер для тех же ста пользователей принимает почту, проверяет ее на вирусы, блокирует спам, возможно, выполняет контекстный анализ письма для фильтрации спама и только после этого сохраняет его на диске. Объемы передаваемой почты тоже существенно возросли. Письма часто отправляются в формате HTML, а многие адресаты вкладывают в письма не только текстовые документы, но и фотографии, музыкальные файлы и видеоклипы. Поэтому, планируя свой новый почтовый сервер с запасом, вы не ошибетесь. Сейчас средний пользователь хранит в своем почтовом ящике несколько сотен мегабайт информации, следует ожидать, что в ближайшее время придется оценивать возможную нагрузку на файловую систему почтового сервера исходя из 5-10 Гбайт на каждого пользователя. Это не относится к серверам, которые только передают почту, но не хранят почтовые ящики пользователей.
Для передачи и приема нескольких писем в секунду придется установить новый компьютер с процессором Pentium IV, если на сервере будет запущена программа контекстного анализа писем для фильтрации спама (например, spamasassin). Объем памяти, естественно, тоже должен быть достаточным для одновременного запуска десятков копий программы sendmail или ее аналога.
Из этого видно, что характер работы сервера надо планировать еще до начала его установки. Во время установки следует задать верные размеры файловых систем. Это избавит вас от необходимости модифицировать их размеры в дальнейшем.
В Solaris размер корневой файловой системы / вполне может быть менее 3 Гбайт. Даже с учетом возможного обновления системы этого достаточно. Но файловая система /usr, куда будут устанавливаться все новые пакеты, должна быть спланирована с запасом. Если работа сервера будет связана с большой дисковой нагрузкой (кэширование http-запросов, хранение файлов или почты), то для этих специфических целей (например, кэш http-запросов) можно выделить отдельный раздел и назначить ему такой размер, который соответствует вашим потребностям.
Надо будет учесть такие факторы, как возможный рост потребностей, требуемая производительность (для подсистем SCSI лучше установить шесть дисков по 9 Гбайт, чем один размером 54 Гбайт, - так будет быстрее) и не забыть учесть "запас", который создает система на каждом разделе1).
Права доступа
Давно известно, что в Москве раньше были две угнетаемые нации: "погазоны" и "улюки". Их никто никогда не видел, но всем было их очень жалко. Куда ни пойдешь, везде пестрели надписи: "Погазонам не ходить", "Машины улюков не ставить".
В каждой многопользовательской системе полагается развешивать такие таблички по каталогам, чтобы доступ к информации имели только те, кому он разрешен.
Система безопасности UNIX основана на правах доступа к объектам файловой системы - файлам и каталогам. У каждого каталога или файла есть один владелец и один групповой владелец. Группового владельца файла мы будем для краткости называть группой файла.
Словосочетание "группа файла" не означает, что файлы объединены в какие-то группы. Группа файла - это группа пользователей, которой даны некие специальные права на доступ к этому файлу.
Дав команду ls -l в любом каталоге, мы увидим нечто вроде
-rw-r--r-- 1 root root 433 Feb 2 10:30 acd.c
Первый столбец - это тип файла (первый символ) и права доступа (остальные девять символов). Затем указаны число жестких ссылок на файл, владелец и группа файла, размер файла в байтах, дата последней модификации в формате "Месяц Число Год Время" и имя файла. Год часто не указывается для тех файлов, которые были модифицированы в течение последних 12 месяцев.
Права доступа делятся на три части: права, данные, соответственно, владельцу файла, группе файла и всем остальным (обозначаются термином other или world). Таким образом, девять бит слова прав доступа делятся на три части по три бита:
rwx | rw- | r--| u g o
Часть, обозначенная буквой u (user), определяет права доступа владельца файла, буквой g - права доступа группы файла, буквой o - права всех остальных. Существуют права трех типов: на чтение (r, read), запись (w, write) и запуск на выполнение (x, execute). Пользователю, который хочет обратиться к файлу, даются права доступа либо владельца, либо группы файла, либо "всех остальных". Права доступа проверяются так (см. рис. 6.2, на примере слова прав доступа rwxrw-r--):
Рис. 6.2. Алгоритм получения доступа к файлу
Когда процесс, работающий от имени пользователя, пытается получить доступ к файлу, система выясняет, является ли он владельцем файла. Если является, то он получает права доступа, определенные для владельца файла. Если он - не владелец, но входит в группу, которая является группой файла, то он получает права доступа, определенные для группы файла. Если он не относится ни к одной из этих двух категорий, он получает права, определенные для всех остальных. Права разных категорий пользователей не складываются: если доступ к файлу хочет получить его владелец, и он входит в группу файла, но права группы более широкие, чем права владельца (например, слово прав доступа r-xrwxr--), то он все равно получит права владельца (в последнем примере - r-x). Для большинства файлов и каталогов права их владельца обычно шире, чем у группы.
Слово прав доступа представляет собой последовательность из двенадцати бит. Для назначения прав доступа обычно используются только обсужденные выше младшие девять бит, поэтому права доступа часто записываются в виде трех десятичных чисел, показывающих права владельца, группы и всех остальных соответственно. Установленный в единицу бит говорит о наличии соответствующего права:
мнемоническое обозначение слова прав доступа: rwxrw-r--двоичное представление слова прав доступа: 111 110 100десятичное представление слова прав доступа: 7 6 4
В документации часто встречается требование при установке какой-либо программы установить для некоего каталога права доступа 755. Имеются в виду права rwxr-xr-x, что соответствует полному доступу владельцу и доступу на чтение и запуск группе и всем остальным.
Право запуска в отношении каталога определяется как право поиска в каталоге, что на практике означает право на чтение индексных дескрипторов файлов и подкаталогов этого каталога. Действительно, возможность узнать, какие именно файлы есть в каталоге, определяется правом на чтение каталога. А вот более подробная информация о файлах (кто их хозяин, где лежат и т.п.) доступна только тем, кто имеет право на поиск в каталоге. Наличие или отсутствие права поиска в каталоге не влияет на права пользователя root: ему разрешен поиск в любом каталоге.
Старшие три бита слова прав доступа относятся к запуску файла, поэтому детально они рассмотрены в лекции 7. Вот как выглядит слово прав доступа:
su sg t r w x r w x r w x
Старшие три бита - это бит установки владельца при запуске файла (suid), бит установки группы (sgid) при запуске файла и бит запрета выгрузки файла на диск при выполнении (t).
Для каталога биты suid и sgid имеют другое значение. По умолчанию при создании файла он наследует владельца и группу от процесса, который его создал. Аналогичное правило распространяется и на каталоги. Однако если в правах доступа к каталогу установлен бит suid, то созданный в нем файл или подкаталог будет принадлежать не владельцу по умолчанию, а владельцу каталога с битом suid. Это правило не работает для систем Solaris, хотя справедливо для некоторых других систем UNIX.
В Solaris это правило распространяется только на группу файла, но не на владельца. То есть владельцем нового файла будет владелец создавшего его процесса, независимо от наличия бита suid у каталога, где создан файл. Но если каталог имеет установленный бит sgid, то группой нового файла станет группа процесса-создателя.
Бит запрета выгрузки файла на диск при выполнении (sticky bit) в старых версиях UNIX использовался для указания того, что при выполнении программы, записанной в этом файле, ее страницы запрещено выгружать на диск. В настоящее время sticky bit используется для каталогов, с тем, чтобы указать особые условия удаления файлов из каталога. Если sticky bit установлен для каталога, то все пользователи, кроме root, могут удалять из каталога только те файлы, которые им принадлежат, независимо от прав доступа к каталогу. В разных системах UNIX он может интерпретироваться по-разному, поэтому смотрите для уточнений man sticky и man chmod.
Расширенные права доступа (ACL) к файлам
Расширенные права доступа к файлу могут быть такими, как показано в таблице 6.3.
u[ser]::perms | права доступа хозяина файла |
g[roup]::perms | права доступа группы файла |
o[ther]:perms | права всех остальных |
m[ask]:perms | маска ACL |
u[ser]:uid:perms | права доступа указанного пользователя; в качестве uid можно указать и UID, и имя пользователя |
g[roup]:gid:perms | права доступа указанной группы; в качестве gid можно указать и GID, и имя группы |
Маска задает максимальные права доступа для всех пользователей, за исключением хозяина и групп. Установка маски представляет собой самый быстрый путь изменить фактические (эффективные) права доступа всех пользователей и групп. Например, маска r-- показывает, что пользователи и группы не могут иметь больших прав, чем просто чтение, даже если им назначены права доступа на чтение и запись.
Расширенные права доступа (ACL) к каталогам
Кроме расширенных прав доступа к файлу, которые могут быть назначены и каталогу, существуют специфические права доступа к каталогу, а именно права доступа по умолчанию. Файлы и подкаталоги, которые будут создаваться в этом каталоге, будут получать такие же расширенные права доступа по умолчанию, которые заданы в расширенных правах доступа к этому каталогу.
d[efault]:u[ser]::perms | права хозяина файла по умолчанию |
d[efault]:g[roup]::perms | права группы файла по умолчанию |
d[efault]:o[ther]:perms | права остальных пользователей по умолчанию |
d[efault]:m[ask]:perms | маска ACL по умолчанию |
d[efault]:u[ser]:uid:perms | права доступа по умолчанию для указанного пользователя; в качестве uid можно указать и UID, и имя пользователя |
d[efault]:g[roup]:gid:perms | права доступа по умолчанию для указанной группы; в качестве gid можно указать и GID, и имя группы |
Устанавливая права доступа по умолчанию для конкретных пользователей и групп, необходимо также установить права доступа по умолчанию для хозяина и группы файла, а также всех остальных, а также маску ACL (эти четыре обязательных записи указаны выше по тексту - первыми в таблице расширенных прав доступа к файлу).
Присвоение расширенных прав доступа осуществляется программой setfacl с ключом -s (set). Без этого ключа расширенные права доступа модифицируются, с ним - устанавливаются в точности такими, как указано в данной команде setfacl.
Например, чтобы установить права на чтение и запись файла project07 для пользователей lena и petr, надлежит выполнить команду
setfacl -m user:lena:rw-,user:petr:rw- project07
Ключ -m служит для добавления прав доступа, а не для их замены. Эффективные (т.е. те, которые в самом деле будут иметь место) права доступа пользователей lena и petr определяются не только их персональными правами доступа к этому файлу, но и маской, которая показывает права доступа по умолчанию. Из персональных прав и маски выбираются наиболее строгие ограничения, поэтому, если в персональных правах доступа или в маске для файла project07 отсутствует право на запись, то ни lena, ни petr не получат реальной возможности изменить файл project07.
Расширенные права доступа не показываются в выводе программы ls, но команда ls -l позволяет установить наличие расширенных прав доступа к файлу или каталогу. Если они назначены, то в первой колонке после стандартных прав доступа владельца, группы файла и остальных будет стоять знак "+" ("плюс"). Узнать, какие именно расширенные права доступа назначены, можно с помощью команды
getfacl имя_файла
Более подробную информацию о ключах setfacl и getfacl следует получить из man.
Помните, что назначение прав доступа с помощью chmod может привести к изменению записей ACL, а изменение маски ACL может повлиять на фактические права доступа к объекту для его владельца, группы и всех остальных пользователей.
Списки ACL
Стандартные права доступа в UNIX не всегда идеальным образом подходят для решения задач администрирования системы. Например, что сделает администратор, если доступ к файлу на чтение и запись надо дать одной группе пользователей? Конечно, сделает эту группу владелицей файла, а затем делегирует право чтения и записи файла этой группе, вот так:
chgrp нужная_группа файл chmod g=rw файл
А если надо дать право доступа только одному из членов этой группы? Тогда можно создать новую группу специально для этой цели, сделать ее членом только одного пользователя, и затем указать, что эта новая группа будет владеть файлом:
addgroup новая_группа chgrp новая_группа файл chmod g=rw файл #редактируем /etc/group и добавляем в новую группу существующего пользователя vi /etc/group
Такое ухищрение нам помогло, но что делать, если надо дать право чтения, записи и запуска двум разным пользователям, а еще двум - право чтения и записи, а еще одному - только чтения? А всем остальным - вообще не дать доступ к этому файлу? На такой вопрос нет ответа, если вы работаете в "классической" версии UNIX. Однако некоторые современные системы UNIX (например, Solaris Linux и FreeBSD) обладают требуемым механизмом. Это - списки управления доступом к файловой системе, access control lists (ACLs).
Списки управления доступом дают более гибкие возможности назначения прав доступа, чем традиционные права доступа UNIX. С помощью ACL можно назначить как права доступа хозяина файла, группы файла и всех остальных, так и отдельные права для указанных пользователей и групп, а также максимальные права доступа по умолчанию, которые разрешено иметь любому пользователю.
Здесь и далее мы будем называть ACL для файлов и каталогов "расширенными правами доступа". Расширенные права доступа к файлам и каталогам устанавливаются командой setfacl.
Они представляют собой ряд полей, разделенных двоеточиями:
entry_type:[uid|gid]:perms
Здесь entry_type - тип расширенного права доступа, uid и gid - идентификаторы пользователя и группы, соответственно, а perms - собственно назначаемые права доступа.
Ссылки
В любой системе UNIX используются жесткие и символические ссылки.
Жесткая ссылка - это ссылка на индексный дескриптор файла. В этом смысле имя файла и есть жесткая ссылка, причем у одного файла может быть несколько разных имен в разных каталогах. Это значит, что в разных каталогах могут быть записи, ссылающиеся на один и тот же файл и, следовательно, один и тот же индексный дескриптор. Этот файл будет доступен под всеми этими именами. Число жестких ссылок на файл хранится в его индексном дескрипторе:
# ls -li file* 16852 -rw-r--r-- 2 root root 0 Mar 20 16:11 file 16852 -rw-r--r-- 2 root root 0 Mar 20 16:11 file1
В этом примере видно, что в каталоге есть два файла с разными именами, но все остальные свойства у них одинаковы. Это обусловлено тем, что файлы имеют один и тот же индексный дескриптор (его номер выводится в первом столбце).
Число в третьем столбце показывает, сколько в файловой системе есть жестких ссылок на этот файл. Физически файл один, так как местоположение содержимого файла на диске определяется индексным дескриптором. При этом можно обратиться к этому файлу, называя его разными именами. Фактически, после создания жесткой ссылки на файл определить, какое из имен было придумано раньше, невозможно. Права доступа ко всем жестким ссылкам на файл одинаковы, так как определяются одним и тем же индексным дескриптором.
Смысл жесткой ссылки состоит в возможности поместить в разные каталоги записи об одном и том же файле, без многократного копирования этого файла во все каталоги, где нужна запись о нем. При модификации файла, независимо от того, через какую именно жесткую ссылку к нему обратились, изменяется информация в самом файле. Если модифицировать файл, обратившись к нему по одному имени (через одну жесткую ссылку), и записать сделанные изменения, то при последующем обращении к нему через другую жесткую ссылку вы увидите уже новую, модифицированную информацию.
Жесткие ссылки создает команда ln:
ln старое_имя новое_имя
При создании жесткой ссылки сам файл не модифицируется, старое имя никак не изменяется, результат выполнения команды проявляется только в создании еще одного имени этого файла.
Нельзя создать жесткую ссылку на файл, который располагается на другом разделе UNIX. Это связано с тем, что каждый раздел файловой системы имеет свою таблицу индексных дескрипторов, а указать в каталоге индексный дескриптор чужого раздела невозможно. Также нельзя создать жесткую ссылку на любой каталог.
Файл в любой файловой системе UNIX считается удаленным только тогда, когда удалены все жесткие ссылки на него. Удаление жесткой ссылки выполняется командой rm и внешне ничем не отличается от удаления обычного файла.
Найти все жесткие ссылки на файл можно с помощью команды find:
find откуда_искать -inum номер_индексного_дескриптора_файла
Например, find / -inum 16852.
Символическая ссылка - это запись в каталоге, ссылающаяся на файл с определенным именем. Фактически, символическая ссылка - это отдельный файл типа "символическая ссылка", и индексный дескриптор этого файла содержит только путь к файлу или каталогу, на который указывает ссылка:
ls -l lrwxrwxrwx 1 root root :. qq ->/usr/home/qq
Можно создать символическую ссылку на любой каталог, а также на файл, находящийся в другом разделе UNIX. Символическая ссылка является аналогом ярлыка (shortcut) в системах Windows. При удалении символической ссылки с файлом или каталогом, на который она ссылается, ничего не происходит. При удалении файла, на который указывает символическая ссылка, она "повисает в воздухе", ссылаясь на пустоту. В последнем случае при обращении к такой "пустой" ссылке возникнет ошибка file not found, несмотря на то, что сама ссылка будет видна и доступна в списке файлов.
Обычно по команде ls -l выдается не только информация о типе файла 1, если это символическая ссылка, но и указывается, на что она ссылается. Если эта информация не появилась, попробуйте дать команду ls -F. В разных системах UNIX ключи программы ls могут незначительно отличаться.
Типы файлов
Если дать команду ls -l, то тип файла будет указан первым символом первого столбца вывода:
ls -l /etc lrwxrwxrwx 1 root root 14 Янв 22 14:59 aliases -> ./mail/aliases drwxr-xr-x 2 root bin 512 Янв 22 15:53 apache ... -rw-r--r-- 1 root root 12 Янв 23 08:35 defaultrouter -r--r--r-- 1 root root 1825 Янв 22 15:42 device.tab -rw-r--r-- 1 root sys 2467 Янв 22 15:02 devlink.tab drwxr-xr-x 2 root sys 512 Янв 22 14:54 dfs prw------- 1 root root 0 Мар 16 15:50 initpipe -rw-r--r-- 1 root sys 1087 Янв 23 08:33 inittab
Вывод команды ls для каталога /etc в этом примере сильно обрезан, на самом деле там несравнимо больше файлов. Нас интересуют различные типы файлов, которые мы здесь встретим.
В системах UNIX файлы могут быть обычными (этому типу соответствует обозначение -), а также представлять собой каталог (d), файл символьного (c) или блочного (b) устройства, символьную ссылку на другой файл (l), программный канал (p). В Solaris есть еще специальный тип door (дверь), ассоциированный с набором потоков в системе и требуемый для программирования взаимодействия потоков.
Обычный файл может содержать текст или двоичные данные - система не делает никаких предположений о содержимом файла в зависимости от его имени, в отличие от Windows-систем. Возможность запустить файл определяется исключительно правами доступа к файлу. Если вы попытаетесь запустить двоичный файл, система будет искать в нем корректный заголовок исполняемого кода. Если этот файл на самом деле не является программой UNIX, система просто сообщит об ошибке. При попытке выполнить текстовый файл он будет рассматриваться как скрипт командного процессора (если иное не указано в первой строке файла, где можно указать иной интерпретатор). Если файл не является скриптом, командный процессор завалит вас сообщениями об ошибках. Он будет выдавать не меньше одного ругательного сообщения на каждую строку. Не пытайтесь запускать то, что не должно запускаться!
Каталог представляет собой файл специального формата, содержащий имена файлов, которые лежат в этом каталоге, и номера их индексных дескрипторов. Подробнее об индексных дескрипторах рассказано в разделе "Индексные дескрипторы".
Файлы символьных или блочных устройств - это файлы, которые располагаются в каталоге /dev или связанном с ним (см. лекцию 5). Обмен данными с символьным устройством (например, с терминалом) идет посимвольно, с блочным (например, с диском) - поблочно.
О символических1) ссылках будет рассказано ниже в разделе "Ссылки"; это - файлы специального типа, аналог ярлыка в Windows.
Программный канал - это файл, образующийся в некоторых случаях при организации каналов связи между процессами. От администратора обычно не требуется никаких действий в отношении файлов типа p.
В каталоге /etc мы видим обычные файлы, символические ссылки, каталоги и даже один программный канал. Файлы этих типов (за исключением файлов каналов) и составляют большинство в системе.
Таким образом, в Solaris используются следующие типы файлов:
d каталог (directory);
D дверь (door);
l символическая ссылка (symbolic link);
b файл блочного устройства (block);
с файл символического устройства, устройства прямого доступа (character);
p специальный файл программного канала (FIFO, named pipe);
s сокет;
- обычный файл.
и user2 имена реальных пользователей
Создайте файл.
Установите расширенные права доступа к нему командой
setfacl -m user:user1:rw-,user:user2:rw- имя_файла
Используйте вместо user1 и user2 имена реальных пользователей вашей системы, вместо имя_файла - имя любого существующего файла в вашей системе.
Проверьте командой ls -l права доступа к файлу.Проверьте командой getfacl имя_файла права доступа к файлу.Каковы эффективные права доступа к файлу? Измените маску с помощью setfacl или права доступа хозяина, группы или остальных пользователей командой chmod.Оцените, какое действие - установка маски ACL или прав доступа с помощью chmod действительно изменяет эффективные права доступа к файлу для пользователей user1 и user2.Выполните переход в домашний каталог командой cd ~. Выполнилась ли команда? Если нет, то почему? Какой командный интерпретатор вы используете? Попробуйте выполнить то же действие командой cd без параметров.
Аргументы
Каждый процесс при запуске может получить один или несколько аргументов. К аргументам можно обращаться так же, как и к переменным среды окружения, через массив строк:
char *argv[]
Число аргументов обязательно передается в каждый процесс в переменной:
int argc
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
В тех случаях, когда поведение и ключи программ 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).
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, то они потеряются навсегда.
Диспетчер
Когда поток готов к выполнению, он помещается в очередь отправки на выполнение. Каждый процессор (в многопроцессорной системе) имеет отдельный набор очередей отправки. Состояние ожидания в очереди отправки называется состоянием выполнения (RUN). Когда процессор освобождается, диспетчер берет поток с наивысшим приоритетом из очереди отправки этого процессора и помещает его в процессор. Теперь поток в состоянии "внутри процессора" (ONPROC) и может выполнять вычисления.
Поток может лишиться процессорного времени и покинуть процессор по нескольким причинам:
поток занимает процессор, пока не закончится отведенный ему период времени (определяемый приоритетом потока). Такой период называется квантом. Поскольку процессы с большим приоритетом выбираются чаще, то квант обычно обратно пропорционален приоритету (процессы с более высоким приоритетом имеют меньшие кванты). Когда квант исчерпан, потоку присваивается приоритет нового уровня (значение tqexp). Такой уровень почти всегда ниже приоритета потока при старте. Это сделано для обеспечения справедливости при планировании;поток ждет завершения ввода-вывода или разблокировки нужного ему ресурса, тогда он переходит в состояние "сна" (SLEEP). Проснувшимся потокам назначается более высокий приоритет, чем у них был до сна, чтобы они могли "наверстать упущенное";ядро прервало поток; если прерванный поток долго ожидает внимания процессора, то его приоритет повышается до значения lwait. Так потоки компенсируют ожидание в очереди после прерывания.
Доступ процессов к файлам
В ходе работы процессы обращаются к внешним устройствам, файлам и каталогам. При обращении к внешнему устройству права доступа к нему определяются правами доступа к соответствующему файлу устройства. Права доступа к файлу и каталогу определяются одинаково, исходя из фактических прав доступа, определенных в файловой системе, включая расширенные права доступа (ACL).
То, какие права доступа к файлу получит процесс, зависит от эффективных идентификатора владельца (eUID ) и группы (eGID) этого процесса. При обращении процесса к файлу ядро проверяет, кем по отношению к этому файлу является владелец процесса. Если эффективный идентификатор владельца процесса совпадает с идентификатором владельца файла, то процесс получает права доступа к файлу, определенные для владельца файла. Если владелец процесса входит в группу файла, но не является владельцем файла, он получает права, определенные для группы файла. Если не имеет место ни то, ни другое, то процесс получает права доступа к файлу, определенные для "всех остальных".
Новый файл по умолчанию получает идентификаторы владельца и группы по наследству от процесса, который его создал, а права доступа к нему - по умолчанию - исходя из маски прав доступа umask.
Эффективный идентификатор группы процесса не играет роли в вычислении фактических прав доступа к файлу. Он используется исключительно для того, чтобы назначить его (по наследству) новому файлу, который будет создан процессом.
UID PID PPID LWP NLWP
/usr/bin/ps -efcL UID PID PPID LWP NLWP CLS PRI STIME TTY LTIME CMD root 0 0 1 1 SYS 96 00:23:03 ? 0:03 sched root 1 0 1 1 TS 59 00:23:03 ? 0:00 /etc/init - root 2 0 1 1 SYS 98 00:23:03 ? 0:00 pageout root 3 0 1 1 SYS 60 00:23:03 ? 0:00 fsflush root 314 1 1 1 TS 59 00:23:35 ? 0:00 /usr/lib/saf/sac -t 300 root 289 1 1 1 TS 59 00:23:32 ? 0:00 /usr/lib/snmp/snmpdx -y -c /etc/snmp/conf root 182 1 1 3 TS 59 00:23:22 ? 0:00 /usr/lib/autofs /automountd root 182 1 2 3 TS 59 00:23:23 ? 0:00 /usr/lib/autofs /automountd root 182 1 3 3 TS 59 00:25:23 ? 0:00 /usr/lib/autofs /automountd root 207 1 3 18 TS 59 00:23:25 ? 0:00 /usr/sbin/nscd root 207 1 4 18 TS 59 00:23:25 ? 0:00 /usr/sbin/nscd root 207 1 5 18 TS 59 00:23:25 ? 0:00 /usr/sbin/nscd root 207 1 6 18 TS 59 00:23:25 ? 0:00 /usr/sbin/nscd root 207 1 7 18 TS 59 00:23:25 ? 0:00 /usr/sbin/nscd root 207 1 8 18 TS 59 00:23:25 ? 0:00 /usr/sbin/nscd root 207 1 9 18 TS 59 00:23:25 ? 0:00 /usr/sbin/nscd root 193 1 11 13 TS 59 00:23:24 ? 0:00 /usr/sbin/syslogd root 193 1 12 13 TS 59 00:23:24 ? 0:00 /usr/sbin/syslogd root 193 1 13 13 TS 59 00:23:26 ? 0:00 /usr/sbin/syslogd root 439 419 1 1 IA 39 00:24:42 pts/4 0:00 bash |
Пример 7.1. Результат работы команды ps c ключами -L и -c |
Закрыть окно |
dispadmin -c TS -g # Time Sharing Dispatcher Configuration RES=1000 ts_quantum ts_tqexp ts_slpret ts_maxwait ts_lwait PRIORITY LEVEL 200 0 50 0 50 # 0 200 0 50 0 50 # 1 200 0 50 0 50 # 2 200 0 50 0 50 # 3 200 0 50 0 50 # 4 200 0 50 0 50 # 5 200 0 50 0 50 # 6 200 0 50 0 50 # 7 200 0 50 0 50 # 8 200 0 50 0 50 # 9 160 0 51 0 51 # 10 160 1 51 0 51 # 11 160 2 51 0 51 # 12 160 3 51 0 51 # 13 160 4 51 0 51 # 14 160 5 51 0 51 # 15 160 6 51 0 51 # 16 160 7 51 0 51 # 17 160 8 51 0 51 # 18 160 9 51 0 51 # 19 120 10 52 0 52 # 20 120 11 52 0 52 # 21 120 12 52 0 52 # 22 120 13 52 0 52 # 23 120 14 52 0 52 # 24 120 15 52 0 52 # 25 120 16 52 0 52 # 26 120 17 52 0 52 # 27 120 18 52 0 52 # 28 120 19 52 0 52 # 29 80 20 53 0 53 # 30 80 21 53 0 53 # 31 80 22 53 0 53 # 32 80 23 53 0 53 # 33 80 24 53 0 53 # 34 80 25 54 0 54 # 35 80 26 54 0 54 # 36 80 27 54 0 54 # 37 80 28 54 0 54 # 38 80 29 54 0 54 # 39 40 30 55 0 55 # 40 40 31 55 0 55 # 41 40 32 55 0 55 # 42 40 33 55 0 55 # 43 40 34 55 0 55 # 44 40 35 56 0 56 # 45 40 36 57 0 57 # 46 40 37 58 0 58 # 47 40 38 58 0 58 # 48 40 39 58 0 59 # 49 40 40 58 0 59 # 50 40 41 58 0 59 # 51 40 42 58 0 59 # 52 40 43 58 0 59 # 53 40 44 58 0 59 # 54 40 45 58 0 59 # 55 40 46 58 0 59 # 56 40 47 58 0 59 # 57 40 48 58 0 59 # 58 20 49 59 32000 59 # 59 |
Пример 7.2. Результат работы команды dispadmin -c TS -g |
Закрыть окно |
# Real Time Dispatcher Configuration RES=1000 TIME QUANTUM(rt_quantum) PRIORITY LEVEL 1000 # 0 1000 # 1 1000 # 2 1000 # 3 1000 # 4 1000 # 5 1000 # 6 1000 # 7 1000 # 8 1000 # 9 800 # 10 800 # 11 800 # 12 800 # 13 800 # 14 800 # 15 800 # 16 800 # 17 800 # 18 800 # 19 600 # 20 600 # 21 600 # 22 600 # 23 600 # 24 600 # 25 600 # 26 600 # 27 600 # 28 600 # 29 400 # 30 400 # 31 400 # 32 400 # 33 400 # 34 400 # 35 400 # 36 400 # 37 400 # 38 400 # 39 200 # 40 200 # 41 200 # 42 200 # 43 200 # 44 200 # 45 200 # 46 200 # 47 200 # 48 200 # 49 100 # 50 100 # 51 100 # 52 100 # 53 100 # 54 100 # 55 100 # 56 100 # 57 100 # 58 100 # 59 |
Пример 7.3. Таблица диспетчера |
Закрыть окно |
ps -ef | more UID PID PPID C STIME TTY TIME CMD root 0 0 0 17:43:30 ? 0:03 sched root 1 0 0 17:43:30 ? 0:00 /etc/init -s root 2 0 0 17:43:30 ? 0:00 pageout root 3 0 0 17:43:30 ? 0:00 fsflush root 349 1 0 17:43:53 ? 0:00 /usr/lib/saf/sac -t 300 root 277 276 0 17:43:49 ? 0:00 htt_server -port 9010 -syslog -message_locale C root 180 1 0 17:43:45 ? 0:00 /usr/lib/autofs/automountd root 59 1 0 17:43:39 ? 0:00 /usr/lib/sysevent/syseventd root 73 1 0 17:43:40 ? 0:00 /usr/lib/picl/picld root 133 1 0 17:43:43 ? 0:00 /usr/sbin/rpcbind root 229 1 0 17:43:48 ? 0:00 /usr/lib/power/powerd root 172 1 0 17:43:44 ? 0:00 /usr/lib/nfs/lockd root 156 1 0 17:43:44 ? 0:00 /usr/sbin/inetd -s root 217 1 0 17:43:47 ? 0:00 /usr/lib/lpsched daemon 168 1 0 17:43:44 ? 0:00 /usr/lib/nfs/statd root 189 1 0 17:43:45 ? 0:00 /usr/sbin/syslogd root 203 1 0 17:43:46 ? 0:00 /usr/sbin/cron root 205 1 0 17:43:46 ? 0:00 /usr/sbin/nscd root 343 1 0 17:43:53 ? 0:00 /usr/sbin/vold root 240 1 0 17:43:48 ? 0:00 /usr/lib/utmpd root 324 1 0 17:43:51 ? 0:00 /usr/lib/snmp/snmpdx -y -c /etc/snmp/conf root 261 1 0 17:43:49 ? 0:00 /usr/sadm/lib/smc/bin/smcboot root 355 329 0 17:43:56 ? 0:00 /usr/dt/bin/dtlogin -daemon root 329 1 0 17:43:52 ? 0:00 /usr/dt/bin/dtlogin -daemon root 262 261 0 17:43:49 ? 0:00 /usr/sadm/lib/smc/bin/smcboot root 263 261 0 17:43:49 ? 0:00 /usr/sadm/lib/smc/bin/smcboot root 354 1 0 17:43:55 ? 0:00 /usr/lib/ssh/sshd root 338 1 0 17:43:52 ? 0:00 /usr/lib/dmi/snmpXdmid -s sunny root 352 349 0 17:43:53 ? 0:00 /usr/lib/saf/ttymon root 353 329 2 17:43:54 ? 1:41 /usr/openwin/bin/Xsun :0 -nobanner -auth /var/dt/A:0-KtaiPa root 356 329 0 17:43:56 ? 0:00 /usr/openwin/bin/fbconsole -d :0 root 358 324 0 17:43:57 ? 0:00 mibiisa -r -p 5248 root 337 1 0 17:43:52 ? 0:00 /usr/lib/dmi/dmispd |
Пример 7.4. Результат работы программы ps |
Закрыть окно |
top last pid: 923; load averages: 4.56, 1.18, 0.50 17:54:22 64 processes: 63 sleeping, 1 on cpu CPU states: 0.0% idle, 0.5% user, 99.5% kernel, 0.0% iowait, 0.0% swap Memory: 128M real, 18M free, 101M swap in use, 499M swap free PID USERNAME LWP PRI NICE SIZE RES STATE TIME CPU COMMAND 909 root 1 60 0 17M 3340K sleep 0:00 0.92% pagein 353 root 1 58 0 32M 16M sleep0 :05 0.37% Xsun 893 root 1 49 0 2228K 1172K cpu 0:00 0.15% top 753 root 1 49 0 15M 8112K sleep 0:00 0.13% dtterm 911 root 1 59 0 3352K 752K sleep 0:00 0.03% sh 912 root 1 49 0 3360K 600K sleep 0:00 0.03% sh 894 root 1 59 0 3064K 1816K sleep 0:00 0.03% dtexec 656 root 5 59 0 22M 10M sleep 0:01 0.02% dtwm 648 root 1 59 0 6644K 2280K sleep 0:00 0.02% ttsession 667 root 1 59 0 1844K 512K sleep 0:00 0.02% rpc.rstatd 277 root 29 59 0 5612K 1724K sleep 0:00 0.01% htt_server 895 root 1 59 0 3360K 756K sleep 0:00 0.01% soffice 720 root 4 49 0 42M 26M sleep 0:03 0.00% mozilla-bin 649 root 1 49 0 18M 6288K sleep 0:00 0.00% dtsession 760 root 1 49 0 4752K 1656K sleep 0:00 0.00% bash |
Пример 7.5. Результат работы команды top |
Закрыть окно |
pargs 2793 2793: dtterm -name Run -xrm *menuBar: False -iconic -map -e /usr/dt/bin/dtexec -open argv[0]: dtterm argv[1]: -e argv[2]: /usr/dt/bin/dtexec argv[3]: -open argv[4]: -1 argv[5]: -ttprocid argv[6]: 2.10fX-r 01 648 1289637086 1 1 0 192.168.5.33 5 sunny_105_1 argv[7]: /export/home/mozilla_bin/sfw/bin/mozilla argv[8]: <NULL> argv[9]: -open argv[10]: -1 argv[11]: -ttprocid argv[12]: 2.10fX-r 01 648 1289637086 1 1 0 192.168.5.33 5 sunny_105_1 argv[13]: /export/home/mozilla_bin/sfw/bin/mozilla pargs -e 2793 2793: dtterm -name Run -xrm *menuBar: False -iconic -map -e /usr/dt/bin/dtexec -open envp[0]: AB_CARDCATALOG=/usr/dt/share/answerbooks/ru_RU.UTF-8/ab_cardcatalog envp[1]: DISPLAY=:0.0 envp[2]: DTAPPSEARCHPATH=//.dt/appmanager:/etc/dt/appconfig/appmanager/%L:/etc/dt/appconfig/appmanager/C:/usr/dt/appconfig/appmanager/%L:/usr/dt/appconfig/appmanager/C envp[3]: DTDATABASESEARCHPATH=//.dt/types,/etc/dt/appconfig/types/%L,/etc/dt/appconfig/types/C,/usr/dt/appconfig/types/%L,/usr/dt/appconfig/types/C |
Пример 7.6. Результат работы программы pargs |
Закрыть окно |
prstat PID USERNAME SIZE RSS STATE PRI NICE TIME CPU PROCESS/NLWP 3576 root 3412K 868K run 13 0 0:00:02 6,3% find/1 353 root 45M 19M sleep 59 0 0:02:30 0,2% Xsun/1 753 root 15M 3620K run 49 0 0:00:02 0,1% dtterm/1 3577 root 6640K 4108K cpu0 49 0 0:00:00 0,1% prstat/1 205 root 2872K 624K sleep 59 0 0:00:00 0,0% nscd/18 895 root 123M 21M sleep 49 0 0:00:49 0,0% soffice.bin/4 667 root 1844K 488K sleep 59 0 0:00:00 0,0% rpc.rstatd/1 217 root 5364K 536K sleep 59 0 0:00:00 0,0% lpsched/1 324 root 4360K 196K sleep 59 0 0:00:00 0,0% snmpdx/1 240 root 1100K 288K sleep 59 0 0:00:00 0,0% utmpd/1 343 root 4892K 0K sleep 59 0 0:00:00 0,0% vold/3 276 root 3240K 0K sleep 59 0 0:00:00 0,0% htt/1 633 root 3784K 0K sleep 59 0 0:00:00 0,0% sdt_shell/1 657 root 16M 2496K sleep 49 0 0:00:00 0,0% dtfile/1 203 root 4484K 568K sleep 59 0 0:00:00 0,0% cron/1 189 root 5636K 1092K sleep 59 0 0:00:00 0,0% syslogd/13 168 daemon 2444K 820K sleep 59 0 0:00:00 0,0% statd/1 156 root 2412K 688K sleep 59 0 0:00:00 0,0% inetd/1 172 root 2160K 748K sleep 59 0 0:00:00 0,0% lockd/2 229 root 1348K 0K sleep 59 0 0:00:00 0,0% powerd/2 133 root 2212K 604K sleep 59 0 0:00:00 0,0% rpcbind/1 Total: 61 processes, 161 lwps, load averages: 0,25, 0,17, 0,27 |
Пример 7.7. Результат работы программы prstat |
Закрыть окно |
Идентификаторы процесса
Процесс всегда имеет свой уникальный номер - 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.
Иерархия процессов в Solaris
Процессы делятся на процессы ядра и на все остальные процессы (последние называются пользовательскими процессами). Пользовательский процесс не обязательно запущен неким пользователем, то, что он - "пользовательский", означает лишь, что он не принадлежит ядру.
Само ядро Solaris представляет собой множество потоков (threads), которые выполняются параллельно. Действительно, у ядра много разных дел, было бы странно, если бы ядро пыталось все делать последовательно, а не параллельно. Термин threads часто переводят как "нить", но мы будем говорить в контексте управления процессами именно о "потоках", понимая под этим "потоки команд", в отличие от "потоков данных", которые будут рассмотрены ниже.
Потоки ядра чрезвычайно "легковесные", они обладают лишь маленькими сегментом данных и стэком. Передача управления от одного потока ядра другому не требует изменения базовых адресов виртуальной памяти. Каждый поток ядра имеет свой приоритет и может относиться к определенному классу потоков, в том числе и к классу потоков "реального времени".
Solaris реализует многоуровневую поточную модель. Ее назначение - разделить управление потоками пользовательского уровня и работу ядра. Потоки пользовательского уровня имеют свою схему приоритетов. Их планирование проводится с помощью потока-планировщика. Такой поток создается библиотекой потоков, когда многопоточное приложение компилируется и выполняется. Внутри одного пользовательского процесса могут работать свои потоки, передача управления между которыми осуществляется внутренним планировщиком этого процесса. Благодаря этому многопоточные приложения могут порождать тысячи потоков без существенной загрузки ядра. Оно будет видеть это приложение как один процесс. По сути, ядро не видит пользовательские потоки, пока они не присоединяются к легковесному процессу (lightweight process, LWP), имеющему определенное положение в операционной системе. Поток-планировщик отвечает за отображение пользовательских потоков в легковесный процесс (LWP), который связан с потоком ядра для выполнения процессором. Каждый LWP имеет поток ядра, но необязательно каждый поток ядра имеет LWP. Часть потоков ядра задействованы исключительно операционной системой, поэтому LWP здесь не требуется.
Интерактивные и фоновые процессы
Процесс в UNIX может быть интерактивным и фоновым. Процесс, который имеет доступ к вводу с терминала и к выводу на него, называется интерактивным (foreground). Таким процессом является почтовая программа mail, редактор текста vi и другие программы. Фоновый процесс не имеет доступа к вводу с терминала, и имеет условный доступ к выводу на терминал. Условие состоит в том, что вывод на терминал разрешен фоновому процессу, если терминал настроен для работы в режиме tostop. Эту настройку можно выполнить командой
stty -tostop
Обратная настройка выполняется командой
stty tostop
Если фоновый процесс пытается выводить что-либо на терминал, настроенный для работы в режиме tostop, то процессу посылается сигнал SIGSTOP. Процесс, получивший такой сигнал, останавливается (переводится в состояние STOPPED).
Если фоновый процесс начинает выполнять вывод на терминал в то время, когда вы работаете в текстовом редакторе или подобной программе, текст на экране может перемешаться. Это не беда: на фактическое содержание редактируемого файла это никакого влияния не оказывает. В большинстве полноэкранных программ под UNIX достаточно нажать Ctrl-L, чтобы обновить экран, и назойливые сообщения исчезнут.
Для запуска фонового процесса из командного интерпретатора следует дать команду, завершив ее знаком "&" (амперсэнд):
команда &
Можно запустить сборку пакета программ в фоновом режиме, и пока он собирается, выполнять другую работу:
make all &
Каналы и сокеты
Процессы могут обмениваться данными друг с другом, и в UNIX предусмотрены механизмы такого обмена. Прежде всего, это каналы (pipes) и сокеты (sockets), которые служат для межпроцессной коммуникации, т.е. для передачи данных между одновременно запущенными процессами.
Канал - это последовательность байт, используемая как однонаправленный поток ввода/вывода.
С точки зрения программиста, бывают именованные и неименованные каналы, и способы обращения к ним несколько отличаются. При использовании канала один процесс открывает канал для чтения, другой - для записи.
Сокет - это объект, который используется для межпроцессных коммуникаций; он существует, пока какой-либо процесс хранит дескриптор, ссылающийся на него. Сокет создается системным вызовом socket, который возвращает его дескриптор. Имеется несколько типов сокетов, которые поддерживают различные возможности передачи данных.
Для каждого процесса ядро хранит таблицу внутренних дескрипторов. По-английски эта таблица называется "descriptor table", и чтобы не путать ее с таблицей дескрипторов в файловой системе, мы называем внутреннюю таблицу дескрипторов, относящуюся к конкретному процессу, "таблицей внутренних дескрипторов". Слово "внутренних" подчеркивает то, что эти дескрипторы существуют только в пределах процесса, который пользуется ими для обращения к файлам. Эта таблица наследуется от родительского процесса, поэтому вместе с ней наследуется и доступ к объектам, на которые ссылаются дескрипторы (файлам, каналам, сокетам).
Основными способами, при помощи которых процесс может получить дескриптор, является открытие или создание объекта, а также наследование от родительского процесса. Когда процесс завершается, ядро освобождает все дескрипторы, которые использовались этим процессом. Если процесс хранил последнюю ссылку на объект - файл или канал (т.е. в файловой системе больше не содержится записей об этом объекте), то система выполняет окончательное удаление файла (канала) или уничтожение сокета.
Подробнее о сокетах можно прочесть в socket(3)1).
Классы планирования
В Solaris 9 есть шесть классов планирования: с разделением времени (timesharing, TS), интерактивный (interactive, IA), системный (system, SYS), реального времени (real-time, RT),с фиксированным приоритетом (fixed priority, FX) и планирование на основе справедливого раздела (fair share scheduling, FSS).
159–100 | Процессы реального времени (0-59) |
99–60 | Системные процессы |
59–0 | Приоритеты процессов с разделением времени (0-59) |
По умолчанию процессы попадают в класс с разделением времени.
С помощью команды
ps -cl
можно узнать глобальные приоритеты запущенных в данный момент процессов, а "внутренние" приоритеты процессов в разных классах планирования - с помощью команды dispadmin.
Команды наблюдения за процессами
Для просмотра текущего списка и состояния процессов следует использовать программу ps. Она выдает "мгновенный снимок" таблицы процессов, которые запущены в системе.
Программа ps без аргументов сообщает список процессов, запущенных пользователем в текущей сессии. Обычно системного администратора интересуют все запущенные в системе процессы, список которых можно узнать по команде
ps -ef
В системах BSD и System V программа ps имеет разные ключи, поэтому если вы переходите от одной системы к другой, надо помнить об этих различиях или обращаться к man ps.
Разберем подробнее, какую информацию выдает программа ps:
Пример 7.4. Результат работы программы ps (html, txt)
Ниже мы описываем смысл колонок этого вывода. Некоторые колонки появятся только при использовании специфических ключей, отличных от ключей 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:
Пример 7.5. Результат работы команды top (html, txt)
В Solaris для удобства получения информации о процессах с определенными именами есть команда
pgrep имя
Она является эквивалентом команды
ps -ef | grep имя
С помощью pargs можно посмотреть, какие аргументы переданы конкретному процессу и какая у него среда окружения:
Пример 7.6. Результат работы программы pargs (html, txt)
Вывод команды pargs значительно сокращен, ключ -e требует вывести все содержимое среды окружения, а для графических программ типа dtterm, как в нашем примере, среда окружения весьма велика.
Команда prstat позволяет в динамике, подобно команде top, отслеживать состояние процессов:
Пример 7.7. Результат работы программы prstat (html, txt)
Вы можете получить информацию только о тех процессах, которые запущены вами. Пользователю root доступна информация о любых процессах.
top last pid: 923; load averages: 4.56, 1.18, 0.50 17:54:22 64 processes: 63 sleeping, 1 on cpu CPU states: 0.0% idle, 0.5% user, 99.5% kernel, 0.0% iowait, 0.0% swap Memory: 128M real, 18M free, 101M swap in use, 499M swap free
PID USERNAME LWP PRI NICE SIZE RES STATE TIME CPU COMMAND 909 root 1 60 0 17M 3340K sleep 0:00 0.92% pagein 353 root 1 58 0 32M 16M sleep0 :05 0.37% Xsun 893 root 1 49 0 2228K 1172K cpu 0:00 0.15% top 753 root 1 49 0 15M 8112K sleep 0:00 0.13% dtterm 911 root 1 59 0 3352K 752K sleep 0:00 0.03% sh 912 root 1 49 0 3360K 600K sleep 0:00 0.03% sh 894 root 1 59 0 3064K 1816K sleep 0:00 0.03% dtexec 656 root 5 59 0 22M 10M sleep 0:01 0.02% dtwm 648 root 1 59 0 6644K 2280K sleep 0:00 0.02% ttsession 667 root 1 59 0 1844K 512K sleep 0:00 0.02% rpc.rstatd 277 root 29 59 0 5612K 1724K sleep 0:00 0.01% htt_server 895 root 1 59 0 3360K 756K sleep 0:00 0.01% soffice 720 root 4 49 0 42M 26M sleep 0:03 0.00% mozilla-bin 649 root 1 49 0 18M 6288K sleep 0:00 0.00% dtsession 760 root 1 49 0 4752K 1656K sleep 0:00 0.00% bash
Пример 7.5. Результат работы команды top
В Solaris для удобства получения информации о процессах с определенными именами есть команда
pgrep имя
Она является эквивалентом команды
ps -ef | grep имя
С помощью pargs можно посмотреть, какие аргументы переданы конкретному процессу и какая у него среда окружения:
pargs 2793 2793: dtterm -name Run -xrm *menuBar: False -iconic -map -e /usr/dt/bin/dtexec -open argv[0]: dtterm argv[1]: -e argv[2]: /usr/dt/bin/dtexec argv[3]: -open argv[4]: -1 argv[5]: -ttprocid argv[6]: 2.10fX-r 01 648 1289637086 1 1 0 192.168.5.33 5 sunny_105_1 argv[7]: /export/home/mozilla_bin/sfw/bin/mozilla argv[8]: <NULL> argv[9]: -open argv[10]: -1 argv[11]: -ttprocid argv[12]: 2.10fX-r 01 648 1289637086 1 1 0 192.168.5.33 5 sunny_105_1 argv[13]: /export/home/mozilla_bin/sfw/bin/mozilla
pargs -e 2793 2793: dtterm -name Run -xrm *menuBar: False -iconic -map -e /usr/dt/bin/dtexec -open envp[0]: AB_CARDCATALOG=/usr/dt/share/answerbooks/ru_RU.UTF-8/ab_cardcatalog envp[1]: DISPLAY=:0.0 envp[2]: DTAPPSEARCHPATH=//.dt/appmanager:/etc/dt/appconfig/appmanager/%L:/etc/dt/appconfig/appmanager/C:/usr/dt/appconfig/appmanager/%L:/usr/dt/appconfig/appmanager/C envp[3]: DTDATABASESEARCHPATH=//.dt/types,/etc/dt/appconfig/types/%L,/etc/dt/appconfig/types/C,/usr/dt/appconfig/types/%L,/usr/dt/appconfig/types/C
Пример 7.6. Результат работы программы pargs
Вывод команды pargs значительно сокращен, ключ -e требует вывести все содержимое среды окружения, а для графических программ типа dtterm, как в нашем примере, среда окружения весьма велика.
Команда prstat позволяет в динамике, подобно команде top, отслеживать состояние процессов:
prstat PID USERNAME SIZE RSS STATE PRI NICE TIME CPU PROCESS/NLWP 3576 root 3412K 868K run 13 0 0:00:02 6,3% find/1 353 root 45M 19M sleep 59 0 0:02:30 0,2% Xsun/1 753 root 15M 3620K run 49 0 0:00:02 0,1% dtterm/1 3577 root 6640K 4108K cpu0 49 0 0:00:00 0,1% prstat/1 205 root 2872K 624K sleep 59 0 0:00:00 0,0% nscd/18 895 root 123M 21M sleep 49 0 0:00:49 0,0% soffice.bin/4 667 root 1844K 488K sleep 59 0 0:00:00 0,0% rpc.rstatd/1 217 root 5364K 536K sleep 59 0 0:00:00 0,0% lpsched/1 324 root 4360K 196K sleep 59 0 0:00:00 0,0% snmpdx/1 240 root 1100K 288K sleep 59 0 0:00:00 0,0% utmpd/1 343 root 4892K 0K sleep 59 0 0:00:00 0,0% vold/3 276 root 3240K 0K sleep 59 0 0:00:00 0,0% htt/1 633 root 3784K 0K sleep 59 0 0:00:00 0,0% sdt_shell/1 657 root 16M 2496K sleep 49 0 0:00:00 0,0% dtfile/1 203 root 4484K 568K sleep 59 0 0:00:00 0,0% cron/1 189 root 5636K 1092K sleep 59 0 0:00:00 0,0% syslogd/13 168 daemon 2444K 820K sleep 59 0 0:00:00 0,0% statd/1 156 root 2412K 688K sleep 59 0 0:00:00 0,0% inetd/1 172 root 2160K 748K sleep 59 0 0:00:00 0,0% lockd/2 229 root 1348K 0K sleep 59 0 0:00:00 0,0% powerd/2 133 root 2212K 604K sleep 59 0 0:00:00 0,0% rpcbind/1 Total: 61 processes, 161 lwps, load averages: 0,25, 0,17, 0,27
Пример 7.7. Результат работы программы prstat
Вы можете получить информацию только о тех процессах, которые запущены вами. Пользователю root доступна информация о любых процессах.
Команды управления процессами
Основным средством управления процессами является команда 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.
Настройка таблиц диспетчера
Таблицы диспетчера можно настроить с помощью команды dispadmin. Настройка выполняется следующим образом: вначале таблица диспетчера конкретного класса выводится в файл, затем файл редактируется в текстовом редакторе и загружается обратно в таблицу диспетчера. Вывод и загрузка таблицы осуществляется с помощью программы dispadmin.
Чтобы узнать, какие классы доступны для редактирования, следует запустить dispadmin с ключом -l и определить активные классы планирования:
dispadmin -l CONFIGURED CLASSES ================== SYS (System Class) TS (Time Sharing) FX (Fixed Priority) IA (Interactive) RT (Real Time)
Далее выводим таблицу диспетчера для выбранного класса (попробуем это на классе планирования с разделением времени - TS):
Пример 7.2. Результат работы команды dispadmin -c TS -g (html, txt)
Первая строка, в которой указано значение RES, определяет, в чем измеряется время во всей таблице приоритетов данного класса. Величина RES фактически задает дискретность измерения времени для столбца ts_quantum таблицы диспетчера. Ее значение по умолчанию - 1000. Изменять дискретность не рекомендуется. Обратная к RES величина равна 0,001, и это интерпретируется как одна тысячная секунды, т.е. одна миллисекунда. Стало быть, по умолчанию время в столбце ts_quantum измеряется в миллисекундах.
Как было показано в разделе "Диспетчер" выше, смысл значений, приведенных в столбцах таблицы диспетчера, следующий:
ts_quantum представляет собой максимальный период времени (квант), в течение которого поток может оставаться в процессоре до того, как диспетчер изменит его приоритет;ts_tqexp задает приоритет, который будет назначен потоку после того, как истечет его квант времени и он будет удален из процессора;ts_slpret указывает приоритет, который будет иметь процесс, когда он будет обрабатываться после "сна", т.е. после ожидания завершения ввода-вывода или когда он дождется снятия блокировки с требуемого ему ресурса;ts_maxwait указывает время в секундах, которое процесс будет оставаться в очереди, в случае, если его квант времени еще не истек; если он не использует свой квант времени в течение этого числа секунд, ему будет присвоен новый приоритет ts_lswait. Если ts_maxwait равно нулю, то принимается значение по умолчанию (одна секунда);ts_lswait обозначает присваиваемый процессу приоритет, когда процесс на долгое время был вытеснен из процессора.
В таблицах диспетчера указываются относительные приоритеты (которые имеют силу внутри класса планирования). Глобальный (иначе говоря - абсолютный) приоритет вычисляется из относительного в соответствии с табл. 8.1.
Обратите внимание на то, что более высокоприоритетные процессы имеют меньшие кванты времени. Значение 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 |
и т.д. | и т.д. |
Класс реального времени (RT) описывается более простой таблицей диспетчера:
Пример 7.3. Таблица диспетчера (html, txt)
Потоки реального времени выполняются до завершения или до истечения их кванта (если в очереди стоят несколько потоков реального времени). Потокам реального времени присваивается самый высокий абсолютный приоритет, даже более высокий, чем потокам ядра, потому что относительные приоритеты отображаются в абсолютные, как показано в табл. 8.1.
# Real Time Dispatcher Configuration RES=1000 TIME QUANTUM(rt_quantum) PRIORITY LEVEL 1000 # 0 1000 # 1 1000 # 2 1000 # 3 1000 # 4 1000 # 5 1000 # 6 1000 # 7 1000 # 8 1000 # 9 800 # 10 800 # 11 800 # 12 800 # 13 800 # 14 800 # 15 800 # 16 800 # 17 800 # 18 800 # 19 600 # 20 600 # 21 600 # 22 600 # 23 600 # 24 600 # 25 600 # 26 600 # 27 600 # 28 600 # 29 400 # 30 400 # 31 400 # 32 400 # 33 400 # 34 400 # 35 400 # 36 400 # 37 400 # 38 400 # 39 200 # 40 200 # 41 200 # 42 200 # 43 200 # 44 200 # 45 200 # 46 200 # 47 200 # 48 200 # 49 100 # 50 100 # 51 100 # 52 100 # 53 100 # 54 100 # 55 100 # 56 100 # 57 100 # 58 100 # 59
Пример 7.3. Таблица диспетчера
Потоки реального времени выполняются до завершения или до истечения их кванта (если в очереди стоят несколько потоков реального времени). Потокам реального времени присваивается самый высокий абсолютный приоритет, даже более высокий, чем потокам ядра, потому что относительные приоритеты отображаются в абсолютные, как показано в табл. 8.1.
Перенаправление потоков
Поток данных, связанный с процессом, может быть перенаправлен в файл или другой поток данных. Например, если требуется, чтобы программа 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 стандартный планировщик задач (диспетчер) старается предоставить процессам, которые по умолчанию запускаются с классом планирования 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
Планирование процессов реального времени
Планирование в реальном времени относится к средствам, с помощью которых процессу по мере необходимости обеспечивается квант процессора. Такая схема характерна для некоторых типов приложений, например, в робототехнике или управлении полетом. Вообще, поддержка планирования в реальном времени важна там, где требуется гарантированное время реакции системы на внешнее событие: в системах управления технологическими процессами, военных системах, коммуникационных системах и т.п. При написании приложения, которое управляет ракетой, заслонкой дозатора краски или даже простым видеотелефоном, приходится гарантировать время его реакции на прерывание, вызванное внешним событием, чтобы обеспечить разумное поведение приложения. Может выйти накладка, если ракета пролетит мимо цели, краски в крем для торта выльется больше, чем сливок, а изображения разных частей лица на видеофоне не будут синхронизированы во времени.
Существуют три варианта планирования процессов реального времени: его поддержки нет совсем, существует строгая поддержка реального времени (для приложений соблюдаются все предельные сроки) и выполняется нестрогая поддержка реального времени (предельные сроки могут быть пропущены, но поддерживается статистический минимум). Solaris - это среда с нестрогой поддержкой реального времени. А потому, для управления ракетой она может и не подойти - это зависит от алгоритма управления. Поддержка статистического минимума означает, что ракета может пролететь мимо, но зато вернется (если ее не собьют раньше или не закончится топливо).
В нестрогой среде реального времени период реакции должен иметь гарантированную конечную продолжительность (например, верхний предел времени, за которое приложение должно освободить процессор; в Solaris такой период составляет 5 миллисекунд).
В большинстве систем UNIX поддержки реального времени нет. Это связано с тем, что:
"промахи" обращения к памяти из-за отсутствия страниц в оперативной памяти могут вызвать непредсказуемую задержку вследствие необходимости подгрузить требуемую страницу в память из swap-раздела;хотя ядро является выгружаемым (preemptable) - т.е. оно может быть смещено из процессора при запуске другого процесса, - в некоторых ситуациях все же не допускается выгрузка ядра из процессора, например, при обработке прерывания; элементы кода, которые не могут быть выгружены из процессора во время выполнения, называются "точками невыгружаемости" (nonpreemption points).
Решение первой из этих проблем в Solaris состоит в том, что все страницы процесса реального времени в памяти блокируются и их выгрузка на диск запрещается. Вторая проблема решается за счет того, что ядро Solaris - многопотоковое, обработчики прерываний реализованы как отдельные потоки, что делает возможным установить для них отдельный приоритет; более того, в Solaris есть возможность priority lending - "одалживание приоритета". Это означает, что когда более приоритетный процесс нуждается в результатах работы менее приоритетного процесса, он может "одолжить" последнему на время свой высокий приоритет для выполнения требуемой задачи.
Планирование запуска процессов
Вынесете ли вы сегодня мусор или пойдете в магазин, поедете на заправку кормить своего железного коня бензином или просто ляжете спать пораньше - так или иначе, какое-нибудь дело вы сегодня сделаете. Дела, которые вы делаете, могут быть однократными (купить щенка) или регулярными (погулять с собакой). Может быть, "однократные" - не совсем точное прилагательное, потому что щенка вы можете купить и раз, и два, и еще много раз в жизни. Но вряд ли это дело можно назвать регулярным - не станете же вы раз в год ровно в полночь 13 марта покупать щенка.
Все-таки станете? Вы не сатанист, часом?
Еще приятнее запланировать выполнение нерегулярного или регулярного дела так, чтобы его делал кто-то другой. Например, сообщите сыну, что вы просите его завтра в полдень отправиться в клуб собаководов и купить там щеночка. Однократно. А потом (когда купит) скажите, что вы запланировали его (сына) прогулки с ним (щеночком) ежедневно - на годы вперед.
Системный администратор, даже если у него нет сына и щеночка, тоже не лишен радостей планирования. Так, для планирования однократных действий в любом UNIX используется программа at, а для регулярных - crontab.
Приоритеты процесса
Во многих системах UNIX процесс имеет базовый приоритет (NICE) и динамический приоритет (PRI). Базовый приоритет может принимать значение от -20 до +20. Чем меньше числовое значение базового приоритета NICE, тем выше приоритет. Процесс с отрицательным приоритетом -20 - самый высокоприоритетный. Динамический приоритет вычисляется планировщиком задач на основе базового приоритета по формуле, в которую входит общее потребленное процессом процессорное время. Чтобы дать возможность выполняться новым и более коротким процессам, динамический приоритет снижается с увеличением потребленного процессом времени процессора.
В Solaris применяется более сложная схема планирования приоритетов процессов, которая описывается ниже. Для процессов одного из классов планирования (с разделением времени) справедлива вышеописанная простая схема из базового и динамического приоритетов.
Каждый процесс может быть представлен одним или несколькими потоками ядра. С точки зрения ядра, объектом назначения того или иного приоритета является поток ядра. Если процесс сопоставлен только одному потоку ядра, то приоритет процесса и приоритет этого потока ядра - это одно и то же.
Приоритет базируется на классе планирования (scheduling class); всего различают четыре класса планирования: с разделением времени (timesharing), системный (system), реального времени (real-time) и планирование на основе справедливого раздела (fair Class scheduling, FCS). У процессов разных классов планирования свои уровни приоритета и свои очереди на выполнение. Стало быть, в системе мы имеем четыре очереди к процессору. Внутри каждого класса процессы, стоящие в очереди, имеют свои уровни приоритета. Эти уровни отображаются в глобальные приоритеты планирования (global scheduling priorities). Первым процессор займет процесс, который имеет наивысший глобальный приоритет. По умолчанию, процесс из класса планирования с разделением времени имеет более низкий глобальный приоритет, чем процесс из системного класса, а тот, в свою очередь, более низкий, чем процесс реального времени.
Процесс получает свой класс планирования и приоритет в наследство от процесса-родителя. Изменить класс планирования можно либо с помощью команды priocntl, либо посредством одноименного системного вызова.
Получить информацию о текущих классах планирования процессов можно с помощью команды dispadmin.
Процессы-зомби
В Solaris 9 появилась новая программа preap, которая позволяет убрать из системы "мнимые" (defunct), не до конца завершившиеся процессы, которые также носят название "зомби" (zombie). Эти процессы совершенно безобидны, так как это - самые обыкновенные процессы, код завершения которых не был принят родительскими процессами (например, в результате преждевременного завершения родительского процесса или иного сбоя). Несмотря на безобидность, они могут попусту занимать ресурсы системы, если таких процессов будет много. Обычно процессы-зомби автоматически уничтожаются процессом init, но если этого почему-либо не произошло, можно воспользоваться программой preap, которая примет код завершения процесса-зомби и даст ему упокоиться с миром.
Проверка приоритета процесса
Выяснить, с каким легковесным процессом ассоциирован конкретный процесс и какой класс планирования ему назначен, можно с помощью команды ps и ключей -L и -с:
Пример 7.1. Результат работы команды ps c ключами -L и -c (html, txt)
Вывод этой команды здесь сильно сокращен: процессов в системе на самом деле всегда значительно больше. Сейчас нам интересны прежде всего колонки LWP, CLS и PRI, в которых показаны номер легковесного процесса, класс планирования и глобальный приоритет соответственно.
Чем больше числовое значение глобального приоритета (значение PRI), тем выше глобальный приоритет процесса.
Мы видим, что многопоточные процессы (например, демон автомонтирования /usr/lib/autofs/automountd и демон протоколирования /usr/sbin/syslogd) могут одновременно иметь несколько LWP (в колонке NLWP указано количество LWP, с которыми ассоциирован процесс).
Работа с заданиями
Заданием называют запущенные одной командой несколько программ (в частном случае это может быть и одна программа). Для управления заданиями можно использовать встроенные команды командных интерпретаторов. Так, в большинстве из них есть команды jobs, bg и fg - для получения информации о заданиях, переключении задания в фоновый или интерактивный режим соответственно.
Более подробно о работе с заданиями говорится в лекции 9.
Распределение памяти. Swaping
В любой многопроцессной системе запущенные процессы и процессы, которые ждут возможности продолжить свое выполнение, могут в сумме занимать больший объем, чем объем установленной оперативной памяти, и поэтому в таких системах используют виртуальную память. Виртуальная память складывается из оперативной памяти и swap-разделов, размещенных на жестких дисках компьютера.
В UNIX вся память разделена на страницы определенного одинакового размера. Каждый процесс получает от системы запрошенное количество памяти, выделение памяти в UNIX осуществляется постранично. Процессы реального времени и часть кода ядра (например, та, что отвечает за обмен страницами между оперативной памятью и диском) всегда находятся в памяти, страницы остальных процессов могут быть выгружены на диск. В большинстве систем UNIX размер страницы составляет 4 Кбайт. В Solaris для x86 он ровно такой же, но на платформе SPARC может быть другой размер страницы, т.к. это свойство системы зависит от платформы. Узнать размер страницы памяти в Solaris можно по команде pagesize.
Традиционно в литературе по системам UNIX для описания процесса обмена страницами между памятью и диском используют термин "свопинг" (swaping). Этот термин в действительности означает полную выгрузку страниц процесса на диск. На самом деле менеджер виртуальной памяти в UNIX обычно выполняет "пейджинг" (paging), что означает постраничную (частичную) выгрузку процесса на диск. Свопинг выполняется в том случае, если памяти критически не хватает, чего при нормальной работе системы не наблюдается.
Алгоритм, который используется для выгрузки страниц в UNIX, называется "алгоритмом часов". Предполагается, что сканер страниц памяти время от времени указывает "стрелкой" этих "часов" на случайно выбранную страницу памяти. Как только это произошло, страница становится кандидатом на выгрузку. Если в течение определенного промежутка времени к ней не произошло обращения, ее и в самом деле выгружают на диск.
Более подробно алгоритм работы менеджера виртуальной памяти рассмотрен в лекции 7 курса "Администрирование ОС Solaris".
Для функционирования системы обязательно требуется, чтобы существовал по крайней мере один swap-раздел. При его создании рекомендуют отвести такому разделу не менее удвоенного объема оперативной памяти. Даже если вы являетесь сторонником выполнения этой рекомендации, постарайтесь подойти к ней критически: создание огромного swap-раздела, который никогда не будет использован даже наполовину, столь же нерационально, как и создание слишком маленького swap-раздела, который доведет систему до критической нехватки виртуальной памяти, что чревато неожиданным и принудительным завершением нужных процессов в системе.
При планировании дисковой подсистемы (в частности, размера swap-разделов) важно хорошо представлять, сколько памяти может потребоваться тем программам, которые будут одновременно работать в системе. В самом деле, если в системе планируется одновременно запускать сервер баз данных, web-сервер и несколько почтовых служб, можно предположить, что памяти понадобится много. Вполне реально оценить потребности в ней эмпирически - запустите по одной копии каждого демона, умножьте объем памяти, занятой каждым из них, на число предполагаемых демонов такого типа в рабочей системе и умножьте сумму получившихся чисел еще на два - для получения разумного запаса. Если такое количество оперативной памяти физически возможно установить в компьютер, вам светит счастливая звезда! Если нет, надо прикинуть, какой объем памяти критически важен (программы должны работать одновременно, а не лежать в swap-разделе поочереди или, не дай Бог, все вместе!), и решить, сколько при этом останется программ, которым все-таки придется "отдохнуть" на диске.
При нехватке памяти ядро UNIX просто уничтожает процессы, которые имеют более низкий приоритет, чтобы освободить место для других, более важных для системы процессов. Иногда ядро "убивает" процессы молча, даже не сообщая об этом на консоль, поэтому в условиях нехватки памяти мы можем неожиданно получить работающий, но не отвечающий ни на какие наши действия компьютер. Это лечится только аппаратным перезапуском.
Регулярно выполняемые системные скрипты
В 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 и так далее.
Семафоры
Семафоры - это механизм, который принято использовать для контроля доступа нескольких процессов к одному ресурсу. Есть несколько реализаций программного интерфейса (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=100set semsys:seminfo_semmsl=<10 + самое большое значение PROCESSES среди ваших БД>set semsys:seminfo_semmns=<столько, сколько объяснено ниже>set semsys:seminfo_semopm=100set semsys:seminfo_semvmx=32767
Значение seminfo_semmns рекомендуется установить равным сумме параметров PROCESSES всех баз данных сервера, причем самый большой из них должен быть просуммирован с коэффициентом 2, плюс еще 10 на каждую базу данных.
Узнать текущие значения параметров семафоров (Solaris) можно с помощью команды:
sysdef | tail -25
Текущие наборы семафоров в системе (Solaris) покажет команда:
ipcs -sb
Иногда случается, что при неверном завершении процесса семафоры остаются блокированными. Или бывает, что повторный запуск интенсивно использующего семафоры процесса сорвется из-за нехватки семафоров. В этом случае необходимо удалить соответствующие наборы семафоров командой
ipcrm -s semsetID
semsetID здесь означает идентификатор набора семафоров.
Сигналы
Процессы могут взаимодействовать, посылая друг другу сигналы. Список сигналов в 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.
В табл. 7.2 приведен список сигналов, определенный стандартом POSIX 1.1, а в табл. 7.3 - список сигналов, определенных в Solaris 9.
Кроме команды pkill системный администратор может найти удобной команду pgrep, которая заменяет конструкцию
ps -ef | grep команда
В Solaris для получения того же результата можно ввести более короткую команду
pgrep команда
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,161) | Определяется пользователем |
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 | Вывод на терминала для фонового процесса |
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 | * | завершение | последний сигнал реального времени |
Среда окружения
Каждый процесс имеет свою среду окружения - специальную область, в которой хранятся имена переменных и их значения. Среда окружения используется для модификации поведения процесса; так, в зависимости от значения переменной TERM текстовый редактор будет выдавать разные коды управления экраном, поскольку переменная TERM используется для задания типа терминала. Переменные среды окружения могут быть помечены как экспортируемые, это означает, что такую переменную дочерний процесс унаследует от процесса-родителя. Такие переменные, как TERM, PATH, USER обычно являются экспортируемыми. Из командной строки пометить переменную как экспортируемую можно с помощью команды export:
export TERM PATH
К переменным среды окружения легко обратиться из прикладной программы на языке С - для этого предусмотрен специальный массив строк:
char *env[]
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, ежедневно проверяющем состояние системы.
Имеет смысл удостовериться в том, что все эти новые файлы появились по известной вам причине.
Свойства процесса
Каждый процесс имеет уникальный идентификатор, владельца и группу, представленные эффективным идентификатором пользователя и эффективным идентификатором группы, реальных владельца и группу, класс планирования и приоритет. Процесс всегда претендует на процессорное время и определенный объем оперативной памяти, которые требуются для успешной работы процесса.
Рис. 7.1. Взаимоотношения процессов в многопотоковой архитектуре
Взаимодействие процессов
Процессы взаимодействуют друг с другом, используя при этом разные механизмы. Процессы могут асинхронно или синхронно передавать друг другу данные и управление доступом к ресурсам системы.
С каждым процессом связаны три независимых потока данных: стандартный ввод (stdin), стандартный вывод (stdout) и стандартный поток сообщений об ошибках (stderr). По умолчанию все три потока связаны с тем терминалом, с которого запущен процесс (стандартный ввод - с клавиатуры, вывод данных и ошибок - на экран). Стандартный ввод также называют входным потоком, а стандартный вывод - выходным.
Каждому из этих потоков сопоставлены внутренние дескрипторы файлов: входному потоку - 0, выходному потоку - 1, потоку сообщений об ошибках - 2. Внутренний дескриптор файла существует только в пределах того процесса, с которым он связан. Внутренние дескрипторы в разных процессах имеют одинаковые номера, но это физически разные внутренние дескрипторы - каждый процесс имеет свои собственные внутренние дескрипторы.
Замечание о совместимости утилит
Несмотря на то что Solaris удовлетворяет многочисленным стандартам, некоторые программы в системе (точнее, их возможности и ключи) расходятся со стандартом XPG4. Этот стандарт (The X/Open Portability Guide, Issue 4 - XPG4) представляет собой спецификацию, описывающую программы, заголовки и интерфейсы. В частности, описывается ожидаемое поведение ряда программ UNIX и их ключи.
Запуск приложения от имени владельца файла приложения
Обычно эффективные идентификаторы владельца и группы процесса достаются процессу по наследству от процесса-родителя. Но в некоторых ситуациях необходимо запустить программу с правами, большими, нежели права запускающего ее пользователя. Например, вам надо изменить свой пароль. Для этого требуется осуществить запись в файл /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).