О. С. Попова Хіхловська І. В. Системне та прикладне програмне забезпечення у телекомунікаціях Конспект

Вид материалаКонспект
Прикладные процессы
Атрибуты процессов
Идентификатор родительского процесса (PPID)
Реальный (RID) и эффективный (EUID) идентификаторы
Реальный (RGID) и эффективный (EGID) идентификаторы группы
Жизненный путь процесса
Взаимодействие между процессами
Организация каналов
Взаимодействие между процессами
Совместное использование данных.
Недостатком каналов
Подобный материал:
1   2   3   4   5   6   7   8   9   ...   14

Прикладные процессы


К прикладным процессам относятся все остальные процессы, выполняющиеся в системе, как правило, порожденные в рамках пользовательского сеанса работы. Например, запуск команды ls(1) породит прикладной процесс просмотра файлов, процессов, которые выполняются. Основной командный интерпретатор ( login sheel ), обеспечивает работу в UNIX, он запускается сразу после регистрации в системе, а после завершения работы отключается от системы. Пользовательские процессы могут выполняться как в интерактивном, так и фоновом режимах, но время их жизни ограничено сеансом пользователя. Интерактивные процессы монопольно владеют терминалом, пока такой процесс не завершит свое выполнение, например, ps(1). В то же время интерпретатор sheel считывает пользовательский ввод и запускает задачи.

Атрибуты процессов



Каждый процесс имеет уникальный идентификатор PID, позволяющий ядру системы различать процессы. Когда создается новый процесс, ядро присваивает ему следующий свободный идентификатор по нарастающей до максимально возможного. Когда процесс завершает свою работу, ядро освобождает занятый им идентификатор, (0…65535)=216.


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

Parent Process ID


Идентификатор процесса, породившего данный процесс.


Приоритет процесса ( Nice Number)


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


Реальный (RID) и эффективный (EUID) идентификаторы

пользователя


Реальный идентификатором пользователя данного процесса является идентификатор пользователя, запустившего процесс. Эффективный идентификатор служит для определения прав доступа процесса к системным ресурсам, в первую очередь к ресурсам файловой системы. Обычно RID и EUID эквивалентны, т.е. процесс имеет в системе те же права, что и пользователь, запустивший его. Существует возможность задать процессу более широкие права, чем права пользователя путем установки флаги SUID, когда эффективному идентификатору присваивается значение идентификатора владельца исполняемого файла.


Реальный (RGID) и эффективный (EGID) идентификаторы группы


RGID равен идентификатору первичной ил текущей группы пользователя, запустившего процесс. EGID служит для определения прав доступа к системным ресурсам по классу доступа группы. Возможна установка EGID равным идентификатору группы владельца исполняемого файла ( флаг SGID).

Жизненный путь процесса



Процесс в UNIX создается системным вызовом fork(2). Процесс, сделавший вызов fork(2), называется родительским, а вновь созданный процесс – дочерним. Новый процесс имеет те же инструкции и данные, что и его родитель. Выполнение родительского и дочернего процесса начнется с одной и той же инструкции, следующей за вызовом fork(2). Отличаются они только PID.Для запуска новой программы процесс должен выполнить системный вызов exec(2). При этом новый процесс не порождается, а исполняемый код дочернего процесса полностью замещается кодом запускаемой программы. Окружение же новой программы во многом сохраняется, в частности сохраняются значения переменных окружения, назначения стандартных потоков ввода/вывода, вывода сообщений об ошибках и приоритет процесса. Запуск на выполнение новой программы часто связан с порождением нового процесса, таким образом, сначала процесс выполняет вызов fork(2), порождая дочерний процесс, который затем выполняет exec(2), полностью замещаясь новой программой. Пусть пользователь, работая в командном интерпретаторе shell, запускает ls(1). Текущий процесс (shell) делает вызов fork(2), порождая вторую копию shell. Порожденный shell вызывает exec(2), указывая в качестве параметра имя исполняемого файла, образ которого необходимо загрузить в память вместо кода shell. Код ls(1) размещает код порожденного shell, и утилита ls(1) начинает выполняться. По завершении работы ls(1) созданный процесс “умирает”. Пользователь вновь возвращается в командный режим




$ ps(1) –ef / head –20

UID PID PPID C CMD

1 user 1 745 1 10 sh пользователь работает в командном режиме

2 user 1 745 1 10 sh

3 user 1 802 745 14 sh

4 user 1 745 1 10 sh

5 user 1 802 745 12 ls

6 user 1 745 1 10 sh


Процедура запуска новой программы называется fork-and-exec. Бывают ситуации, когда достаточно одного вызова fork(2) без последующего exec(2). В этом случае исполняемый код родительского процесса должен содержать логическое ветвление для родительского и дочернего процессов. Прародителем всех процессов является процесс init(1M), который также называемый распределителем процессов. init(1M) – это демон, неинтерактивная программа обеспечивающая доступ по сети, печать, электронная почта, возможность терминального входа.

Сигналы



Сигналы являются способом передачи от одного процесса к другому или от ядра ОС к процессу уведомления о возникновении определенного события. Сигналы рассматриваются как простейшая форма межпроцессорного взаимодействия. Сигналы похожи на программные прерывания, когда нормальное выполнение процесса прерывается. Например, если процесс производит деление на 0, ядро посылает ему сигнал SIGFPE; при нажатии клавиш прерывания - или +,текущему процессу посылается сигнал SIGINT.

Для отправления сигнала служит команда kill(1):

kill sig_no pid,

Где sig_no – номер или символическое название сигнала, а pid – идентификатор процесса, которому посылается сигнал. Администратор системы может посылать сигналы любым процессам, обычный же пользователь может посылать сигналы только процесса, владельцем которых он является. PID и EUID процесса, посылающего сигнал, должны совпадать с идентификатором пользователя. Например, процессу, который только что запустили в фоновом режиме, нужно послать сигнал завершения выполнения SIGTERM; для этого нужно:

$ long_program & Запуск программы в фоновом режиме

$ kill $! По умолчанию команда kill(1) посылает сигнал SIGTERM; переменная $! Содержит PID последнего процеса, запущенного в фоновом режиме

При получении сигнала процесс имеет три варианта действий для выбора:
  1. Он может игнорировать сигнал, но нельзя игнорировать сигналы, вызванные аппаратной частью, при делении на 0 или ссылки на недопустимые области памяти.
  2. Процесс может потребовать действия по умолчанию, это сводится к завершению выполнения процесса.
  3. Процесс может перехватить сигнал и самостоятельно обработать его, т.е. например, перехват сигнала SIGINT позволит процессу удалить созданные или временные файлы. Сигналы SIGKILL и SIGSTOP нельзя ни перехватить, ни игнорировать.

По умолчанию команда kill(1) посылает сигнал с номером 15 – SIGTERM – завершение выполнения процесса, получившего сигнал. Иногда процесс продолжает существовать и после отправления сигнала SIGTERM. В этом случае можно применить более жесткое средство – послать сигналу SIGKILL с номером (9), т.к. этот сигнал нельзя ни перехватить, ни игнорировать:

$kill – 9pid

Иногда процесс не исчезает и в этом случае:
  1. Процессы-зомби, т.е. процессы, от которых осталась лишь запись в системной таблице, удалить его можно только перезапуском ОС.В больших количествах они переполняют таблицы процессов.
  2. Процессы, ожидающие недоступные ресурсы NFS( Network File System), например, записывающие данные в файл файловой системы в ПК удаленного доступа, отключенного от сети.
  3. Процессы, ожидающие завершение операции с устройством.

Сигналы могут использоваться не только для завершения, но и для, например, считывания базы данных с сервера: SIGHUP посылается серверу DNS (named(1M)).


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


С одной стороны процессы изолированы друг от друга, находясь в разных адресных пространствах. С другой стороны, они должны взаимодействовать:
  1. Передавать данные
  2. Совместно использовать данные
  3. Извещать друг друга о наступлении какого-либо события

Механизмы взаимодействия сводятся к использованию:
  1. Сигналов
  2. Каналов,

например, Cat myfilewc оба процесса создаются shell

Стандартный вывод программы cat(1), которая выводит содержимое файла myfile, передается на стандартный ввод программы wc(1), которая подсчитывает количество строк, строк и символов. В результате получим

12 45 260

строк слов символов

Каналы могут использоваться для взаимодействия только родственных процессов.

Использовался программный канал, который обеспечил однонаправленную передачу данных между двумя процессами.
  1. FIFO – очень похож на каналы, но это именованный канал , как файл, например, программа “сервер”.


$mknod name p – создание FIFO из командной строки.

где p программма ls покажет в первой позиции.


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


Организация каналов


Для создания канала используются системный вызов pipe(2);

int pipe(int*fildes); или int pipe(int filedes[2]);

fildes – переменная, может быть filedes.

Системный вызов pipe(2) возвращает два файловых дескриптора: fildes[0] для записи в канал, fildes[1] – для чтения из канала. Если один процесс записывает данные в fildes[0], то другой процесс может получить эти данные из fildes[1]. Сложность в том, как второй процесс сможет получить сам файловый дескриптор fildes[1]. В случае неудачи возвращение – 1.

При создании процесса дочерний процесс наследует все назначенные файловые дескрипторы родительского процесса. Доступ к дескрипторам fildes канала может получить сам процесс, вызвавший pipe(2) и его дочерние процессы. После создания канала с ним можно работать с помощью системных вызовов read write.







Рис. Создане канала между задачами cat(1) и wc(1)


Если в канал записать три сообщения, то считываться они будут в том же порядке

Каналы создаются заново и после обращения к ним процесса уничтожаются.

Буферизация данных в канале стандартно осуществляется путем выделения дискового пространства в структуре файловой системы. Таким образом, запись и чтение связаны с дисковым вводом/ выводом, что сказывается на его производительности. Современные ОС (серверные) обеспечивают работу каналов через специальную файловую систему HPPS( High Performance Pipe System). С ее помощью данные буферизуются в ОЗУ, что ускоряет запись/ чтение.


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


В ОС UNIX процессы выполняются в собственном адресном пространстве и изолированы друг от друга. Это исключает ( сводит к минимуму) возможные влияния процессов друг на друга, что является необходимым в многозадачных ОС. Т.к. в то же время процессы должны взаимодействовать , то для реализации взаимодействия требуются:
  1. Обеспечение средств взаимодействия
  2. Исключить нежелательные влияния между ними

Взаимодействие между процессами необходимо для решения следующих задач:
  1. Передача данных. Один процесс передает данные другому процессу, при этом объем передаваемых данных должен варьироваться от десятков байтов до нескольких Мбайтов.
  2. Совместное использование данных. Вместо копирования данных от одного процесса к другому, они могут совместно использовать одну копию, причем изменения, сделанные одним процессом будут заметны для другого. Количество взаимодействующих процессов может больше двух. При совместном использовании ресурсов процессам может понадобиться протокол взаимодействия для сохранения целостности данных и исключения конфликтов между ними при доступе к данным.
  3. Извещения. Процесс может известить другой процесс или группу процессов о наступлении события. Это может понадобиться для синхронизации выполнения нескольких процессов (сигналы, похожие на прерывания).

Задача взаимодействия между процессами решается силами ОС. В UNIX это следующие средства:
  1. Сигналы
  2. Каналы
  3. FIFO – именованные каналы
  4. Сообщения (очереди сообщений)
  5. Семафоры
  6. Разделяемая память
  7. Сокеты



  1. Сигналы могут уведомлять об ошибках, для синхронизации процессов, для передачи простейших команд от одного процесса к другому, например, для сервера DNS named (1M) таким образом используется сигнал SIGHUP, являющийся сигналом обновления базы данных. Сигналы очень ресурсоемки. Отправка сигнала требует системного вызова, а доставка – прерывания процесса-получателя и операций со стеком ( работа с подпрограммой). Сигналы малоинформативны и их число ограничено.
  2. Каналы. На примере команды в командной строке shell рассмотрим синтаксис организации программных каналов:

cat myfile  wc

Стандартный вывод команды cat(1), которая выводит содержимое файла myfile, передается на стандартный ввод программы wc(1), которая подсчитывает количество строк,слов и символов. В результате получается:

12 45 260 –

количество строк, слов, символов в myfile

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

Для создания канала используется системный вызов pipe(2):


int pipe( int * fildes), иначе int pipe(int filedes[2]);


который возвращает два файловых дискриптора – fildes[0] для записи в канал и fildes[1] для чтения из канала( если неудача, вызов pipe вернет – 1). Теперь один процесс записывает данные в fildes[0], другой может получить эти данные из fildes[1]. Как получает файловый дескриптор fildes[1] другой процесс? При создании процесса наследующие атрибуты дочерний процесс наследует и разделяет все назначенные файловые дескрипторы процесса родительского. Доступ к дескрипторам filedes канала может получить сам процесс, вызвавший pipe(2), и его дочерние процессы. Серьезный недостаток каналов в том, что они могут быть использованы для передачи данных только между родственными процессами и не могут быть использованы для передачи данных между независимыми процессами. В приведенном примере оба процесса cat(1) и wc(1) создаются shell и поэтому являются родственными.

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

3. FIFO

Название каналов FIFO ( First In First Out, 1-м-вошел, 1-м-вышел). FIFO являются однонаправленными средствами передачи данных, причем чтение данных происходит в порядке их записи. FIFO имеют имена, которые позволяют взаимодействовать независимым процессам (именованные каналы).В BSD не используются. FIFO является типом файлов (ls-l покажет в первой позиции p). Для создания FIFO используется системный вызов mknod(2):

int mknod (char *pachname, int mode, int dev),

где pathname – имя файла в Ф.С.( имя FIFO),

mod – флаги владения прав доступа и тд.( поле mode).Например, 0666 –для всех права доступа на запись и чтение.

dev – при создании файла игнорируется.

FIFO может быть создан и из командной строки shell:

$ mkmode name p

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

Каналы FIFO и обычные каналы работают по следующим правилам:
  1. При чтении меньшего числа байтов, чем находятся в канале или FIFO, возвращается требуемое число байтов, остаток сохраняется для последующих чтений.
  2. При чтении большего числа байтов, чем есть, возвращается доступное число байтов, а процесс, читающий из канала, должен обработать ситуацию, если прочитано меньше, чем заказано.
  3. Если канал пуст и ни один процесс не открыл его на запись, при чтении из канала будет получено 0 байтов. Если канал открывали для записи, но не записали, то вызов read(2) будет заблокирован до появления данных, если в канале не установлен флаг отсутствия блокировки O_NDELAY.
  4. Запись числа байтов, меньшего емкости канала или FIFO, гарантировано атомарно. Это означает, что в случае записи в канал одновременно несколькими процессами, порции данных не перемешиваются.
  5. При записи большего числа байтов, чем это позволяет канал или FIFO, вызов write(2) блокируется до освобождения места. Атомарность при этом не гарантируется. Если процесс пытается записать данные в канал, не открытый ни одним процессом на чтение, процессу гарантируется сигнал SIGPIPE, а вызов write(2) возвращает 0 с установкой ошибки (errno=EPIPE), если процесс не установил обработки сигнала SIGPIPE, производится обработка по умолчанию – процесс завершается.