Процессы Linux

Процессы операционной системы 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):

$ export MYVAR='Hello world'

При предоставлении сессии командной оболочки, показывающей интерактивный ввод и вы­вод, текст ввода будет всегда выделяться полужирным шрифтом. Иногда в сессию будет включаться комментарий, выделенный курсивом, — в нем содержатся пояснения, касающи­еся введенных команд или произведенного вывода.

Программы на языке С могут получать доступ к среде, используя внешнюю пере­менную (char **environ) и различные библиотечные функции, позволяющие процессу извлекать и изменять значения в его среде.

Переменные среды предназначены для различных целей. Например, оболочка опре­деляет и использует ряд переменных, к которым можно получить доступ из сценариев и программ, выполняемых из оболочки. В число таких переменных входят НОМЕ, указы­вающая путевое имя пользовательского каталога входа в систему, и PATH, указывающая список каталогов, в которых оболочка будет вести поиск программ, соответствующих введенным пользователем командам.

 

Ограничения ресурсов

Каждый процесс потребляет ресурсы, например открытые файлы, память и время цен­трального процессора. Используя системный вызов setrlimit(), процесс может устано­вить верхний предел своего потребления различных ресурсов. Каждый такой предел имеет два связанных с ним значения: мягкое ограничение, ограничивающее тот объем ресурса, который процесс может задействовать, и жесткое ограничение, представляющее собой верхний предел значения, которое может быть отрегулировано мягким ограничением. Непривилегированный процесс может изменить свое мягкое ограничение для конкрет­ного ресурса на любое значение в диапазоне от нуля и до соответствующего жесткого ограничения, но свое жесткое ограничение он может только понизить.

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

Ограничения ресурсов оболочки могут быть отрегулированы с использованием коман­ды ulimit (limit в оболочке С shell). Эти настройки ограничений наследуются дочерними процессами, создаваемыми оболочкой для выполнения команд.

 

Вас заинтересует / Intresting for you:

Основа операционной системы Li...
Основа операционной системы Li... 856 просмотров Андрей Волков Wed, 09 Jan 2019, 05:36:45
Дата и время для процесса в Li...
Дата и время для процесса в Li... 415 просмотров Fortan Thu, 21 Feb 2019, 16:33:05
Краткая история Linux
Краткая история Linux 816 просмотров Андрей Волков Wed, 09 Jan 2019, 02:46:59
Сигналы в Linux
Сигналы в Linux 536 просмотров Fortan Tue, 05 Feb 2019, 16:18:38

Войдите чтобы комментировать

Doc аватар
Doc ответил в теме #9353 22 фев 2019 07:51

OraDevel пишет: Я так понял это вводная статья больше для программистов? Те, кто соберется кодить Linux API?

В целом, да. Но и сисадмину будет полезно чуть глубже погрузиться в мир Linux.
OraDevel аватар
OraDevel ответил в теме #9338 28 янв 2019 11:11
Я так понял это вводная статья больше для программистов? Те, кто соберется кодить Linux API?