Сколько процессов может создать одна команда linux
Процесс — это абстракция, используемая для описания выполняющийся программы. Процесс представляет из себя системный объект, посредством которого можно контролировать обращение программы к памяти, центральному процессору и ресурсам ввода-вывода. В операционных системах Linux и Unix системные и пользовательские процессы подчиняются одним и тем же правилам, благодаря чему управление осуществляется с помощью единого набора команд.
Процесс состоит из адресного пространства и набора структур данных, содержащихся внутри ядра. Адресное пространство представляет собой совокупность страниц памяти, которые были выделены ядром для выполнения процесса. В него загружается код и используемые им библиотеки функций, а также переменные, содержимое стеков и различная вспомогательная информация, необходимая ядру для работы процесса. Поскольку в системах UNIX и Linux поддерживается концепция виртуальной памяти, страницы адресного пространства процесса в конкретный момент времени могут находится либо в физической памяти, либо в разделе подкачки, т.е. на диске.
В структуре данных ядра хранится всевозможная информация о каждом процессе. К наиболее важным относят:
- Таблицу распределения памяти
- Текущий статус (неактивен, приостановлен, выполняется и т.п.)
- Приоритет
- Информацию об используемых ресурсах
- Информацию о файлах и сетевых портах, открытых процессом
- Маску сигналов (запись о том, какие сигналы блокируются)
- Имя владельца процесса
Поток выполнения, обычно именуемой просто потоком, представляет результат разветвления в выполнении процесса. Поток наследует многие атрибуты своего процесса, причем в рамках одного процесса могут выполняться одновременно (параллельно) несколько потоков — такая модель выполнения получила название многопоточности. В старых однопроцессорных системах параллельное выполнение моделируется ядром, но в мультиядерных и многопроцессорных архитектурах потоки могут выполняться одновременно в различных ядрах. Такие многопоточные приложения, как BIND и Apache, извлекают максимальную пользу из мультиядерных систем, поскольку эти приложения могут обрабатывать несколько запросов одновременно.
Атрибуты процесса
Ядро назначает каждому процессу уникальный идентификатор PID. PID — Proccess ID. Большинство команд и системных вызовов, работающих с процессами, требуют указания конкретного идентификатора, чтобы был ясен контекст операции. Идентификаторы присваиваются по порядку по мере создания процессов.
Ни в UNIX, ни в Linux нет системного вызова, который бы инициировал новый процесс для выполнения конкретной программы. Для того, чтобы породить новый процесс, существующий процесс должен клонировать себя сам. Клон может заменить выполняемую программу другой.
В операции клонирования исходный процесс называют родительским, а его клон — дочерним. Помимо собственного идентификатора, каждый дочерний процесс имеет атрибут PPID (Parent Proccess ID), который совпадает с идентификатором породившего его дочернего процесса. Стоит отметить, что PPID — весьма полезная информация, если приходится иметь дело с неизвестными процессами. Отслеживание истоков процесса может облегчить понимание его назначения и значимости.
Когда система загружается, ядро самостоятельно запускает несколько процессов. Наиболее важный из них — демон init, идентификатор которого всегда равен 1. Демон init отвечает за выполнение сценариев запуска системы. Все процесса, кроме тех, что создаются ядром, являются потомками демона init.
UID (User ID) — это идентификатор пользователя, создавшего данный процесс. Менять атрибуты процесса могут только его создатель (владелец) и суперпользователь. EUID (Effective User ID) — это текущий пользовательский идентификатор процесса, предназначенный для того, чтобы определить, к каким ресурсам и файлам у процесса есть доступ в данный момент. У большинства программ значения UID и EUID одинаковы. Исключение составляют программы, у которых установлен бит смены идентификатора пользователя (setuid).
GID (Group ID) — это идентификатор группы, к которому принадлежит владелец процесса. Текущий идентификатор группы (EGID) связан с атрибутом GID так же, как и значение EUID связано с UID.
Приоритет процесса определяет, какую долю времени центрального процессора получает программа. Ядро применяет динамический алгоритм вычисления приоритетов, учитывающий сколько времени центрального процессора уже использовал процесс и сколько времени он ожидает в своей очереди.
Жизненный цикл процесса
Создание процесса — это переход процесса из состояния «Новый» в состояние «Готов». В момент создания процесса операционная система подготавливает структуру данных для него. Новому процессу присваивается собственный PID, и учет ресурсов ведется независимо от предка. Тот факт, что процесс существует — еще не дает ему права на использование ресурсов центрального процессора.
Готовый процесс получил все необходимые ресурсы и ждет, пока системный планировщик предоставит ему доступ к центральному процессору. При выделении доступа процесс запускается и переходит в активное состояние (выполняется).
Из состояния «Запущен» есть два пути:
- Таймаут — процесс поработал и освободил ресурсы процессора (перешел в очередь)
- Ожидание — процесс переведен в режим ожидания, где ждет некоего сигнала
Если процесс осуществил системной вызов, который нельзя завершить немедленно, то ядро переводит его в режим ожидания (сон). Ожидающий процесс ждет наступления определенного события, будь то поступление данных с терминала или из сетевого соединения. Многие системные демоны проводят в этом состоянии большую часть своего времени. Важно отметить, что в данном случае процесс будет продолжать храниться в оперативной памяти.
Некоторые операции переводят процесс в состояние непрерывного ожидания (приостановлен). В данном состоянии процесс ожидает определенного сигнала от аппаратной части и не реагирует на другие сигналы. При этом процесс выгружен из оперативной памяти на жесткий диск (swap-раздел). Для того, чтобы избавиться от такого процесса необходимо устранить породившую их проблему или перезагрузить систему.
После того как процесс завершился — он уничтожается.
Зомби — это процесс, который закончил выполняться, но информация об этом еще не поступила родительскому процессу. Процесс при завершении высвобождает все свои ресурсы (за исключением PID) и становится «зомби» — пустой записью в таблице процессов, хранящий код завершения для родительского процесса.
Все процессы выстраиваются в очередь на выполнение команд. При этом существует несколько очередей в зависимости от статуса процесса: очередь готовых и очередь заблокированных. По истечении работы процесс переходит в начало очередь и вновь ждет своего момента для доступа к ресурсам центрального процессора.
Работа с процессами в Linux
Просмотреть список всех процессов, выполняемых в текущий момент времени можно с помощью команды ps. С помощью команды ps можно получить информацию об идентификаторах, приоритете и управляющем терминале того или иного процесса. Она также позволяет выяснить объем оперативной памяти, который использует процесс, сколько времени центрального процессора заняло его выполнение, а также состояние процесса (выполняется, остановлен, простаивает и т.д.). Получить список всех процессов можно с помощью следующей команды:
user@ubuntu$ ps aux
Ключ a используется для вывода всех процессов, ключ x — отображает процессы, отсоединенные от терминала, ключ u — обеспечивает фильтрование по имени или идентификатору пользователя, который запустил программу.
Значение столбцов при выводе команды ps aux:
- USER — имя владельца процесса
- PID — идентификатор процесса
- %CPU — доля времени центрального процессора, которая тратится на данный процесс (в процентах)
- %MEM — часть реальной памяти, которая тратится на данный процесс (в процентах)
- VSZ — виртуальный размер процесса
- RSS — количество страниц памяти
- TTY — идентификатор управляющего терминала
- STAT — текущий статус процесса (R-выполняется, D-ожидает записи на диск, S-неактивен, T-приостановлен, Z-зомби)
- TIME — количество времени центрального процессора, затраченное на выполнение данного процесса
- COMMAND — имя и аргументы команды
Ниже в сокращенном виде показаны результаты работы команды ps lax. Обратите внимание на дополнительные поля PPID (идентификатор родительского процесса), NI (фактор уступчивости), WCHAN (ресурс, которого ожидает процесс).
NI по сути отображает приоритет процесса. Чем ниже значение — тем приоритетней он будет выполняться процессором. Значение варьируются от -20 до 20.
Очень удобно искать идентификатор процесса с помощью связки команд ps и grep. PS выводит список процессов, после чего передает управление команде grep, которая в свою очередь выделяет из списка искомый процесс. Пример: найдем PID для процесса cron.
Как видно PID для процесса cron равен 879.
Команда ps позволяет сделать только разовый «снимок» системы. Для динамического отслеживания процессов используют команду top.
Наиболее активные процессы находятся вверху. Команда top отображает также статистику по статусам процессов, объем используемых ресурсов ЦПУ и оперативной памяти.
Сигналы — это запросы на прерывания, реализуемые на уровне процессов.
Когда поступает сигнал, возможен один из двух вариантов событий. Если процесс назначил сигналу подпрограмму обработки, то после вызова ей предоставляется информация о контексте, в котором был сгенерирован сигнал. В противном случае ядро выполняет от имени процесса действия, заданные по умолчанию. Эти действия зависят от сигнала, а в некоторых случаях еще создается дамп памяти.
Дамп памяти — это файл, содержащий образ памяти процесса
Процедура вызова обработчика называется перехватом сигнала. Когда выполнение обработчика завершается, процесс возобновляется с той точки, где был получен сигнал.
Для того, чтобы некоторые сигналы не поступали в программу можно задать их игнорирование и блокирование. Игнорируемый сигнал просто пропускается и не влияет на работу процессора. Блокируемый сигнал ставится в очередь на обработку, но ядро не требует от процесса никаких действий до явного разблокирования сигнала.
Определено свыше тридцати разных сигналов, и они находят самое разное применение. Самые распространенные из них:
- KILL — безусловное завершение процесса на уровне ядра
- STOP — приостанавливает выполнение процесса
- CONT — возобновляет выполнение процесса
- TSTP — генерируется при нажатии CTRL + Z, приостанавливает процесс пользователем
- TERM — запрос на завершение программы (процесс осуществляет очистку и нормально завершается)
- QUIT — то же самое, что и TERM + создается дамп памяти
- HUP — команда сброса
- BUS — ошибка на шине (указывает на неправильное обращение к памяти)
- SEGV — ошибка на сегментации (указывает на неправильное обращение к памяти)
Сигналы KILL и STOP нельзя ни перехватить, ни заблокировать, ни проигнорировать.
Команда kill используется для отправки сигналов процессу. Kill имеет следующий синтаксис:
user@ubuntu$ kill [-сигнал] PID
Для примера уничтожим процесс cron. Ранее мы выяснили, что его PID = 879.
user@ubuntu$ kill -KILL 879
Как видим процесс cron убран. Сигналы типа kill надо посылать с правами суперпользователя. Также перед тем, как убивать cron я убрал строчку respawn в конфигурационном файле cron.conf, который находится в папке /etc/init/cron.conf.
Напоследок расскажу про еще одну интересную вещь. Upstart — это система инициализации ОС, которая управляет запуском демонов в течении загрузки системе. Хранятся конфигурационные файлы Upstart в папке /etc/init. Существует несколько команд для работы с Upstart.
Sorry, you have been blocked
This website is using a security service to protect itself from online attacks. The action you just performed triggered the security solution. There are several actions that could trigger this block including submitting a certain word or phrase, a SQL command or malformed data.
What can I do to resolve this?
You can email the site owner to let them know you were blocked. Please include what you were doing when this page came up and the Cloudflare Ray ID found at the bottom of this page.
Cloudflare Ray ID: 7a25688f8ecc2319 • Your IP: Click to reveal 88.135.219.175 • Performance & security by Cloudflare
Процессы Linux
Говоря простым языком, процесс представляет собой экземпляр выполняемой программы. Когда программа выполняется, ядро загружает ее код в виртуальную память, выделяет память под переменные программы и определяет учетные структуры данных ядра для записи различной информации о процессе (имеются в виду идентификатор процесса, код завершения, пользовательские и групповые идентификаторы).
С точки зрения ядра процессы являются объектами, между которыми ядро должно делить различные ресурсы компьютера. В случае с ограниченными ресурсами, например памятью, ядро изначально выделяет некоторый их объем процессу и регулирует это выделение в ходе жизненного цикла процесса, реагируя на потребности процесса и общие потребности системы в этом ресурсе. Когда процесс завершается, все такие ресурсы высвобождаются для повторного использования другими процессами. Другие ресурсы, такие как время центрального процессора и сетевой трафик, являются возобновляемыми, но должны быть поровну поделены между всеми процессами.
Модель памяти процесса
Процесс логически делится на следующие части, известные как сегменты.
- Текст — инструкции программы.
- Данные — статические переменные, используемые программой.
- Динамическая память (куча) — область, из которой программа может динамически выделять дополнительную память.
- Стек — часть памяти, которая может расширяться и сжиматься по мере вызова функций и возвращения из них и которая используется для выделения хранилища под локальные переменные и информацию о взаимосвязанности вызовов функций.
Создание процесса и выполнение программы
Процесс может создать новый процесс с помощью системного вызова fork() . Процесс, вызывающий fork() , известен кък родительский процесс, а новый процесс называется дочерним процессом. Ядро создает дочерний процесс путем изготовления дубликата родительского
процесса. Дочерний процесс наследует копии родительских сегментов данных, стека и кучи, которые затем могут изменяться независимо от своих родительских копий. (Текст программы размещается в области памяти с пометкой «только для чтения» и совместно используется двумя процессами.)
Дочерний процесс запускается либо для выполнения другого набора функций в том же самом коде, что и у родительского процесса, либо зачастую для использования системного вызова execve()) с целью загрузки и выполнения совершенно новой программы. Вызов execve()) удаляет существующие сегменты текста, данных, стека и кучи, заменяя их новыми сегментами, основываясь на коде новой программы.
У вызова execve()) есть ряд надстроек в виде родственных функций библиотеки языка С с несколько отличающимся интерфейсом, но сходной функциональностью. У всех этих функций имена начинаются со строки ехес . (В тех случаях, когда разница между ними неважна, мы будем для общей ссылки на эти функции использовать обозначение ехес() . И все же следует иметь в виду, что на самом деле функции по имени ехес() не существует.)
В основном глагол «выполнять» ( ехес ) будет употребляться для описания операций, выполняемых execve()) и ее библиотечными функциями-надстройками.
Идентификатор процесса и идентификатор родительского процесса
У каждого процесса есть уникальный целочисленный идентификатор процесса (PID). У каждого процесса также есть атрибут идентификатора родительского процесса (PPID), идентифицирующий процесс, запросивший у ядра создание данного процесса.
Завершение процесса и код завершения
Процесс может быть завершен двумя способами: запросом своего собственного завершения с использованием системного вызова _exit() (или родственной ему библиотечной функции exit() ) или путем его уничтожения извне с помощью сигнала. В любом случае процесс выдает код завершения, небольшое неотрицательное целое число, которое может быть проверено родительским процессом с использованием системного вызова wait() . В случае вызова _exit() процесс явным образом указывает свой собственный код завершения. Если процесс уничтожается сигналом, код завершения устанавливается по типу сигнала, уничтожившего процесс. (Иногда мы будем называть аргумент, передаваемый _exit() , кодом выхода процесса, чтобы отличить его от кода завершения, который является либо значением, переданным _exit() , либо указателем на сигнал, уничтоживший процесс.)
По соглашению, код завершения 0 служит признаком успешного завершения процесса, а ненулевое значение служит признаком возникновения какой-то ошибки. Большинство оболочек позволяют получить код завершения последней выполненной программы с помощью переменной оболочки по имени $? .
Принадлежащие процессу идентификаторы пользователя и группы (учетные данные)
У каждого процесса имеется несколько связанных с ним идентификаторов пользователей ( UID ) и групп ( GID ). К ним относятся следующие.
- Реальный идентификатор пользователя и реальный идентификатор группы. Они идентифицируют пользователя и группу, которым принадлежит процесс. Новый процесс наследует эти идентификаторы ( ID ) от своего родительского процесса. Оболочка входа в систему получает свой реальный UID и реальный GID от соответствующих полей в системном файле паролей.
- Действующий идентификатор пользователя и действующий идентификатор группы.
- Эти два идентификатора (в сочетании с рассматриваемыми сразу после них дополнительными идентификаторами групп) используются при определении прав доступа, имеющихся у процесса при доступе к защищенным ресурсам, таким как файлы и объекты обмена данными между процессами. Обычно имеющиеся у процессов действующие идентификаторы содержат те же значения, что и соответствующие им реальные ID . При изменении действующих идентификаторов процессу можно присваивать права доступа другого пользователя или группы, в порядке, который вскоре будет рассмотрен.
- Дополнительные идентификаторы группы. Они позволяют определить дополнительные группы, которым принадлежит процесс. Новый процесс наследует свои дополнительные идентификаторы групп от своего родительского процесса. Оболочка входа в систему получает свои дополнительные идентификаторы групп от системного файла групп.
Привилегированные процессы
Традиционно в системах UNIX привилегированным считается процесс, чей действующий идентификатор пользователя имеет значение 0 (привилегированный пользователь, суперпользователь). Такой процесс обходит ограничения прав доступа, обычно применяемые ядром. И наоборот, непривилегированным называется процесс, запущенный другими пользователями. Такие процессы имеют ненулевой действующий UID и должны соблюдать навязываемые ядром правила разрешения доступа.
Процесс может быть привилегированным из-за того, что был создан другим привилегированным процессом, например оболочкой входа в систему, запущенной суперпользователем (root). Еще один способ получения процессом привилегированности связан с механизмом установки идентификатора пользователя ( set-user-ID ), который позволяет присвоить процессу такой же действующий идентификатор пользователя, как и идентификатор пользователя файла выполняемой программы.
Мандаты (возможности)
Начиная с ядра версии 2.2, Linux делит привилегии, традиционно предоставляемые суперпользователю, на множество отдельных частей, называемых возможностями. Каждая привилегированная операция связана с конкретной возможностью, и процесс может выполнить операцию, только если у него имеется соответствующая возможность. Традиционный привилегированный процесс (с действующим идентификатором пользователя, равным 0 ) соответствует процессу со всеми включенными возможностями.
Предоставление процессу некоторого набора возможностей позволяет ему выполнять часть операций, обычно разрешенных суперпользователю, не позволяя ему выполнять другие операции такого вида.
Процесс init
При загрузке системы ядро создает особый процесс, который называется init , «родитель всех процессов». Он ведет свое происхождение от программного файла /sbin/init . Все процессы в системе создаются (используя fork() ) либо процессом init , либо одним из его потомков. Процесс init всегда имеет идентификатор процесса 1 и запускается с правами доступа суперпользователя. Процесс init не может быть уничтожен (даже привилегированным пользователем) и завершается только при завершении работы системы. Основной задачей init является создание и слежение за процессами, требуемыми работающей системе. (Подробности можно найти на странице руководства init(8) .)
Процессы-демоны
Демоном называется процесс специального назначения, создаваемый и управляемый системой точно так же, как и другие процессы, но отличающийся от них следующими характеристиками.
- Он долгоживущий. Процесс-демон зачастую запускается при загрузке системы и продолжает свое существование до тех пор, пока работа системы не будет завершена.
- Он запускается в фоновом режиме, и у него нет управляющего терминала, с которого он мог бы считывать ввод или на который он мог бы записывать вывод.
- К примерам процессов-демонов относятся syslogd , который записывает сообщения в системный журнал, и httpd , который обслуживает веб-страницы посредством протокола передачи гипертекста — Hypertext Transfer Protocol (HTTP).
Список переменных среды
У каждого процесса имеется список переменных среды, являющийся набором переменных среды, который содержится в памяти пользовательского пространства процесса. Каждый элемент этого списка состоит из имени и связанного с ним значения. При создании нового процесса с помощью fork() он наследует копию среды своего родителя. Таким образом, среда предоставляет родительскому процессу механизм для обмена информацией с дочерним процессом. Когда процесс заменяет программу, запуская новую программу с помощью ехес() , последняя либо наследует среду, используемую старой программой, либо получает новую среду, указанную как часть вызова ехес() .
Переменные среды, как в следующем примере, создаются в большинстве оболочек командой export (или командой setenv в оболочке С shell):
При предоставлении сессии командной оболочки, показывающей интерактивный ввод и вывод, текст ввода будет всегда выделяться полужирным шрифтом. Иногда в сессию будет включаться комментарий, выделенный курсивом, — в нем содержатся пояснения, касающиеся введенных команд или произведенного вывода.
Программы на языке С могут получать доступ к среде, используя внешнюю переменную ( char **environ ) и различные библиотечные функции, позволяющие процессу извлекать и изменять значения в его среде.
Переменные среды предназначены для различных целей. Например, оболочка определяет и использует ряд переменных, к которым можно получить доступ из сценариев и программ, выполняемых из оболочки. В число таких переменных входят НОМЕ , указывающая путевое имя пользовательского каталога входа в систему, и PATH , указывающая список каталогов, в которых оболочка будет вести поиск программ, соответствующих введенным пользователем командам.
Ограничения ресурсов
Каждый процесс потребляет ресурсы, например открытые файлы, память и время центрального процессора. Используя системный вызов setrlimit() , процесс может установить верхний предел своего потребления различных ресурсов. Каждый такой предел имеет два связанных с ним значения: мягкое ограничение, ограничивающее тот объем ресурса, который процесс может задействовать, и жесткое ограничение, представляющее собой верхний предел значения, которое может быть отрегулировано мягким ограничением. Непривилегированный процесс может изменить свое мягкое ограничение для конкретного ресурса на любое значение в диапазоне от нуля и до соответствующего жесткого ограничения, но свое жесткое ограничение он может только понизить.
Когда с помощью fork() создается новый процесс, он наследует копии настроек ограничений ресурсов от своего родительского процесса.
Ограничения ресурсов оболочки могут быть отрегулированы с использованием команды ulimit ( limit в оболочке С shell). Эти настройки ограничений наследуются дочерними процессами, создаваемыми оболочкой для выполнения команд.