report2.docx
Санкт-Петербургский политехнический университет Петра Великого Институт Информационных Технологий и УправленияКафедра компьютерных систем и программных технологий
Отчёт по практической работе № 2по предмету «Проектирование ОС и компонентов»
Работу выполнил студент гр. 63501/3 Мартынов С. А. Работу принял преподаватель Душутина Е. В.Санкт-Петербург 2016
Содержание
В рамках данной работы необходимо изучить процесс написания системных служб для ОС семейства Windows и демонов Linux, порядок их запуска и взаимодействия с системным журналом.
В каждую минуту времени компьютер выполняет множество задач. Не все эти задачи происходят в графическом режиме и пользователь может их наблюдать. Многие вещи (служба печати, времени, индексации) скрыта, но продолжает работать. Это обеспечи- вает возможность компьютера в одно время быть сервером печати, сервером доступа к файлам и воспроизводить музыку. Эти службы (или демоны) обладают определенными особенностями, которые будут рассмотрены в данной работе.Вторым важным вопросом является распространение кода программ. Исходный код позво- ляет всегда быть уверенным в том, что приложение делает то, что обещал разработчик, но на практике подобный подход не всегда возможет как с точки зрения защиты исходного кода коммерческих продуктов, так и по причине долгой сборки (к примеру браузер Mozilla Firefox может компилироваться почти 20 часов на среднем компьютере). Эта проблема ре- шается распространением бинарных пакетов, которые необходимо правильно организовать на компьютере пользователя.
Фоновые приложения в Linux
Понятие процесса и демона
В любой многозадачной системе одновременно может быть запущено много программ, то есть много процессов. В действительности в каждый момент времени выполняется только один процесс. Ядро (по средствам планировщика) выделяет каждому процессу небольшой квант времени и по истечении этого кванта передает управление следующему процессу. Кванты времени, выделяемые каждому процессу, на столько малы, что у пользователя создается иллюзия одновременного выполнения многих процессов. Для организации пе- реключения между процессами по истечении кванта времени, выполняется фиксация и сохранение в памяти состояния программы. Этот снимок содержит информацию о состоя- нии регистров центрального процессора на момент прерывания программы, указание на то, с какой команды возобновить исполнение программы (состояние счетчика команд), содержимое стека и подобные данные. Когда процесс снова получает в свое распоряжение ЦП, состояние регистров ЦП и стека восстанавливается из сделанного снимка и выполне- ние программы возобновляется в точности с того места, где она была остановлена. Такие же действия выполняются в тех случаях, когда какому-то процессу необходимо вызвать некоторую системную функцию (вызов ядра)[1].Кроме организации переключения процессов, ядро в многозадачной системе отвечает за изоляцию процессов – два процесса не должны одновременно изменять какие-то данные одном участке памяти. Для этого каждому процессу выделяется свое виртуальное ад- ресное пространство. Его размер может даже превышать размер реальной оперативной памяти, что обеспечивается за счет применения страничной организации памяти и ме- ханизма свопинга. И физическая и виртуальная память организована в виде страниц – областей памяти фиксированного размера (обычно 4 Кбайта). Если страница долго не используется, ее содержимое переносится в область свопинга на жестком диске, а страница в оперативной памяти предоставляется в распоряжение другого процесса. Подсистема управления памятью поддерживает таблицу соответствия между страницами виртуальной памяти процессов и страницами физической памяти (включая страницы, перенесенные в область свопинга). В современных компьютерных системах эти механизмы реализуются на аппаратном уровне с помощью устройств управления памятью – Memory Management Unit (MMU). Если процесс обращается к странице виртуальной памяти, которая размещается в оперативной памяти, операция чтения или записи осуществляется немедленно. Если же страница в оперативной памяти отсутствует, генерируется аппаратное прерывание, в ответ на которое подсистема управления памятью определяет положение сохраненного содержимого страницы в области свопинга, считывает страницу в оперативную память,
корректирует таблицу отображения виртуальных адресов в физические, и сообщает про- цессу о необходимости повторить операцию. Все эти действия невидимы для приложения, которое работает с виртуальной памятью. При этом один процесс не может прочитать что-либо из памяти (или записать в нее) другого процесса без «разрешения» на то со стороны подсистемы управления памятью. При такой организации работы крах одного процесса никак не повлияет на другие выполняющиеся процессы и на всю систему в целом.Среди всех процессов можно выделить несколько особых типов процессов.
Системные процессы являются частью ядра и всегда находятся в оперативной памяти. Такие процессы не имеют соответствующих им программ в виде исполняемых файлов и запускаются особым образом при инициализации ядра системы. Примерами системных процессов являются планировщик процессов, диспетчер свопинга, диспетчер буферного кэша, диспетчер памяти ядра. Такие процессы являются фактически потоками ядра.Демоны отличаются от обычных процессов только тем, что они работают в интерактивном режиме. Если с обычным процессом всегда ассоциирован какой-то терминал или псевдо терминал, через который осуществляется взаимодействие процесса с пользователем, то де- мон такого терминала не имеет. Демоны обычно используются для выполнения сервисных функций, обслуживания запросов от других процессов, причем не обязательно выпол- няющихся на данном компьютере. Пользователь не может непосредственно управлять демонами, он может влиять на их работу, только посылая им какие-то задания, например, отправляя документ на печать.Главным демоном в системе является демон init[2]. Он является прародителем всех про- цессов в системе и имеет идентификатор 1. Выполнив задачи, поставленные в ему в файле inittab, демон init не завершает свою работу – он постоянно находится в памяти и отслеживает выполнение других процессов.Прикладные процессы – это все остальные процессы, выполняющиеся в системе. Как правило, эти процессы порождаются в рамках сеанса работы пользователя. В каждом таком сеансе работы вначале запускается оболочка (командный интерпретатор) shell. Этот экземпляр оболочки называется login shell и завершение соответствующего процесса приводит к отключению пользователя от системы.
Создание демона Linux
Для задачи демонизации будем использовать программу из предыдущей лабораторной работы. Она будет отслеживать состояние сетевого интерфейса и записывать результаты своей работы в системный журнал. Код демона представлен в листинге 1.
Листинг 1: Исходный код демона Linux (src/daemons/lin/main.cpp)1 #i nc l ude <iostream>2 #i nc l ude <fstream>3 #i nc l ude <s tri ng >4 #i nc l ude <regex>
5
6 #i nc l ude <uni s td . h>7 #i nc l ude <sys / types . h>8 #i nc l ude <sys / s ta t . h>
9
10 #i nc l ude <s y s l o g . h>11 #i nc l ude <s i g n a l . h>12 #i nc l ude <stdarg . h>
13
14 bool parse ( char * ifname , long long * rx_bytes , long long * rx_packets ,15 long long * tx_bytes , long long * tx_packets ) ;
16
17 i n t main ( i n t argc , char * argv [ ] ) {18 openlog ( " netmonitor " , LOG_PID | LOG_NDELAY | LOG_PERROR, LOG_DAEMON) ;19 i f ( argc < 2 ) {20 s y s l o g (LOG_ERR, " Usage : %s interface_name " , argv [ 0 ] ) ;21 re turn 1 ;22 }
23
24 i n t pid = f o rk ( ) ;25 switch ( pid ) {26 case 0 :27 umask ( 0 ) ;28 s e t s i d ( ) ;29 c hdi r ( "/" ) ;30 c l o s e (STDIN_FILENO) ;31 c l o s e (STDOUT_FILENO) ;32 c l o s e (STDERR_FILENO) ;
33
34 {35 long long rx_bytes = 0 ;
_bytes , &rx_packets , &tx_bytes , &
t f i n d such i n t e r f a c e : %s " , argv
e %l l d bytes (% l l d packets ) \n\ l l d "packets ) " ,ytes , rx_packets , tx_bytes ,;
ble to f o rk " ) ;
on with pid %d i s c re ate d \n" , pid ) ;
g * rx_bytes , long long * rx_packets ,
69 long long * tx_bytes , long long * tx_packets ) {70 std : : s t r i n g i n t e r f a c e ( i fname ) ;71 i n t e r f a c e . append ( " : " ) ;72 std : : s t r i n g buf f ;73 std : : i f s tre a m n e ts ta t ( "/ proc / net/ dev" ) ;
74
75 while ( std : : g e t l i n e ( ne ts tat , buf f ) ) {76 s i z e _ t s h i f t = buf f . f ind_ f i rst_ not_ of ( ’ ’ ) ;77 i f ( buf f . compare ( s h i f t , i n t e r f a c e . l e ng th ( ) , i n t e r f a c e ) == 0 ) {78 std : : regex rx (R" ( [ ^ [ : alpha : ] ] [ [ : d i g i t : ] ] + [ ^ [ : alpha : ] ] ) " ) ;79 std : : s re g e x _ i te ra to r pos ( buf f . cbegin ( ) , buf f . cend ( ) , rx ) ;
80
81 * rx_bytes = std : : s t o l l ( pos−>s t r ( ) ) ;82 ++pos ;83 * rx_packets = std : : s t o l l ( pos−>s t r ( ) ) ;84 std : : advance ( pos , 7 ) ;85 * tx_bytes = std : : s t o l l ( pos−>s t r ( ) ) ;86 ++pos ;87 * tx_packets = std : : s t o l l ( pos−>s t r ( ) ) ;
88
89 re turn true ;90 }91 }92 re turn f a l s e ;93 }
Логика работы самого приложения не изменилась, изменился только способ запуска. После проверки аргументов (стр. 19), приложение выполняет операцию fork() (стр. 24), после чего "родительская"часть спокойно завершает свою работу (стр. 59), а "дочернее"выполняет ряд операций, характерных для демона.Для начала в процессе потомка нужно разрешить выставлять все биты прав на создаваемые файлы, это избавляет от проблемы с правами доступа (стр. 27). Потом создаётся новый сеанс, чтобы не зависеть от родителя (стр. 28). Далее осуществляется переход в корень диска, если этого не сделать, то могут быть проблемы, к примеру с размонтированием дисков (стр. 29). И в конце происходит закрытие дескрипторов ввода/вывода/ошибок, так как демону они не понадобятся (стр. 30-32).
После запуска демона, убедиться в его работоспособности можно так
enp2s0
Работа с системным журналом
Функция системного журналирования (т.н. "логи"или логирование) – это основной источ- ник информации о работе системы и ошибках. Журналирование может осуществляться на локальной системе, а так же сообщения журналирования могут пересылаться на удален- ную систему. Журналирование осуществляется при помощи демона syslogd или rsyslogd. Журнал обычно получает входную информацию при помощи сокета /dev/log (локально) или с udp-порта 514 (с удаленных машин)[3].Соединение с журналом было установлено в строке 18. Первый параметр сообщил систем- ному журналу имя приложения, которое будет использоваться при ведении записей, а два оставшихся поля состоят из флагов флагов[2].Предпоследнее поле (option) принимает дизъюнкцию следующих значений:
LOG_CONS написать сообщение об ошибке прямо на консоли, если была ошибка при записи данных в системный журнал;LOG_NDELAY устанавливать соединение немедленно (обычно оно устанавливается только при поступлении первого сообщения);LOG_NOWAIT не ожидает дочерние процессы которые могут быть созданы во время отправки этого сообщенияLOG_ODELAYобратно от LOG_NDELAY; открытие соединения откладывается до вызова syslog().LOG_PERROR посылать сообщение еще и в поток stderr;LOG_PID добавлять к каждому сообщению идентификаторПоследнее поле (facility) используется для указания типа программы, записывающей сообщения и принимает дизъюнкцию следующих значений:LOG_AUTH сообщения о безопасности/авторизации (РЕКОМЕНДУЕТСЯ исполь- зовать вместо него LOG_AUTHPRIV).LOG_AUTHPRIV сообщения о безопасности/авторизации (частные);
LOG_CRON демон часов (cron и at);LOG_DAEMON другие системные демоны;LOG_KERN сообщения ядра;LOG_LOCAL0 до LOG_LOCAL7 зарезервированы для определения пользова- телем;LOG_LOG_LPR подсистема принтера;LOG_MAIL почтовая подсистема;LOG_NEWS подсистема новостей USENET;LOG_SYSLOG сообщения, генерируемые syslogd;LOG_USER (по умолчанию) – общие сообщения на уровне пользователя;LOG_UUCP – подсистема UUCPПри записи сообщения, можно указать его тип (критичность) для последующей фильтрации (показывать сообщения не ниже определённого уровня). Это используется в строках 20, 42, 46, 56, 60.Уровень важности сообщения по понижению:
LOG_EMERG система остановлена;LOG_ALERT требуется немедленное вмешательство;LOG_CRIT критические условия;LOG_ERR ошибки;LOG_WARNING предупреждения;LOG_NOTICE важные рабочие условия;LOG_INFO информационные сообщения;LOG_DEBUG сообщения об отладке.В строке 64 соединение с системным логом закрывается.
Записи системного лога попадают в файл /var/log/syslog. В листинге 2 показан вывод (без форматирования) некоторых (10 последних) строк этого файла. Важно отметить, что когда системный журнал получает повторяющиеся события (т.е. состояние счётчиков на сетевой карте не успело измениться), он делает пометку о повторе, вместо прямого дублирования.
Листинг 2: Системный журнал Linux1 Apr 23 2 1 : 2 8 : 2 9 spb netmonitor [ 5 7 7 6 ] : message repeated 3043 times : [ enp2 s 0 :#012#011 Receive 1535932378 bytes ( 1111392 packets )#012#011 Transmit 202177932 bytes ( 700394 packets ) ]2 Apr 23 2 1 : 2 8 : 2 9 spb netmonitor [ 5 7 7 6 ] : enp2 s 0 :#012#011 Receive1535932378 bytes ( 1111392 packets )#012#011 Transmit 202178497 bytes ( 700395 packets )3 Apr 23 2 1 : 2 8 : 2 9 spb netmonitor [ 5 7 7 6 ] : message repeated 25 times : [ enp2 s 0 :#012#011 Receive 1535932378 bytes ( 1111392 packets )#012#011 Transmit 202178497 bytes ( 700395 packets ) ]4 Apr 23 2 1 : 2 8 : 2 9 spb netmonitor [ 5 7 7 6 ] : enp2 s 0 :#012#011 Receive1535932444 bytes ( 1111393 packets )#012#011 Transmit 202178497 bytes ( 700395 packets )5 Apr 23 2 1 : 2 8 : 2 9 spb netmonitor [ 5 7 7 6 ] : message repeated 126 times : [ enp2 s 0 :#012#011 Receive 1535932444 bytes ( 1111393 packets )#012#011 Transmit 202178497 bytes ( 700395 packets ) ]6 Apr 23 2 1 : 2 8 : 2 9 spb netmonitor [ 5 7 7 6 ] : enp2 s 0 :#012#011 Receive1535932738 bytes ( 1111394 packets )#012#011 Transmit 202178497 bytes ( 700395 packets )7 Apr 23 2 1 : 2 8 : 2 9 spb netmonitor [ 5 7 7 6 ] : message repeated 12 times : [ enp2 s 0 :#012#011 Receive 1535932738 bytes ( 1111394 packets )#012#011 Transmit 202178497 bytes ( 700395 packets ) ]8 Apr 23 2 1 : 2 8 : 2 9 spb netmonitor [ 5 7 7 6 ] : enp2 s 0 :#012#011 Receive1535932738 bytes ( 1111394 packets )#012#011 Transmit 202178563 bytes ( 700396 packets )9 Apr 23 2 1 : 2 8 : 2 9 spb netmonitor [ 5 7 7 6 ] : message repeated 12 times : [ enp2 s 0 :#012#011 Receive 1535932738 bytes ( 1111394 packets )#012#011 Transmit 202178563 bytes ( 700396 packets ) ]10 Apr 23 2 1 : 2 8 : 2 9 spb netmonitor [ 5 7 7 6 ] : enp2 s 0 :#012#011 Receive1535933590 bytes ( 1111395 packets )#012#011 Transmit 202178629 bytes ( 700397 packets )
Дистрибуция пакетов в Linux
Программное обеспечение в ОС Ubuntu Linux распространяется в так называемых deb- пакетах. Обычно при установке программы из репозитория система автоматически ска- чивает и устанавливает deb-пакеты. Главной причиной использовать этот путь является автоматическое разрешение зависимостей. Программу можно установить, только если уже установлены пакеты, от которых она зависит. Такая схема позволяет избежать дублиро- вания данных в пакетах (например, если несколько программ зависят от одной и той же библиотеки, то не придётся пихать эту библиотеку в пакет каждой программы – она поста- вится один раз отдельным пакетом). В отличие от, например, Slackware или Windows, в Ubuntu зависимости разрешаются пакетным менеджером (Synaptic, apt, Центр приложений, apt-get, aptitude) – он автоматически установит зависимости из репозитория. Зависимости придётся устанавливать вручную, если нужный репозиторий не подключен, недоступен, ес- ли нужного пакета нет в репозитории, если вы ставите пакеты без использования пакетного менеджера (используете Gdebi или dpkg), если вы устанавливаете программу не из пакета (компилируете из исходников, запускаете установочный run/sh скрипт). Операционные системы на базе Debian распространяют пакеты deb, на базе RedHat – rpm.
Создание DEB/RPM/TGZ пакетов
CheckInstall – это удобная утилита, позволяющая создавать бинарные пакеты для Linux из исходного кода приложения. После компиляции программного обеспечения checkinstall может автоматически сгенерировать Slackware-, RPM- или Debian-совместимый пакет, который впоследствии может быть полностью удалён через соответствующий менеджер пакетов. Эта возможность является предпочтительной при установке любых пакетов[4].
Установка пакета checkinstall не должна вызвать особых сложностей. В операционных системах, использующих DEB пакеты, установка производится командой:
В операционной системе, использующей RPM пакеты, установка пакета checkinstall выпол- няется командой:
Если такой пакет в Вашей ОС не обнаружен, то следует посетить домашнюю страницу проекта и скачать требуемую версию для Вашего дистрибутива:
Далее следует перейти в каталог с программой и провести её компиляцию.
Программа, которая была рассмотрена в предыдущем разделе может быть собрана следу- ющим образом.
Программа checkinstall создает и устанавливает пакет для основных ОС. Тип пакета (DEB или RPM) checkinstall определяет сам. Для жесткого указания типа создаваемого пакета используем команду checkinstall с ключами:Создает и устанавливает RPM пакет
Создает и устанавливает DEB пакет
Создает и устанавливает TGZ пакет (дистрибутивы: Slackware, Zenwalk, DeepStyle, Vektorlinux, Mops)
Далее следует ответить на несколько вопросов. По умолчанию все ответы на задаваемые вопросы подходят в большинстве случаев, поэтому везде нажимаем Enter.
Создание PKGBUILD
Пользовательский репозиторий Arch Linux (Arch User Repository, AUR) – это поддер- живаемое сообществом хранилище ПО для пользователей Arch. Он содержит описания пакетов (файлы PKGBUILD), которые позволят скомпилировать пакет из исходников с помощью makepkg и затем установить его, используя pacman. В AUR пользователи могут добавлять свои собственные сборки пакетов (PKGBUILD и другие необходимые файлы). Сообществу предоставлена возможность голосовать за эти пакеты или против них. Если пакет становится популярным, распространяется под подходящей лицензией и может быть
собран без дополнительных сложностей, то, вероятно, он будет перенесен в репозиторий community (непосредственно доступный при помощи утилит pacman и abs)[4].Файл PKGBUILD по сути напоминает Makefile, и требует установки значений следующих переменных в зависимости от пакета:pkgname – название пакета. Можно использовать только строчные английские буквы. Значение этой переменной большой роли не играет, но может помочь, если установить сюда имя рабочей директории, или, например, имя файла с исходным кодом (*.tar.gz), который требуется загрузитьpkgver – версия пакета. Эта переменная может содержать буквы, цифры, знаки препинания, но не может содержать дефисов. Содержимое этой переменной зависит от метода присвоения версий (major.minor.bugfix, major.date, и т.д.) который исполь- зует программа. Чтобы следующие шаги были наиболее эффективными и лёгкими, рекомендуется включить номер версии в имя файла с исходным кодом.pkgrel – число, которое нужно увеличивать каждый раз после новой сборки пакета. При первой сборке пакета значение pkgrel должно быть установлено в "1". Цель этой переменной состоит в том, чтобы различать разные сборки пакета одной и той же версии.pkgdesc – краткое описание пакета, обычно не более 76 символов.arch – список архитектур, где может быть использован данный PKGBUILD (обычно это "i686").url – адрес веб-сайта программы, где заинтересовавшиеся могут получить более подробную информацию о программе.license – тип лицензии (может быть ’unknown’).depends – список пакетов, разделенный пробелами, которые должны быть установлены до использования пакета. Во избежании проблем, имена пакетов заключаются в апострофы (’), а весь массив в скобки. Используя математическое "больше или равно можно указать минимальную допустимую версию пакета-зависимости.makedepends – список пакетов, которые потребуются для сборки пакета, но которые не нужны для его использования.provides – список пакетов, необходимость в которых пропадает, так как собираемый пакет выполняет, по крайней мере, похожие функции.conflicts – список пакетов, которые, если установлены, могут создать проблемы во время использования собираемого пакета.
replaces – список пакетов, которые заменит собираемый пакет.source – список файлов, которые потребуются во время сборки пакета. Здесь должна быть ссылка на архив с исходным кодом программы (в большинстве случаев такая ссылка представляет из себя HTTP или FTP ссылку, заключённую в кавычки).md5sums – список контрольных сумм для файлов из предыдущей переменной, разде- ленных пробелами и заключённых в апострофы. Как только станут доступны все файлы из списка source, md5 суммы файлов будут автоматически сгенерированы и проверены на соответствие с этим списком.
Фоновые приложения в Windows
Службы Windows
Служба (сервис от англ. service) - это программы, которые автоматически запускаются системой при загрузке Windows и выполняются в любом случае, вне зависимости от действий пользователя.В большинстве случаев службам запрещено взаимодействие с консолью или рабочим столом пользователей (как локальных, так и удалённых), однако для некоторых сервисов возможно исключение — взаимодействие с консолью (сессией с номером 0, в которой зарегистрирован пользователь локально или при запуске службы mstsc с ключом /console).Существует четыре режима для сервисов:
запрещён к запуску;ручной запуск (по запросу);автоматический запуск при загрузке компьютера;обязательный сервис (автоматический запуск и невозможность (для пользователя) остановить сервис).Windows предлагает программу Service Control Manager, с её помощью можно управлять созданием, удалением, запуском и остановкой служб. Приложение, имеющее статус сервиса, должно быть написано таким образом, чтобы оно могло принимать сообщения от Service Control Manager. Затем, одним или несколькими вызовами API, имя службы и другие атрибуты, такие, как его описание, регистрируются в Service Control Manager.Список служб находится в ветке реестра HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\S Значения параметра «Start» имеют тип «REG_DWORD» и могут принимать значения:«0», «1», «2», «3» и «4» (когда служба не запускается, то есть запуск данной службы запрещен)[5].Сервисы Windows по умолчанию запускаются от имени пользователя «LocalSystem», кото- рый обладает полными правами в системе (превосходящими права даже учётной записи Administrator). Рабочим каталогом будет системный каталог Windows (обычно C:\WINNT или C:\WINDOWS), а каталог для хранения временных файлов будет C:\WINNT\TEMP.Поскольку это не настоящий пользователь, а «виртуальный», появляются некоторые трудности, когда приложению необходимо сохранить данные, относящиеся к пользователю (user-specific data), поскольку не существует папки этого пользователя.
Важно также то, что в случае если служба работает от имени локального пользователя (реальный пользователь созданный для служебных целей) если пароль такого пользователя изменён, сервис не будет запускаться до тех пор, пока пароль для сервиса тоже не будет изменен.
Создание службы Windows с помощью программы Sc.exe
Этот способ является рекомендованным корпорацией Microsoft[6].
Для создания служб Windows можно использовать программу Sc.exe, включенную в пакет ресурсов Resource Kit, которая реализует вызовы ко всем функциям интерфейса приклад- ного программирования (API) управления службами Windows. Настроить параметры для этих функций можно, задав их в командной строке. С помощью средства Sc.exe имеется возможность запросить состояние службы и получить значения, хранящиеся в полях струк- туры