Перейти к содержанию

part5 - Processes and Runs


Рекомендуемые сообщения

Present: обновление от 5 мая 2009

ps - список запущенных процессов

top - своеобразный диспетчер задач

*** Раздел 5. Процессы и действия над ними ***

В этом разделе мы поговорим с вами о том, как работают процессы в UNIX-системе.

И какие sh-команды используются для слежения за процессами и выполнения различных действий над ним.

--- Глава 1. Требования к архитектуре компьютера со стороны операционной системы ---

Здесь мы поговорим об особенностях адресного пространства UNIX-процесса и какие требования для этого налагаются на архитектуру компьютера.

1. Изоляция адресных пространств процессов

У каждого процесса есть свое АП. Это значит, что его команды не могут читать / писать данные из другого процесса, или передать туда управление. Разумеется, ни одна нормальная программа не будет вторгаться в адресное пространство другого процесса. Но если бы такой защиты не было, тогда:

- Из-за ошибки в одном процессе он мог бы непредумышленно исказить адресное пространство другого процесса, и тем самым вызвать в нем другую ошибку. Таким образом, ошибка в одном процессе повалила бы все остальные!

- Успешно выполнялась нехорошая программа, алгоритм к-ой предусматривает влияние на АП другого процесса.

Благодаря этой защите все выполняющиеся машинные команды могут выполнять действия только в адресном пространстве своего процесса. Архитектура компьютера должна поддерживать такую возможность.

2. Плоская модель памяти

Кроме защиты процессов от непредумышленного доступа в результате ошибки нужно еще... защитить процесс от самого себя! Во всех программах есть следующие компоненты: КОД, ДАННЫЕ и СТЕК. Нужно сделать так, чтобы нельзя было:

1) передать управление на стек или на сегмент, содержащий данные

2) записать / прочитать данные оттуда, где находится код

Для этого была придумана модель сегментов - отдельных адресных пространств. В этой модели определенные команды работают только со "своим" сегментом. Н-р, команды передачи управления работают только с сегментом КОДА, команды обработки данных манипулируют данными в сегменте ДАННЫХ, а команды работы со стеком изменяют данные только в сегменте СТЕКА.

Все UNIX-системы используют плоскую модель памяти. Почему не сегментную? Все дело в кроссплатформенности. Сегментную модель памяти можно сделать плоской - наложив 4 сегмента одинакового размера друг на друга мы получим одно Адресное пространство. А вот плоскую модель сегментной сделать никак нельзя. Поэтому если бы UNIX использовала сегментную модель, система не смогла бы работать на тех архитектурах где поддерживается только плоская модель памяти. Плюс... платформ с поддержкой сегментной модели гораздо меньше, чем с плоской.

3. Страницы доступа

В плоском режиме КОД, ДАННЫЕ и СТЕК находятся в одном АП. Это означает, что команды процесса умышленно или в результате ошибки могут:

1) передать управление на стек или на данные

2) записать / прочитать данные оттуда, где находится код

Чтобы этого не произошло, используется страничная модель памяти. Областям АП процесса устанавливаются только те права доступа, которые необходимы:

- У кода должно быть право на выполнение.

- Данные бывают разные. Для констант и текстовых строк нужно только чтение. Для переменных и буферов - чтение и запись.

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

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

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

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

4. Ограничение привилегий процессов

Кроме изоляции адресных пространств нужно ограничивать привилегия процесса. Среди машинных команд есть обычные и привилегированные - которые влияют на само адресное пространство, виртуальную память и работу процессора. Операционная система (или процесс root'а) должна иметь возможность создавать новые процессы и манипулировать их памятью, используя эти привилегированные команды. А процессу обычного пользователя нужно разрешить выполнять только обычные команды, а манипулировать своей памятью и запускать процессы - руками операционной системы.

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

5. Выводы

Итак, UNIX будет работать только на тех архитектурах, процессор которых поддерживает:

1) Выполнение процессов в отдельных адресных пространствах

2) Плоскую модель памяти

3) Страницы доступа

4) Запрет на выполнения привелегированных команд для пользовательских процессов.

P.S.

С моделью памяти в истории UNIX связаны интересные события. Линус Торвальдс не мог бы создать ядро Linux по образу и подобию Unix System 5, если бы 386-процессор на его компьютере IBM XT на тот момент не поддерживал защищенный режим со страничной моделью. В процессе развития Linux новые ядра стали оптимизироваться для процессоров 586 и 686. По сравнению с 386-ми модели памяти в них немного изменились. Поэтому современный Линукс "наверное, вроде, как-бы, должен" работать на 386-процессорах. Хотя 386 и 486 процы сейчас почти нигде не встретишь, все еще остаются старые компы конца 90-х с 386-м. Будет очень жаль если вскоре из ядра 2.6 "наконец" исчезнет поддержка 386-ых.

Со стороны поддержки процессоров гораздо лучше выглядит FreeBSD. Эта система изначально предназначалась для 386-процессоров и его поддержка - главное условие её существования.

--- Глава 2. Характеристики процесса ---

Что такое процесс? Процесс - это адресное пространство, в котором выполняется программа. Именно так. Чтобы запустить программу, надо создать новый процесс и загрузить в него эту программу. Показатели процесса касаются именно процесса, а не выполняемой в нем программы. Так, например, время выполнения показывает - сколько машинного времени отнял у системы процесс, а не конкретно программа, которая в нем выполнялась! В этой главе мы поговорим о характеристиках процесса.

Изначально в UNIX не было поддержки потоков, они появилась потом. Помните об этом! Про потоки мы вспомним только в главе "Ну вот, появились потоки!". А пока будем считать что у каж. процесса есть только один поток выполнения.

PID (Process IDentificator)

Четное число от 1 до 32767.

Каждый запущенный процесс получает уникальный номер (PID). Нет 2-х процессов с одинаковым PID'ом. Процессы с маленькими значениями PID'ами - обычно являются системными. Н-р, программа инициализации (init) имеет PID = 1, процессы с PID'ами 2, 3, 4, ... - это системные драйверы, запущенные сразу после init.

UID (User IDentificator)

Это - идентификатор пользователя, с правами которого выполняется программа.

При обычном запуске программы она получает UID той учетной записи, который имеет родительский процесс. В результате программа получает те же права доступа к файлам, которые имеет запустивший ее пользователь. После запуска процесс уже не сможет изменить свой UID.

У root-программ (UID == 0) имеется право запустить программу от имени другого пользователя и тем самым установить ей другой UID.

GID (Group IDentificator)

Идентификатор группы процессов. Внимание! Этот аттрибут не связан с одноименным GID (группой пользователя), он используется совсем по-другому.

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

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

???

TID (Terminal IDentificator)

???

NICE

Это - уступчивость процесса (т. е. показатель, противополжный приоритету).

Если загрузка процессора меньше 100%, значит всем программам хватает процессорного времени и приоритет не играет роли. Если загрузка процессора РАВНА 100%, тогда процессы начинают бороться за машинное время. В первую очередь управление получают процессы с самым большим NICE, а процессы с высоким NICE получают его реже всего.

Еще раз - обратите внимание - приоритет играет роль только если загрузка процессоров равна 100%! Если она меньше 100%, значит управление получают все процессы.

Система позволяет создавать процессы с указанным приоритетом (по умолчанию NICE = 0):

- Пользователи могут создавать процессы, с NICE большим или или равным нулю.

- root может запускать процессы с любым NICE.

Также можно изменять приоритет уже имеющихся процессов:

- Юзеры могут изменять NICE только для своих процессов (со своим UID), при этом - его можно только увеличить.

- root может изменять NICE любого процесса в любую сторону.

PR

Начальный приоритет процесса.

???

Корневой каталог (rootdir)

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

Текущий каталог (curdir)

Все открываемые файлы, в качестве пути которых указано только имя, открываются в текущем каталоге. Функция chdir сменяет текущий каталог.

Маска создания файлов (umask)

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

Максимальный размер файла (ulimit)

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

PR - опять приоритет?

GID - ?

--- Глава 3. Показатели процесса ---

Здесь я опишу показатели, специфичные для процесса.

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

Может быть одним из следующих:

Sleeping

Процесс спит, то есть является неактивным и не занимает процессорное время, так как ожидает какое-то событие. А какое? Например:

- окончание ввода / вывода данных

- завершение дочернего процесса или чей-то сигнал

Сон - это основное состояние процесса, практически все процессы системы находятся в этом состоянии. Вы спросите - как это возможно, выходит что они совсем не работают? Нет, они работают. Машинные команды выполняются очень быстро - почти в мгновение ока. А вот ввод-вывод данных работает намного, намного медленнее! Для прочтения/записи данных с носителя нужно много времени - целые милисекунды. Пользователь не может быстро ввести данные - на это потребуется несколько секунд. А когда завершится дочерний процесс или поступит сигнал - вообще неизвестно!

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

Running

Процесс является активным и требует от процессора машинного времени.

Диспетчер процессов занимается распределением процессорного времени между активными процессами. Как он это делает? Диспетчер устанавливает максимальное время M, которое может занимать выполнение одного процесса (н-р 40 мс) - квант выполнения. Системный таймер генерирует аппаратное прерывание каждые N милисекунд (н-р, 10 мс). Это прерывание обрабатывает наш диспетчер, увеличивая счетчик времени на N, тем самым подсчитывая - сколько времени выполняется процесс. Если это время стало >= чем M, то диспетчер прерывает выполнение текущей программы и переключает процессор на выполнение следующей активной задачи.

Если выполняемый процесс перешел в неактивное состояние (или закончил свою работу), то диспетчер также переходит к выполнению следующего. Конечно, процессы, которые непрерывно выполняются целых 40 мс - большая редкость, в большинстве случаев процесс поработает 0,05-0,1 мс и перейдет в неактивное состояние (н-р, будет ждать от пользователя ввода данных). Если бы не было переключения процессов, то зависнувший процесс до бесконечности занимал процессор и не давал работать другим, что привело бы к остановке всей системы.

Stopping

Этот процесс остановлен - не по собственной воле (н-р, другой программой или операционной системой) переключен в неактивное состояние. Когда его включат обратно, он вернется в то состояние, в котором находился до остановки.

Zombie

Процесс был завершен, но родительский процесс пока об этом не узнал. Подробнее о зомби будет позже.

2. Время выполнения процесса

У каждого процесса есть 3 показателя времени выполнения:

time

Это общее время выполнения процесса, подсчитанное диспетчером процессов с помощью прерываний от системного таймера. Заметьте, что TIME - это не время, прошедшее с момента запуска процесса, а сколько программа процесса использовала машинного времени, выделенного диспетчером. Из этого времени:

system

сколько времени процесс провел в режиме ядра,

user

а сколько - в пользовательском режиме.

3. Общее время выполнения

А следующие 3 показателя рассчитываются для всей системы в целом:

idle

Это неиспользуемое машинное время.

Уже было сказано, что диспетчер выделяет каждому процессу квант выполнения. Чаще всего процесс использует его не полностью, так как очень скоро переходит в режим ожидания. Чтобы знать - как много из выделенного времени использовали процессы, в системе существует специальный idle-процесс с PID'ом, равным нулю. Этот процесс отрабатывает все время выполнения, которое остальные процессы не использовали. На время работы он останавливает процессор и тот "отдыхает".

P.S. Idle-процесс, на самом деле, не является процессом, так как не занимает оперативной памяти и его номер (ноль) не возвращается ни одним системным вызовом.

nice

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

cpu

Показатель загруженности микропроцессоров (в процентах).

Это часть времени, в течении которого работают микропроцессоры компьютера.

--- Глава 4. Показатели программы ---

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

1. Занимаемая память

Память процесса состоит из Занимаемой и Разделяемой памяти. Занимаемая память

Каждому процессу принадлежат страницы памяти, к-е занимают определенный размер в системе. Это и есть занимаемая память, она делится на 2 группы, в зависимости от того, где эта память находится:

- Резидентная

Это та память, которая находится в физической оперативной памяти компьютера. Страницы памяти, к-е находятся в ОЗУ, называются активными. Тем самым, размер резидентной памяти определяется по размеру всех активных страниц процесса.

- Выгруженная

А это - та память, к-я была выгружена из оперативной памяти на внешнее устройство. Страницы памяти процесса, к-е НЕ находятся в ОЗУ, называются выгруженными. Где находятся эти страницы - должна помнить операционная система (чаще всего в разделе подкачки, swap). Если команда процесса обратилась к выгруженной странице, то ОСь загружает эту страницу в ОЗУ с раздела подкачки.

Размер выгр-ой памяти процесса определяется по размеру всех его выгруженных страниц.

2. Разделяемая память

В файле программы могут быть страницы, которые имеют аттрибут "shared" (разделяемые). После загрузки программы эти страницы любой другой процесс по своему желанию может спроецировать на свое адресное пространство с теми же правами доступа. Это и есть разделяемая память (та, к-я была спроецирована из АП другого процесса).

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

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

А вот в Windows-системах в АП процесса загружаются все требуемые им библиотеки. Это транжирит память, так как в ОП теперь будет находится несколько копий одной и той же библиотеки.

НЕЗНАЮ! Может возникнуть проблема конфликта из-за обращения 2-х процессов к библиотеке.

3. Дескрипторы открытых файлов

Каждый открытый программой файл получает свой уникальный номер - дескриптор. При старте нового процесса система открывает для него 3 файла. При открытии нового файла создаваемый дескриптор получает первый незанятый номер, считая с нуля. Поэтому эти 3 файла получают номера 0, 1 и 2:

0) Стандартный ввод (stdin), из которого программа читает исходные данные. Обычно этим файлом является клавиатура.

1) Стандартный вывод (stdout). В него программа записывает выходные данные. Обычно это файл консоли.

2) и Стандартный поток ошибок (stderr), в который записываются сообщения об ошибках. Чаще всего это тоже консоль.

Эти файлы определяет родительский процесс. Н-р, если в sh вы перенаправите вывод программы в другой файл, то оболочка в качестве stdout вместо консоли подставит указанный файл. Все файлы, открытые процессом, получают номера дескрипторов, справедливые только для данного процесса. Информация об открытых файлах занимает место в операционной системе и до

--- Глава 5. Передача опций запускаемой программе ---

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

1. Командная строка

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

Например, - в оболочке sh вы ввели следующую команду:

rm ~/file1 ~/disasm ~/obj

В результате sh запускает программу rm и передает ей введенную вами командную строку, без изменений. Перед тем, как передать командную строку программе, система проводит с ней некоторые манипуляции. Она рассматривает в ней слова, разделенные пробелами или табуляцией, как отдельные строки и переводит командную строку в массив указателей на эти строки. Командная строка должна быть не длиннее 5120 байтов. Если требуется включить пробел / табуляцию в одно из слов, то само слово следует заключить в одинарные или двойные кавычки.

Программа может получить содержимое командной строки несколькими способами:

- при вызове функции main она получает 2 параметра: первый - количество строк, а второй - адрес массива строк, получаенных из командной строки.

- использовать функцию getopt для разбора командной строки на ключи и опции. В этом случае 2 символа '--' рассматриваются как конец опций.

2. Переменные среды (или переменные окружения)

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

Запуская программу через exec, родитель может передать процессу нужные переменные среды. Они передаются в виде массива указателей на строки. Каждая строка является одной переменной среды и выглядит так:

Имя=Значение

В программе переменные среды доступны одним из след. образов:

- переданный массив строк доступен под именем envp.

- функция getenv возвращает значение указанной переменной, а putenv изменяет значение переменных (или создает их в случае отсутствия).

Для чего используются переменные среды?

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

PATH

Список путей, разделенных двоеточием, где программе следует искать файлы.

HOME

Домашний каталог пользователя.

TERM

Тип терминала на который направлены stdout и stderr. Эта информация необходима программам, которые могут использоваться специфические возможности терминала конкретного типа.

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

--- Глава 6. Как создаются процессы и как они умирают ---

1. Как процессы создаются

В Windows функция CreateProccess создает новый процесс из исполняемого файла и запускает его.

В UNIX создание процессов сделано довольно странно. Для создания дочернего процесса надо:

1) Сделать точную копию нашего процесса функцией fork

2) Процесс-Копия должен загрузить в себя нужную программу функцией exec.

Избыточность налицо! Представьте, что для создания новых файлов нам приходится копировать уже существующие и писать в них нужные данные. А в Windows функция CreateProccess создает новый "файл" с уже нужным содержимым! Вот такие пироги!

2. Дочерние процессы

При создании нового процесса он считается дочерним (child). А сам процесс по отношению к новому считается родительским (parent). У каждого процесса есть свой PPID - идентификатор процесса-родителя.

После смерти дочернего процесса его родителю посылается сигнал SIGCHLD. Родитель должен обработать этот сигнал:

- установить обработчик этого сигнала до создания дочернего процесса

- или уже после него сделать системный вызов wait, который будет ждать сигнал SIGCHLD.

У вызова wait есть небольшая особенность. Вызов exec, запускающий новый процесс, возвращает управление когда этот процесс уже будет работать и до вызова wait может пройти некоторое время. За это время новый процесс может уже завершиться и к моменту вызова wait окажется, что дочернего процесса уже нет, и функция вернет ошибку! Также родитель не получит сигнал SIGCHLD, когда он находится в остановленном состоянии или игнорирует сигнал SIGCHLD. Пока процесс остановлен, он не выполняет вызов wait и не может обрабатывать сигналы.

Поэтому каждый завершенный процесс переходит в состояние зомби (zombie). Этот процесс все еще числится в системе, но от него почти ничего не осталось. Зомби-процесс умрет окончательно когда его родитель получит сигнал SIGCHLD (установит обработчик, вызовет wait или разбудится). Если родительский процесс завершится раньше дочернего, то вместо него сигнал получит процесс с PID == 1 (init), который всегда обрабатывает сигнал SIGCHLD.

3. Как умирают процессы

Чтобы закончить собственное выполнение, процесс может:

- выполнить return из функции main;

- вызвать функцию exit;

В обоих случаях нужно указать положительное число - код завершения. Общепринято что 0 означает нормальное завершение работы, а положительное значение - ошибку. После завершения работы:

- закрываются все открытые файлы

- освобождается вся память процесса

Далее, процесс становится зомби, а код завершения возвращается родительскому процессу функцией wait или обработчиком сигнала SIGCHLD.

--- Глава 7. Сигналы ---

1. Сигналы

У программ есть возможность посылать и принимать сигналы от других процессов. Причем, пользователю разрешено посылать сигналы только своим процессам (с тем же UID), а root может посылать сигналы любым процессам. При получении сигнала программа также узнает PID какого-то.

Назначений у сигналов несколько:

- узнать об ошибке в собственной программе

Система посылает программе особый сигнал, если в ней возникла ошибка (нарушение доступа, деление на ноль и др.). Получив такой сигнал, программа может сохранить данные на диск перед смертью (т. е. напоминает SEH в Windows).

- сообщить процессу об завершении или изменении состояния его дочернего процесса

Когда изменяется состояние дочернего процесса (остановка, завершение), система сообщает об этом родителю.

- изменить состояние одного из дочерних процессов

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

Есть 3 способа обработки сигналов:

1) Ignore

Игнорировать сигнал. При получении сигнала выполнение процесса не прерывается.

2) Handle

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

3) Terminate

Завершить работу процесса с сбросом дампа (содержимого адресного пространства) на диск. Завершение выполняется аналогично exit(2).

Установка обработчика сигнала и способа его обработки выполняется вызовом signal. А посылка сигнала процессу с указанным PID'ом осуществляет вызов kill (он так назван потому что по умолчанию посылает сигнал SIGKILL).

2. Основные сигналы

Ниже я приведу описание основных сигналов, где PID - это идентификатор процесса, который получает обработчик сигнала вместе с самим сигналом. Названия всех сигналов начинаются с 'SIG'. Вот сигналы, которые система посылает процессу в случае возникновения в нем ошибки (тогда PID равен собственному, если нет - значит сигнал нам послала не система, а другой процесс). В скобках - значение сигнала:

SIGSYS (12) - Неправильный аргумент системного вызова.

SIGILL (04) - Неизвестная или привилегированная машинная команда (illegal instruction).

SIGFPE (08) - Ошибка при выполнении операции с вещественными числами, н-р деление на ноль или превышение допустимой погрешности.

SIGSEGV (11) - Нарушение доступа к странице, н-р, запись в ячейку памяти, к-ая доступна только для чтения или чтение из несуществующией страницы адресного пространства (access violantion).

SIGALRM (14) - На работу процесса родитель отвел определенное время. Так вот, это время закончилось, (alarm clock), поэтому система завершает процесс.

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

SIGHUP (01) - Разрыв связи (hangup). Главный процесс в группе закончил работу (PID), поэтому терминал (устройство ввода и вывода) закрывается и все остальные процессы в группе, работающие с этим терминалом, получают этот сигнал.

SIGQUIT (03) - Система экстренно завершила работу программы (quit).

SIGABRT (06) - Программа сама экстренно завершила работу вызовом функции abort().

SIGCLD (18) - Завершение дочернего процесса. Посылается его родителю.

SIGTRAP (05) - Шаг при трассировке программы. Получает родительский процесс (отладчик).

А вот - сигналы, которые родитель может послать дочернему процессу с целью изменить его состояние. Дочерний процесс в качестве PID получает номер своего родителя:

SIGTERM (15) - Программный сигнал завершения. Сказать дочернему процессу - "заверши свою работу по хорошему". Процесс-получатель может проделать какие-то действия до завершения работы. Это - рекомендуемый способ завершения дочерних процессов.

SIGKILL (09) - Убийство процесса (kill). Этот сигнал процесс не может обработать, так как на самом деле он посылается операционной системе с целью убить указанный процесс. Используйте только в последнем случае.

SIGSTOP (23) - Остановить выполнение процесса.

SIGCONT (25) - Продолжить выполнение остановленного процесса.

* Остановить ввод / вывод - ? (Ctrl+Z)

* Продолжить ввод / вывод - ? (Ctrl+Z)

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

--- Глава 8. Обмен данными и Взаимодействие между процессами ---

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

1. С помощью сигналов

Для общения между родственными процессами могут использоваться следующие сигналы (их можно посылать в обе стороны):

SIGUSR1 (16) - Пользовательский сигнал. Назначение определяется самой программой.

SIGUSR2 (17) - 2-ой пользовательский сигнал.

2. События

???

Эти 2 варианта пригодны только для синхронизации действий. Далее мы рассмотрим способы, которыми можно передавать данные.

3. Разделяемая память

Мы уже говорили про разделяемую память. Если в одной программе есть регион разделяемой памяти, то любой другой процесс может спроецировать этот регион на свое адресное пространство и читать / писать туда данные. А синхронизацию действий можно выполнить с помощью событий или сигналов следующим образом:

- процесс1 записал в регион данные и послал процессу2 сигнал SIGUSR1, что данные готовы

- процесс2 получает сигнал и читает данные из региона, затем посылает SIGUSR2 процессу1

- процесс1 получил SIGUSR2 и записал в регион очередную порцию данных

Недостаток метода в том, что этот регион разделяемой памяти может спроецировать ЛЮБОЙ процесс и писать в него данные.

4. Общие файлы

Неименованные и Именованные каналы

Сокеты

--- Глава 1. Ну вот, появились потоки! ---

Зачем они появились (SMP, обработка событий в Иксах)

Для поддержки потоков были выполнено много изменений в ядре

Потоки - непривычные для UNIX'оидов. Продырявили всю систему!

--- Глава 2. Работа с потоками ---

Поток - это клиент. А процесс - это сервер.

Поток - это особый процесс.

Показатели процесса:

PID

Показатели программы:

*** Раздел 5. Программы, связанные с темой процессов ***

(здесь остановился писать)

--- Программы, связанные с этой темой ---

ps - показать список своих процессов

top - консольный диспетчер задач

nice - запустить процесс с указ. приоритетом

renice - изменить приоритет уже запущенного

kill - послать сигнал процессу с указ. PID

killall - послать сигнал всем процессам с указ. именем

/proc - текущие процессы системы

манипулирование дочерними процессами в sh и bash (fg, bg, &, jobs)

В резидентную память входит:

CODE

Размер всех секций кода

DATA

Размер всех данных и стека.

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

Чтобы осуществить вход пользователя в систему, нужно запустить командную оболочку от имени его учетной записи. Запускать программы от имени другого пользователя может только root. В частности - программа login запускается с правами root и запускает командный интерпретатор от имени той учетной записи, чей логин вы введете. Созданный процесс получает UID этой учетной записи.

При обычном запуске программы она получает UID той учетной записи, который имеет родительский процесс. В результате программа получает привилегии своей учетной записи - она получает те же права доступа к файлам, которые имеет запустивший ее пользователь. После запуска процесс уже не сможет изменить свой UID.

*** Ну вот, появились потоки ***

Типы многопоточности:

- Естественная

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

Пример - Windows, NetBSD

- Искусственная

Каждый "поток" является копией адресного пространства процесса. Каждое АП имеет один поток выполнения.

Пример - Linux, FreeBSD

4. Чтение / запись в адресное пространство

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

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
×
×
  • Создать...