Яростный путь завершения процессов в Linux


Оглавление (нажмите, чтобы открыть):

Linux в жизни системного администратора

Подготовка к экзамену RHCSA

Вникаем в работу с процессами в Linux

Уже некоторое понимание этой операционной системы у меня сложилось. Неплохая, надо сказать, система. Удобная. Для экспериментов и реализации в творческой струе — в самый раз. Файлы создавать-редактировать вроде научился. Как быть с процессами?

Для этого в основном используются две программы ps и top.

Типичные задачи

Типичные задачи можно выделить следующего характера:

  1. Найти все процессы определенного пользователя;
  2. Найти определенный процесс;
  3. Завершить процесс;
  4. Изменить приоритет процесса;

Обычно, кстати, я пользуюсь синтаксисом BSD-систем, как-то проще это даётся.

найдёт все процессы, запущенные под пользователем dmitry

Пользователя можно указывать любого. Сгодится даже его UID вместо имени. Это если мы подозреваем, что юзер Вася что-то накосячил и запустил ресурсоёмкие приложения. Или что с правами пользователя запущен ненужный процесс… Одним словом, иногда надо. Не будем заострять внимание.

Бывает, так же, что процессы запущены с каким-то параметрами, которые нам нужно зафиксировать. Тут уже играет роль так называемая командная строка — параметры, передаваемые в процесс. Например, видно, что процесс с PID (идентификатор процесса) 15068 — это текстовый редактор vim. Параметром запуска является имя файла, который открыт в этом редакторе.

Для того, чтобы найти определенный процесс, проще всего воспользоваться фильтром grep:

# ps aux | grep httpd

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

Так мы отфильтруем среди всего списка процессов те, в описании которых (командная строка, например) присутствует слово httpd.

Так, предположим, найден нежелательный процесс. Как же его завершить?

Завершить процесс в CentOS

Можно завершить процесс натравив на него команду kill:

Кстати, посылать сигналы можно не только на завершение. Например, великолепная утилита dd принимает сигнал USR1 и выдает текущий прогресс (а так как выполняется она без отображения прогресса, это бывает полезно).

Ещё один способ — воспользоваться утилитой top:

Утилита top в CentOS Linux

Убивать процессы с помощью неё — одно удовольствие. Муха-ха. �� Шутка. Нет, в самом деле. Нажимаем клавишу k (kill), вводим PID процесса и, если надо, сигнал. И жмём Enter. Кстати, утилита имеет богатые возможности h (help). Предлагается изучить возможности утилиты самостоятельно.

Изменить приоритет процесса в Linux

Так, что касается приоритета процессов… Надо сказать, что приоритеты процессорного времени в Linux (nice) могут принимать значения от -20 до 19 (0 — по умолчанию). Чем меньше число, тем больше процессорных циклов получает процесс. Пользователи в системе могут только понижать приоритет своих процессов (выставляя положительные значения), суперпользователь же может выставить любой приоритет.

Запустить приложение с требуемым значением приоритета можно так:

# nice -n 5 команда

Разумеется, вместо значения 5 можно указать нужный уровень «вежливости*».

* под вежливостью (англ. nice) понимается готовность процесса пожертвовать свои такты процессора другим задачам.

А изменить приоритет уже запущенного процесса командой renice:

PID — идентификатор процесса, для которого необходимо изменить приоритет.

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

Стоит, кстати, не забывать про приоритеты процессов в плане ввода-вывода. Для этого служит команда ionice:

# ionice -c2 -n0 bash

Запустит баш с наивысшим приоритетом в плане ввода-вывода. Всего, кстати, есть три вида приоритета: 1 для realtime (все свободные ресурсы поставляются в первую очередь), 2 для best effort (по умолчанию для всех процессов, возможно указание дополнительного приоритета -n , большее предпочтение отдается наименьшим значениям) и 3 для idle (процесс может обращаться к диску только тогда, когда никто больше не обращается). Есть ещё параметр -p, который указывает pID процесса, для которого нужно изменить приоритеты.

Выделяя приоритет нужно отдавать себе отчёт в том, что легко можно укокошить систему, случайно выделив все ресурсы на выполнение «тяжелых» задач так, что вмешаться уже не будет возможности. А добавить к этому ещё и возможные опечатки в скрипте, которые могут стать фатальными. Будьте внимательны!

Завершить процесс в Linux — команды ps, kill и killall

Как бы там ни было, но некоторые приложения в Linux иногда зависают. При этом бывают ситуации, когда приложение вообще не отзывается, либо работает так медленно, что корректно завершить его работу не представляется возможным. Чтобы оперативно выйти из получившейся ситуации можно «убить» данный процесс. Для этог используеются команды kill и killall. Сейчас мы разберемся как использоваться эти команды, находить PID процесса и посылать сигнал SIGKILL.

Чтобы избежать путацины, договоримся под процессом понимать запущенную в систему программу. Например, если у вас запушено несколько окон браузера Mozilla Firefox — это значит, что запущено три процесса.

Определить P >PID — уникальный идентификатор процесса в системе Linux. Чтобы корректно выполнить остановку процесса сначала стоит определить его PID. Для этого используются команды ps и grep. В свою очередь команда ps предназначена для вывода списка активных процессов в системе и информации о них. Команда grep запускается одновременно с ps (в канале) и будет выполнять поиск по результатам команды ps. Вывести список всех процессов можно, выполнив в командной строке:

Разумеется, PID можно определить и через top. Но в большинстве случаев количество процессов слишком велико (и динамически меняется в top), поэтому быстро и правильно определить PID не так уж и просто. Как раз для этого используется команда grep. Например, для завершения процесса браузера Google Chrome необходимо выполнить следующую команду:

]$ ps axu | grep chrome
itechf2 20474 2.7 1.5 938416 120136 tty2 Sl+ 11:07 0:00 /opt/google/chrome/chrome

В нашем случае 20474 и есть искомый PID. Более простой способ — использовать команду pidof, при этом необходимо указывать имя процесса. Например:

]$ pidof chrome
20728 20706 20668 20647 20586 20574 20553 20508 20474

Завершить процесс в Linux — команды kill и killall

Завершить процесс в операционной системе Linux, зная его PID, можно командой kill. Стоит знать и понимать: команда kill предназначена для посылки сигнала процессу. По умолчанию, если мы не указываем какой сигнал посылать, посылается сигнал SIGTERM (от слова termination — завершение). SIGTERM указывает процессу на то, что необходимо завершиться. Каждый сигнал имеет свой номер. SIGTERM имеет номер 15. Список всех сигналов (и их номеров), которые может послать команда kill, можно вывести, выполнив kill -l. Чтобы послать сигнал SIGKILL (он имеет номер 9) процессу 2811, выполните в командой строке:


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

Команда killall в Linux предназначена для «убийства» всех процессов, имеющих одно и то же имя. Это удобно, так как нам не нужно знать PID процесса. Например, мы хотим закрыть все процессы с именем chrome. Выполните в терминале:

Команда killall, также как и kill, по умолчанию шлет сигнал SIGTERM. Чтобы послать другой сигнал нужно воспользоваться опцией -s. Например:

Нашли ошибку в тексте? Выделите фрагмент текста и нажмите Ctrl+Enter

Как найти и завершить запущенные процессы в Linux

Управление процессами является одним из важных аспектов системного администрирования в Linux и включает в себя завершение(«убийство») процессов с помощью команды kill.

В этой статье мы рассмотрим завершение менее производительных или нежелательных процессов в вашей Linux-системе.

Что такое процесс в Linux?

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

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

  • Выполнение: означает, что процесс либо выполняется, либо он просто установлен для выполнения.
  • Ожидание: это означает, что процесс ожидает событие или системный ресурс для выполнения задачи.

В Linux существует два типа процесса ожидания: прерываемое и бесперебойное.

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

  • Остановлен: это означает, что процесс был остановлен, используя сигнал.
  • Зомби: это означает, что процесс был внезапно остановлен и теперь мертв.

Теперь рассмотрим способы завершения процессов в системе Linux. Мы уже писали несколько статей о том, как завершать процессы с помощью kill, pkill, killall и xkill.

При завершении процессов команда kill используется для отправки именованного сигнала в именованный процесс или группу процессов. Сигнал по умолчанию — это сигнал TERM.

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

Как найти PID процесса в Linux

В Linux каждый процесс в системе имеет идентификатор PID (идентификационный номер процесса), который можно использовать для уничтожения процесса.

Вы можете идентифицировать PID любого процесса, используя команду pidof следующим образом:

Как завершать процессы в Linux

Вы нашли процесс PID, давайте теперь посмотрим, как убивать процессы. В этом первом примере я собираюсь сначала получить PID процесса, а затем отправить ему сигнал завершения.

Я хочу завершить процесс gimp, это можно сделать следующим образом:

Чтобы убедиться, что процесс был убит, запустите команду pidof, и вы не сможете просмотреть PID этого процесса.

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

Используйте номер сигнала, чтобы убить процесс:

В приведенном выше примере число 9 является номером сигнала для сигнала SIGKILL.

Как завершить одновременно несколько PID-процессов в Linux

Чтобы убить более одного процесса, передайте PID(s) команде kill следующим образом:

Спасибо за уделенное время на прочтение статьи!

Если возникли вопросы, задавайте их в комментариях.

Подписывайтесь на обновления нашего блога и оставайтесь в курсе новостей мира инфокоммуникаций!

Чтобы знать больше и выделяться знаниями среди толпы IT-шников, записывайтесь на курсы Cisco от Академии Cisco, курсы Linux от Linux Professional Institute на платформе SEDICOMM University.

Урок 19. Процессы в Linux — команды просмотра и управления

Что такое процессы?

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

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

Бывает так, что компьютер “тормозит” и не позволяет выполнять некоторые важные операции. Такое происходит, когда какой-нибудь процесс занимает большую часть оперативной памяти или процессорного времени. Зная основы работы с процессами можно отключить мешающий процесс и разгрузить компьютер. Существуют ситуации, когда запущенная программа перестает реагировать на действия пользователя и никак не удается ее закрыть штатным способом. В данном случае достаточно найти процесс данной программы и принудительно закрыть программу.

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

PID — (process ID) идентификатор каждого процесса

PPID — (parent process ID) идентификатор родительского процесса. Процесс может порождать и другие процессы.

UID, GID — реальные идентификаторы пользователя и его группы, запустившего данный процесс.

EUID, EGID — эффективные идентификаторы пользователя и его группы. В 16-ом уроке мы изучали признаки доступа SUID, SGID. Когда пользователь запускает файл с установленными признаками, то эффективные идентификаторы (EUID, EGID) равны реальным идентификаторам (UID, GID) владельца данного файла. То есть система смотрит на эффективные идентификаторы и таким образом узнает, что был установлен признак SUID/SGID и предоставляет доступ пользователю. Если пользователь запустит любой другой файл без установленного признака SUID/SGID, то реальные и эффективные идентификаторы всегда равны.

Priority/Nice — приоритет и относительный приоритет. Служит для выделения большего или меньшего процессорного времени для определенного процесса. Разрешается менять только относительный приоритет (Nice). Его значение варьируется от -20 до +19. Чем ниже значение относительного приоритета, тем больше процессорного времени выделяется для данного процесса.

STAT — состояние процесса. В таблице представлены обозначения процессов:

Работа с процессами в Linux

Список процессов

Вывести на экран список текущих процессов, запущенных пользователем, можно командой:


Чтобы посмотреть список всех процессов с дополнительной информацией, вводим:

Мы увидим, примерно, следующее:

USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 661 0.0 0.0 4072 8 tty1 Ss+ Jul03 0:00 /sbin/mingetty
root 662 0.0 0.0 4072 8 tty2 Ss+ Jul03 0:00 /sbin/mingetty
root 16355 0.0 0.0 171636 3308 pts/0 S 15:46 0:00 sudo su
root 16366 0.0 0.0 140896 1556 pts/0 S 15:46 0:00 su
root 16368 0.0 0.0 108316 1944 pts/0 S 15:46 0:00 bash
root 18830 0.0 0.0 110244 1172 pts/0 R+ 16:20 0:00 ps u

  • USER — учетная запись пользователя, от которой запущен процесс.
  • P > Ключ Описание -A Все процессы. -a Запущенные в текущем терминале, кроме главных системных. -d Все, кроме главных системных процессов сеанса. -e Все процессы. f Показать дерево процессов с родителями. T Все на конкретном терминале. a Все, связанные с текущим терминалом и терминалами других пользователей. r Список только работающих процессов. x Отсоединённые от терминала. u Показать пользователей, запустивших процесс.

Примеры

Поиск процесса с помощью grep:

ps aux | grep apache

Убить процесс

Останавливаем процесс по его PID:

Если процесс не завершается, убиваем его принудительно:

Остановить все процессы с именем nginx:

Как и в случае с kill, можно это сделать принудительно:

killall -9 nginx

Подробная информация о процессе

Для каждого процесса создается каталог по пути /proc/

, в котором создаются папки и файлы с описанием процесса.

Примеры использования /proc/

Подробный вывод статуса:

Адрес в ячейках оперативной памяти, которые занял процесс:

Команда, которой был запущен процесс:

Символьная ссылка на рабочий каталог процесса:

Символьная ссылка на исполняемый файл, запустивший процесс:

Увидеть ссылки на дескрипторы открытых файлов, которые затрагивает процесс:

Подробное описание на сайте man7.org.

Потребление ресурсов процессами

Для просмотра статистики потребления ресурсов используем утилиту top:

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
21059 root 20 0 157884 2280 1496 R 18,8 0,1 0:00.03 top
1 root 20 0 190996 2964 1652 S 0,0 0,1 6:49.99 systemd
2 root 20 0 0 0 0 S 0,0 0,0 0:01.78 kthreadd
3 root 20 0 0 0 0 S 0,0 0,0 0:24.75 ksoftirqd/0
5 root 0 -20 0 0 0 S 0,0 0,0 0:00.00 kworker/0:0H

  • PID — идентификатор процесса.
  • USER — имя учетной записи, от которой запущен процесс.
  • PR — приоритет процесса.
  • NI — приоритет, выставленной командой nice.
  • VIRT — объем виртуальной памяти, потребляемый процессом.
  • RES — объем используемой оперативной памяти.
  • SHR — количество разделяемой памяти, которое используется процессом.
  • S — состояние процесса.
  • %CPU — процент использования процессорного времени.
  • %MEM — потребление оперативной памяти в процентах.
  • TIME — использование процессорного времени в секундах.
  • COMMAND — команда, которая запустила процесс.

Анатомия управления процессами в Linux

Создание, управление, планирование и завершение

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

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

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

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

Представление процессов

Читайте другие статьи Тима Джонса на сайте developerWorks

В ядре Linux процесс представлен довольно большой структурой task_struct (дескриптором процесса). Помимо самой необходимой для описания процесса информации эта структура содержит массу других данных, используемых для учета и связи с другими процессами (родительскими и порожденными). Полное описание структуры task_struct выходит за рамки статьи, однако, ее фрагмент, содержащий упомянутые в статье элементы, приведен в листинге 1. Стоит заметить, что структура task_struct объявлена в файле ./linux/include/linux/sched.h.

Листинг 1. Небольшой фрагмент структуры task_struct

В листинге 1 можно вполне ожидаемо увидеть такие данные, как состояние выполнения, стек, набор флагов, указатель на дескриптор родительского процесса, поток выполнения (их может быть несколько) и дескрипторы открытых процессом файлов. Некоторые поля мы рассмотрим подробно сейчас, к остальным же вернемся позже. Переменная state состоит из битовых флагов, отражающих состояние процесса. Большую часть времени процесс выполняется или ожидает выполнения в очереди ( TASK_RUNNING ), находится в состоянии приостановки ( TASK_INTERRUPTIBLE ), в состоянии непрерываемой приостановки ( TASK_UNINTERRUPTIBLE ), в состоянии останова ( TASK_STOPPED ) и нескольких других. Полный список флагов состояний можно найти в файле ./linux/include/linux/sched.h.

Слово flags также состоит из большого числа флагов, дающих дополнительные сведения о состоянии процесса, например, происходит ли в данный момент создание процесса ( PF_STARTING ), его завершение ( PF_EXITING ) и даже запрошено ли выделение памяти ( PF_MEMALLOC ). Имя исполняемого файла (не содержащее путь) находится в поле comm .

Хотя каждому процессу назначается приоритет (его значение хранится в поле static_prio ), фактический приоритет процесса определяется динамически исходя из загрузки и других факторов. Чем ниже значение приоритета, тем выше его фактический приоритет.

Поле tasks представляет собой элемент связного списка. Оно содержит указатель prev (указывающий на предыдущий дескриптор процесса) и указатель next (указывающий на следующий дескриптор процесса).

Адресное пространство процесса представлено полями mm и active_mm . Поле mm содержит указатель на структуру, описывающую адресное пространство процесса, а поле active_mm указывает на такую же структуру, но относящуюся к предыдущему процессу (это сделано для ускорения переключения контекстов).

Последнее из рассматриваемых полей, thread_struct , содержит сохраненное состояние процесса. Конкретная реализация этой структуры зависит от архитектуры оборудования, на котором выполняется Linux. Ее пример можно найти в файле ./linux/include/asm-i386/processor.h. Эта структура служит для сохранения процесса при переключении контекста (сохраняется состояние аппаратных регистров, счетчика команд и т. п.).

Управление процессами

Максимальное количество процессов

Несмотря на то, что процессы создаются динамически, их максимальное количество ограничено. В ядре это ограничение представлено символом max_threads , объявленным в файле ./linux/kernel/fork.c. Его значение можно изменять из пользовательского пространства через файл /proc/sys/kernel/threads-max файловой системы proc.

Теперь перейдем к рассмотрению управления процессами в Linux. В большинстве случаев процессы создаются динамически и описываются динамически создаваемыми дескрипторами (экземплярами структуры task_struct ). Исключением является процесс init , существующий всегда и описываемый init_task — статически создаваемым дескриптором процесса, объявленным в файле ./linux/arch/i386/kernel/init_task.c.

В Linux существует два способа организации процессов. Первый способ основан на использовании хеш-таблицы, ключом которой является значение PID; второй способ использует кольцевой двусвязный список. Способ, использующий кольцевой список, идеален для последовательного перебора списка процессов. Поскольку кольцевой список не имеет начала и конца, за отправную точку можно принять дескриптор init_task , который существует всегда. Рассмотрим пример перебора списка текущих задач.

Список задач недоступен из пользовательского пространства, но эту проблему легко решить путем добавления нашего кода в ядро в виде модуля. В листинге 2 приведен текст простейшей программы, осуществляющей перебор списка задач и выводящей немного информации о каждой из них ( name , pid и имя родительского процесса, указатель на дескриптор которого хранится в поле parent ). Обратите внимание на использование модулем вызова printk для вывода сообщений. Сообщения, выведенные модулем, можно будет найти в файле /var/log/messages и вывести на консоль с помощью утилиты cat (или tail -f /var/log/messages для вывода сообщений в режиме реального времени). Функция next_task представляет собой макрос, объявленный в файле sched.h и предназначенный для облегчения перебора списка задач (возвращает указатель на дескриптор следующей задачи).


Листинг 2. Простой модуль ядра для вывода сведений о задачах (procsview.c)

Скомпилировать этот модуль можно с помощью make-файла, приведенного в листинге 3. После компиляции модуль можно загружать в ядро командой insmod procsview.ko и выгружать командой rmmod procsview .

Листинг 3. make-файл для сборки модуля ядра

После загрузки модуля в файле /var/log/messages появятся приведенные ниже сообщения. В их числе — информация о задаче бездействия системы (называемой swapper ) и задаче init (pid 1).

Обратите внимание на сведения о текущей задаче. В Linux имеется символ current , представляющий собой указатель на дескриптор текущего процесса (т.е. экземпляр структуры task_struct ). Если добавить в конец функции init_module строку:

будет выведено сообщение:

Заметим, что текущей задачей является insmod , поскольку функция init_module выполняется в контексте этой команды. Символ current , в действительности являющийся указателем на функцию ( get_current ), можно найти в архитектурно-зависимом заголовочном файле ./linux/include/asm-i386/current.h).

Создание процессов

Системные вызовы

Вы, вероятно, обращали внимание на закономерность в наименованиях системных вызовов. Они часто называются по шаблону sys_* и реализуют вспомогательную составляющую вызова (например, проверку возникновения ошибок и другие действия, выполняемые в пользовательском пространстве). Основная же работа вызова часто выполняется другой функцией, названной по шаблону do_* .

Рассмотрим создание пользовательского процесса шаг за шагом. Создание пользовательских процессов и процессов ядра фактически выполняется одним и тем же механизмом — вызовом do_fork . При создании потока ядра оно вызывает функцию kernel_thread (см. файл ./linux/arch/i386/kernel/process.c), выполняющую предварительную работу и затем вызывающую do_fork .

Аналогичные действия выполняются при создании пользовательского процесса. Программа осуществляет вызов fork , который, в свою очередь, обращается к системному вызову sys_fork (см. файл ./linux/arch/i386/kernel/process.c). Связь этих функций показана на диаграмме, приведенной на рисунке 1.

Рисунок 1. Иерархия вызовов при создании процесса

Из рисунка 1 видно, что функция do_fork выполняет основную работу по созданию процесса. Она объявлена в файле ./linux/kernel/fork.c (наряду с другой функцией создания процессов — copy_process ).

Функция do_fork начинает создание процесса с обращения к вызову alloc_pidmap , возвращающему новый PID. Затем do_fork проверяет, не находится ли родительский процесс в состоянии трассировки отладчиком. Если это так, то в параметре clone_flags функции do_fork устанавливается флаг CLONE_PTRACE . Далее функция do_fork вызывает функцию copy_process , передавая ей флаги, стек, регистры, дескриптор родительского процесса и ранее полученный новый PID.

Функция copy_process создает новый процесс путем копирования родительского процесса. Она выполняет все необходимые действия кроме запуска процесса, который происходит позже. Сначала copy_process проверяет, допустимо ли сочетание флагов CLONE . Если это не так, она возвращает код ошибки EINVAL . Затем она запрашивает Модуль безопасности Linux (LSM), разрешено ли текущей задаче породить новую задачу. Узнать больше об LSM в контексте Security-Enhanced Linux (SELinux) можно из материалов, приведенных в разделе Статьи.

Далее происходит вызов функции dup_task_struct (объявлена в файле ./linux/kernel/fork.c), создающей новый экземпляр структуры task_struct и копирующей в него различные дескрипторы, относящиеся к текущему процессу. После создания стека нового потока производится инициализация полей структуры task_struct , описывающих состояние процесса, после чего происходит возврат в copy_process . Затем в copy_process производится проверка лимитов и полномочий, выполняются вспомогательные действия, включающие инициализацию различных полей структуры task_struct . Потом происходит вызов функций, выполняющих копирование составляющих процесса: таблицы дескрипторов открытых файлов ( copy_files ), таблицы сигналов и обработчиков сигналов ( copy_signal и copy_sighand ), адресного пространства процесса ( copy_mm ) и структуры thread_info ( copy_thread ).

Затем только что созданная задача назначается процессору из числа разрешенных для ее выполнения ( cpus_allowed ). После того как новый процесс унаследует приоритет родительского процесса, выполняется еще небольшое число вспомогательных действий и происходит возврат в do_fork . Теперь новый процесс существует, но пока не выполняется. Функция do_fork решает эту проблему вызовом wake_up_new_task . Эта функция, определенная в файле ./linux/kernel/sched.c, инициализирует служебные данные планировщика, помещает новый процесс в очередь выполнения и инициирует его выполнение. После этого функция do_fork завершает создание процесса и свою работу, возвращая значение PID.

Планирование выполнения процесса

Выполнение процесса Linux потенциально может планироваться планировщиком задач. Выходя за рамки этой статьи, отмечу, что для каждого значения приоритета в планировщике задач Linux имеется список указателей на экземпляры структуры task_struct . Задачи запускаются функцией schedule (объявленной в файле ./linux/kernel/sched.c), определяющей наилучший процесс для выполнения исходя из загрузки системы и информации о ранее выполнявшихся процессах. Узнать больше о планировщике задач Linux версии 2.6 можно из материалов, приведенных в разделе Статьи.

Завершение процесса

Завершение процесса может быть вызвано несколькими событиями, от нормального завершения до завершения по сигналу или по вызову функции exit . Однако независимо от события, послужившего причиной завершения процесса, эта работа выполняется вызовом функции ядра do_exit (объявленной в ./linux/kernel/exit.c). Связь этой функции с различными вариантами завершения процесса показана на диаграмме, приведенной на рисунке 2.

Рисунок 2. Иерархия вызовов при завершении процесса

Функция do_exit предназначена для удаления из системы всех ресурсов завершаемого процесса (всех ресурсов, не являющихся общими). Первым шагом процедуры завершения процесса является установка флага PF_EXITING . Другие компоненты ядра анализируют значение этого флага, чтобы избежать выполнения действий с завершающимся процессом. Освобождение ресурсов, занятых процессом в течение его жизненного цикла, выполняется вызовами соответствующих функций, от exit_mm (освобождающей занятые страницы памяти) до exit_keys (удаляющей криптографические ключи потока, сеанса и процесса). Функция do_exit выполняет различные вспомогательные операции по завершению процесса и затем вызывает функцию exit_notify , рассылающую сигналы, оповещающие о завершении процесса (например, родительский процесс о завершении порожденного процесса). После этого статус процесса устанавливается в PF_DEAD и вызывается функция schedule , начинающая выполнение другого процесса. Обратите внимание на то, что если требуется отправка сигнала родительскому процессу (или процесс находится в режиме трассировки), задача не исчезнет из системы. Если отправка сигнала не требуется, вызов функции release_task освободит память, используемую процессом.

Двигаясь дальше

Развитие Linux продолжается, и в области управления процессами также будут появляться новые решения и производиться оптимизации. Оставаясь верным принципам UNIX, Linux продолжает осваивать новые рубежи. Новые архитектуры процессоров, симметричная многопроцессорная обработка (SMP) и виртуализация задают направления дальнейшего развития этой части ядра. Примером может служить новый O(1)-планировщик, появившийся в Linux версии 2.6, обеспечивающий масштабируемость систем, выполняющих большое количество задач. Другой пример — обновленная потоковая модель, использующая библиотеку потоков POSIX (Native POSIX Thread Library, NPTL) и обеспечивающая более эффективную работу потоков, нежели предшествующая модель LinuxThreads. Узнать больше о новых решениях и направлениях развития можно из материалов, приведенных в разделе Статьи.

Ресурсы для скачивания

Похожие темы

  • Оригинал статьи Anatomy of Linux process management (EN) (developerWorks, декабрь 2008 г.).
  • Одним из самых передовых решений в составе ядра версии 2.6 является O(1)-планировщик. Он позволяет Linux выполнять очень большое количество процессов, избегая обычных в таких случаях непроизводительных затрат. Больше узнать о планировщике ядра версии 2.6 можно из статьи «Планировщик задач Linux» (developerWorks, июнь 2006 г.).
  • Великолепный обзор управления памятью в Linux дан в книге Мела Гормана (Mel Gorman) Understanding the Linux Virtual Memory Manager (EN) (Prentice Hall, 2004), доступной также в формате PDF. В книге приведено подробное, но доступно изложенное описание управления памятью в Linux, включающее главу, посвященную адресному пространству процесса.
  • Хорошее введение в управление процессами дано в книге Performance Tuning for Linux: An Introduction to Kernels (EN) (Prentice Hall, 2005). Глава из этой книги доступна на сайте IBM Press.
  • В Linux реализован интересный подход к организации системных вызовов, использующий переходы между пользовательским пространством и ядром (разными адресными пространствами). Об организации системных вызовов в Linux можно узнать подробнее из статьи «Kernel command using Linux system calls» (EN) (developerWorks, март 2007 г.).
  • В этой статье были приведены примеры проверки ядром параметров безопасности процессов, выполняющих системные вызовы. Базовый интерфейс ядра и среды безопасности носит название Linux Security Module. Чтобы изучить Linux Security Module в контексте SELinux, читайте статью «Анатомия SELinux» (developerWorks, апрель 2008).
  • Спецификация Portable Operating System Interface (POSIX) standard for threads (EN) определяет стандартный интерфейс программирования приложений (API) для создания потоков и управления ими. Существуют реализации POSIX для Linux, Sun Solaris и даже для операционных систем, не основанных на UNIX.
  • Native POSIX Thread Library (EN) представляет собой эффективную реализацию POSIX-потоков в ядре Linux. Эта технология появилась в ядре версии 2.6. Предшествующая реализация называлась LinuxThreads (EN).
  • Обзор удобной альтернативы состояниям процесса TASK_UNINTERRUPTIBLE и TASK_INTERRUPTIBLE приведен в статье «TASK_KILLABLE: Новое состояние процесса в Linux» (developerWorks, сентябрь 2008 г.).
  • В разделе сайта developerWorks, посвященном Linux, можно найти другие материалы для Linux-разработчиков (включая новичков) и просмотреть наши самые популярные статьи и руководства (EN).
  • Ознакомьтесь со всеми полезными советами и руководствами по Linux на сайте developerWorks.

Комментарии

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

Как завершить процесс в ubuntu?

Как завершить процесс в ubuntu?

6 ответов 6

Надо запустить терминал и выполнить команду

где process_id — это номер процесса. Этот номер можно получить с помощью команды

Вариант 1) В терминале вводите

sudo killall -9 название процесса


sudo kill -9 ид процесса

Вариант 2) В терминале вводите

Выбираем нужный процесс, и жмем F9

Вообще существует множество вариантов и манов на этот счет, я привел Вам более популярные

Только не всегда процесс убъётся таким образом! По хорошему, лучше использовать

либо по названию процесса

По хорошему процесс следует завершать сигналом 2(SIGINT) или 15(SIGTERM) и если уж не помогает тогда 9(SIGKILL).

Сигнал 2 посылается программе связанной с терминалом при нажатии Ctrl+C, есть ещё запасная комбинация Ctrl+\, посылающая сигнал 3(SIGQUIT), который, если не перехватывается, делает дамп памяти процесса (чтобы потом посмотреть в отладчике).

Сигнал 15 посылается процессам при завершении работы системы или смены runlevel и по-умолчанию если не указан другой в командах kill и killall, по нему программа может быстренько сохранить важные данные и удалить временные файлы, если настроит перехват. Так же перехват сигнала 2 используется для завершающих действий перед выходом.

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

Блог о системном администрировании. Статьи о Linux, Windows, СХД NetApp и виртуализации.

Доброго времени, гости моего блога! В сегодняшнем посте расскажу о том, как работают процессы в ОC Linux, а так же как управлять этими самыми процессами, о выполнении процессов в фоне, о повышении/понижении приоритета процессов.

В общем представлении, процесс — это программа, выполняющаяся в оперативной памяти компьютера. Реально, все гораздо сложней.

В многозадачной системе может быть запущено множество программ. Каждая программа может запустить множество процессов (читай: подпрограмм). При этом в единственный момент на машине, выполняется только 1 процесс. То есть в единственный момент времени ресурсы железа (процессорное время, память, порт ввода/вывода) может использоваться только единственным процессом. Очередью, в которой процессу выделяется определенный ресурс железа, управляет планировщик. При этом, во время прерывания одного процесса и запуска (возобновления) другого процесса, состояние процесса (выполняемые действия, на каком этапе процесс приостановлен) запоминается и записывается в область памяти. Планировщик в Linux — это часть ядра, отвечающая за указанную функциональность. В задачи планировщика так же входит отслеживание и выделение запускаемым процессам определенного приоритета, чтобы процессы «не мешали» друг-другу работать, а так же распределение пространства памяти, чтобы пространство памяти одного процесса не пересекалось с пространством другого.

Все новые процессы в Linux порождаются клонированием какого-то уже имеющегося процесса, с помощью вызова системных функций clone(2) и fork(2) (от forking — порождение). У нового (порожденного или дочернего) процесса тоже окружение, что и у родителя, отличается только номер ID процесса (т.н. PID). Жизнь типичного процесса в Linux можно представить следующей схемой:

На которой можно описать пошагово следующие этапы:

  • процесс /bin/bash клонирует себя системным вызовом fork()
  • при этом создается клон /bin/bash с новым P >Очень наглядную схему предоставила википедия:

Из вышесказанного может последовать логичный вопрос: если новый процесс — всегда копия существующего, то каким образом в системе берется самый первый из процессов?

Первый процесс в системе запускается при инициализации ядра. Данный процесс называется — init и имеет P >

В каких же состояниях может находиться процесс в Linux?

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

  • Активен (R=Running) – процесс находится в очереди на выполнение, то есть либо выполняется в данный момент, либо ожидает выделения ему очередного кванта времени центрального процессора.
  • «Спит» (S=Sleeping) – процесс находится в состоянии прерываемого ожидания, то есть ожидает какого-то события, сигнала или освобождения нужного ресурса.
  • Находится в состоянии непрерываемого ожидания (D=Direct) – процесс ожидает определенного («прямого») сигнала от аппаратной части и не реагирует на другие сигналы;
  • Приостановлен (T) – процесс находится в режиме трассировки (обычно такое состояние возникает при отладке программ).
  • «Зомби» (Z=Zombie) – это процесс, выполнение которого завершилось, но относящиеся к нему структуры ядра по каким-то причинам не освобождены. Одной из причин их появления в системе может быть следующая ситуация. Обычно освобождение структур ядра, относящихся к процессу, выполняет процесс-родитель после получения от потомка сигнала о завершении. Но бывают случаи, когда родительский процесс завершается раньше дочернего. Процессы, не имеющие родителя, называются «сиротами«. «Сироты» автоматически усыновляются процессом init, который и принимает сигналы об их завершении. Если процесс-родитель или init по каким-то причинам не может принять сигнал о завершении дочернего процесса, то процесс-потомок превращается в «зомби» и получает статус Z. Процессы-зомби не занимают процессорного времени (т. е. их выполнение прекращается), но соответствующие им структуры ядра не освобождаются. В некотором смысле это «мертвые» процессы. Уничтожение таких процессов — одна из обязанностей системного администратора. Хочу отметить, что появление данных процессов говорит о том, что в системе что-то не в порядке, и скорее всего не в порядке с аппаратной частью, так что берем memtest и MHDD и тестим-тестим. Не исключен вариант и кривого кода программы.

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

Т.к. в большинстве случаев, демоны в Linux простаивают и ожидают поступления каких-либо данных, соответственно, нужны относительно редко, так что держать их в памяти постоянно загруженными и расходовать на это ресурсы системы нерационально. Для организации работы демонов придуман демон inetd или его более защищенная модификация xinetd (eXtended InterNET Daemon или расширенный Интернет демон). В функции inetd (Xinetd) можно выделить:

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

Все процессы в системе, не важно Linux это или другая ОС, обмениваются между собой какой-либо информацией. Отсюда можно задать вопрос, а как же происходит межПРОЦЕССный обмен?

В ОС LINUX существует несколько видов можпроцессного обмена, а точнее сказать средств межпроцессного взаимодействия (Interprocess Communication — IPC), которые можно разбить на несколько уровней:

локальный (привязаны к процессору и возможны только в пределах компьютера);

— каналы

  1. pipe (они же конвейеры, так же неименованные каналы), о них я много рассказывал в прошлом посте, примером можно привести: команда1 | команда2. По сути, pipe использует stdin, stdout и stderr.
  2. Именованные каналы (FIFO: First In First Out). Данный вид канала создаётся с помощью mknod или mkfifo, и два различных процесса могут обратиться к нему по имени. Пример работы с fifo:

в первом терминале (создаем именованный канал в виде файла pipe и из канала направляем данные с помощью конвейера в архиватор):

во втором терминале (отправляем в именованный канал данные):

в результате это приведет к сжатию передаваемых данных gzip-ом

— сигналы

  • с терминала, нажатием специальных клавиш или комбинаций (например, нажатие Ctrl-C генерирует SIGINT, а Ctrl-Z SIGTSTP);
  • ядром системы:
    • при возникновении аппаратных исключений (недопустимых инструкций, нарушениях при обращении в память, системных сбоях и т. п.);
    • ошибочных системных вызовах;
    • для информирования о событиях ввода-вывода;
  • одним процессом другому (или самому себе), с помощью системного вызова kill(), в том числе:
    • из шелла, утилитой /bin/kill.

сигнал — это асинхронное уведомление процесса о каком-либо событии. Когда сигнал послан процессу, операционная система прерывает выполнение процесса. Если процесс установил собственный обработчик сигнала, операционная система запускает этот обработчик, передав ему информацию о сигнале. Если процесс не установил обработчик, то выполняется обработчик по умолчанию.
Все сигналы начинаются на «SIG…» и имеют числовые соответствия, определяемые в заголовочном файле signal.h. Числовые значения сигналов могут меняться от системы к системе, хотя основная их часть имеет в разных системах одни и те же значения. Утилита kill позволяет задавать сигнал как числом, так и символьным обозначением.
Сигналы можно послать следующими способами:

— разделяемая память

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

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

— очереди сообщений


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

удаленный;

— удаленные вызовы процедур (Remote Procedure Calls — RPC)

RPC — разновидность технологий, которая позволяет компьютерным программам вызывать функции или процедуры в другом адресном пространстве (как правило, на удалённых компьютерах). Обычно, реализация RPC технологии включает в себя два компонента: сетевой протокол (чаще TCP и UDP, реже HTTP) для обмена в режиме клиент-сервер и язык сериализации объектов (или структур, для необъектных RPC).

— сокеты Unix

Сокеты UNIX бывают 2х типов: локальные и сетевые. При использовании локального сокета, ему присваивается UNIX-адрес и просто будет создан специальный файл (файл сокета) по заданному пути, через который смогут сообщаться любые локальные процессы путём простого чтения/записи из него. Сокеты представляют собой виртуальный объект, который существует, пока на него ссылается хотя бы один из процессов. При использовании сетевого сокета, создается абстрактный объект привязанный к слушающему порту операционной системы и сетевому интерфейсу, ему присваивается INET-адрес, который имеет адрес интерфейса и слушающего порта.

высокоуровневый

  1. Обычно — пакеты программного обеспечения, которые реализуют промежуточный слой между системной платформой и приложением. Эти пакеты предназначены для переноса уже испытанных протоколов коммуникации приложения на более новую архитектуру. Примером можно привести: DIPC, MPI и др. (мне не знакомы, честно говоря)

Итак. Подведем маленький итог:

  • В Linux есть процессы,
  • каждый процесс может запускать подпроцессы (нити),
  • создание нового процесса создается клонированием исходного,
  • прородителем всех процессов в системе является процесс init, запускаемый ядром системы при загрузке.
  • процессы взаимодействуют между собой по средствам можпроцессного взаимодействия:
    • каналы
    • сигналы
    • сокеты
    • разделяемая память
  • каждый процесс обладает свойствами (читай: обладает следующим контекстом):
    • PID — идентификатор процесса
    • PPID — идентификатор процесса, породившего данный
    • UID и GID — идентификаторы прав процесса (соответствует UID и GID пользователя, от которого запущен процесс)
    • приоритет процесса
    • состояние процесса (выполнение, сон и т.п.)
    • так же у процесса есть таблица открытых (используемых) файлов

Далее поговорим о том, как посмотреть состояние процессов в Linux и о том, как же ими управлять.

Управление процессами

Получение информации о процессе

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

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

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

# ps aux

Прокомментируем некоторые интересные моменты. Можно заметить, что некоторые процессы указаны в квадратных скобках [ ] – это процессы, которые входят непосредственно в состав ядра и выполняют важные системные задачи, например, такие как управление буферным кэшем [pdflush] и организацией свопинга [kswapd]. С ними лучше не экспериментировать – ничего хорошего из этого не выйдет :). Остальная часть процессов относится к пользовательским.

Какую информацию можно получить по каждому процессу (комментарии к некоторым полям):

  • PID, PPID – идентификатор процесса и его родителя.
  • %CPU – доля процессорного времени, выделенная процессу.
  • %MEM – процент используемой оперативной памяти.
  • VSZ – виртуальный размер процесса.
  • TTY – управляющий терминал.
  • STAT– статус процесса:
    • R – выполняется;
    • S – спит;
    • Z – зомби;
    • + — сортировка по PID;
    • + — сортировать процессы по возрасту;
    • +

    — сортировать процессы по использованию ЦПУ;

  • + — сортировать процессы по использованию памяти;
  • + — сортировка по времени выполнения.

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

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

Итак, теперь об управлении процессами.

Управление процессами в Linux

Каждому процессу при запуске устанавливается определенный приоритет, который имеет значение от -20 до +20, где +20 — самый низкий. Приоритет нового процесса равен приоритету процесса-родителя. Для изменения приоритета запускаемой программы существует утилита nice. Пример ее использования:

где adnice — значение (от –20 до +19), добавляемое к значению nice процесса-родителя. Отрицательные значения может устанавливать только суперпользователь. Если опция adnice не задана, то по умолчанию для процесса-потомка устанавливается значение nice, увеличенное на 10 по сравнению со значением nice родительского процесса.

Команда renice служит для изменения значения nice для уже выполняющихся процессов. Суперпользователь может изменить приоритет любого процесса в системе. Другие пользователи могут изменять значение приоритета только для тех процессов, для которых данный пользователь является владельцем. При этом обычный пользователь может только уменьшить значение приоритета. Поэтому процессы с низким приоритетом не могут породить «высокоприоритетных детей».

Как я уже писал, одним из средств управления процессами являются сигналы. Некоторые сигналы можно сгенерировать с помощью определенных комбинаций клавиш, но такие комбинации существуют не для всех сигналов. Зато имеется команда kill, которая позволяет послать заданному процессу (указав его PID) любой сигнал:

где SIG — это номер сигнала или наименование сигнала, причем если указание сигнала опущено, то посылается сигнал 15 (SIGTERM — программное завершение процесса). Часто используется сигнал 9 (KILL), с помощью которого суперпользователь может завершить любой процесс. Но сигнал этот очень «грубый», если можно так выразиться, потому что он просто «убивает» процесс, не давая ему времени на корректное сохранение всех обработанных данных. Поэтому в большинстве случаев рекомендуется использовать сигналы TERM или QUIT, которые завершают процесс более «мягко». Если процессу необходимо как-то по-особенному реагировать на сигнал, он может зарегистрировать обработчик, а если обработчика нет, за него отреагирует система.

Два сигнала – 9 ( KILL ) и 19 ( STOP ) – всегда обрабатывает система. Первый из них нужен для того, чтобы убить процесс наверняка (отсюда и название). Сигнал STOP приостанавливает процесс: в таком состояниипроцесс не удаляется из таблицы процессов, но и не выполняется до тех пор, пока не получит сигнал 18 ( CONT) – после чего продолжит работу. В Linux сигнал STOP можно передать активному процессу с помощью управляющего символа » ^Z «.

Обычные пользователи могут посылать сигналы только тем процессам, для которых они являются владельцами. Если в команде kill воспользоваться идентификатором процесса (PID), равным -1, то указанный в команде сигнал будет послан всем принадлежащим данному пользователю процессам. Суперпользователь root может посылать сигналы любым процессам. Когда суперпользователь посылает сигнал идентификатору -1, он рассылается всем процессам, за исключением системных. Если этим сигналом будет SIGKILL, то у простых пользователей будут потеряны все открытые ими, но не сохраненные файлы данных.

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

В оболочке bash имеются две встроенные команды, которые служат для перевода процессов на передний план или возврата их в фоновый режим. Команда fg переводит указанный в аргументе процесс на передний план, а команда bg — переводит процесс в фоновый режим. Одной командой bg можно перевести в фоновый режим сразу несколько процессов, а вот возвращать их на передний план необходимо по одному. Аргументами команд fg и bg могут являться только номера заданий, запущенных из текущего экземпляра shell. Возможные значения заданий можно увидеть, выполнив команду jobs.

При завершении сессии оболочка посылает всем порожденным ею процессам сигнал «отбой», по которому порожденные ею процессы могут завершиться, что не всегда желательно. Если вы хотите запустить в фоновом режиме программу, которая должна выполняться и после вашего выхода из оболочки, то ее нужно запускать с помощью утилиты nohup:

Запущенный таким образом процесс будет игнорировать посылаемые ему сигналы (не игнорируются только сигналы SIGHUP и SIGQUIT). Хочу так же выделить команду pstree, которая показывает дерево процессов. Очень наглядно, кстати.

Ну вот. как-то так. Буду рад любым комментариям и дополнениям.

Upd 2011.11.19: небольшой рестайлинг и дополнение информации о сигналах.

Завершить все дочерние процессы в LInux


Я разрабатываю песочницу на linux. И теперь я запутался в завершении всего процесса в песочнице. Моя песочница работает следующим образом: сначала в песочнице запускается только один процесс. Затем он может создать несколько дочерних процессов. И дочерний процесс также создаст свой подпроцесс. И родительский процесс может выйти через некоторое время до выхода своих детей. Наконец песочница завершит весь процесс.

Я использовал это, используя killall или pkill -u с уникальным пользователем, прикрепленным к песочнице. Но, похоже, он не работает в программе, которая быстро использует fork().

Затем я ищу исходный код pkill и понял, что pkill теряет атомарность.

Итак, как я мог достичь своей цели?

Вы можете использовать группы процессов setpgid (2) и сеансы setsid (2), но я не квалифицирую, что вы делаете в виде песочницы (в частности, потому что, если один из процессов является setuid или изменяет свою группу процессов или сам сеанс, Я потеряю его, внимательно прочитайте execve (2) и несколько раз!). Обратите внимание, что kill (2) с отрицательным pid убивает всю группу процессов.

Прочтите хорошую книгу, например, Advanced Linux Programming. Рассмотрим также использование chroot (2).

И объясните, что и почему вы действительно хотите сделать. песочница сложнее, чем вы думаете. См. Также возможности (7), учетные данные (7) и SElinux.

Яростный путь завершения процессов в Linux

Сухая формулировка говорит нам что процесс это — совокупность программного кода и данных, загруженных в память ЭВМ. На первый взгляд процесс — это запущенная программа (приложение) или команда. Но это не совсем так. Некоторые приложения могут создавать несколько процессов одновременно.

Код процесса не обязательно должен выполняться в текущий момент времени, так как процесс может находиться в состоянии спящего. В этом случае выполнение кода такого процесса приостановлено. Существует всего 3 состояния, в которых может находиться процесс:

Работающий процесс — в данный момент код процесса выполняется.

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

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

Каждому процессу в системе назначаются числовые идентификаторы (личные номера) в диапазоне от 1 до 65535 (PID — Process Identifier — идентификатор процесса) и идентификаторы родительского процесса (PPID — Parent Process Identifier — идентификатор родительского процесса). PID является именем процесса, по которому мы можем адресовать процесс в операционной системе при использовании различных средств просмотра и управления процессами. PPID определяет родственные отношения между процессами, которые в значительной степени определяют его свойства и возможности. Другие параметры, которые необходимы для работы программы, называют «окружение процесса». Одним из таких параметров является управляющий терминал — имя терминального устройства, на которое процесс выводит информацию и с которого информацию получает. Управляющий терминал имеют далеко не все процессы. Процессы, не привязанные к какому-то конкретному терминалу называются «демонами» (daemons). Такие процессы, будучи запущенными пользователем, не завершают свою работу по окончании сеанса, а продолжают работать, так как они не связаны никак с текущим сеансом и не могут быть автоматически завершены. Как правило, с помощью демонов реализуются серверные службы, так например сервер печати реализован процессом-демоном cupsd, а сервер журналирования — syslogd.

Для просмотра списка процессов в Linux существует команда ps. Формат команды следующий:

ps [PID] [options] — просмотр списка процессов. Без параметров ps показывает все процессы, которы были запущены в течение текущей сессии, за исключением демонов. Options может принимать одно из следующих значений или их комбинации:

-а или -e — показать все процессы

-f — полный листинг

-w — показать полные строки описания процессов. Если они превосходят
длину экрана, то перенести описание на следующую строку.

Это далеко не все параметры команды ps. Остальные параметры Вы можете узнать, просто набрав man ps.

Пример1:

[gserg@WEBMEDIA gserg]$ ps

PID TTY TIME CMD

3126 pts/2 00:00:00 bash

3158 pts/2 00:00:00 ps

Пример2:

[gserg@WEBMEDIA gserg]$ ps 3126

PID TTY STAT TIME COMMAND

3126 pts/2 S 0:00 /bin/bash

Пример3:

[gserg@WEBMEDIA gserg]$ ps -ef

UID PID PPID C STIME TTY TIME CMD

root 1 0 0 10:01 ? 00:00:03 init [5]

root 2 1 0 10:01 ? 00:00:00 [keventd]

root 3 1 0 10:01 ? 00:00:00 [kapmd]

root 4 1 0 10:01 ? 00:00:00 [ksoftirqd_CPU0]

root 5 1 0 10:01 ? 00:00:24 [kswapd]

root 6 1 0 10:01 ? 00:00:00 [bdflush]

gserg 3126 3124 0 17:56 pts/2 00:00:00 /bin/bash

gserg 3160 3126 0 17:59 pts/2 00:00:00 ps -ef

Пример4:

[gserg@WEBMEDIA gserg]$ ps -efw

UID PID PPID C STIME TTY TIME CMD

root 1 0 0 10:01 ? 00:00:03 init [5]

root 2 1 0 10:01 ? 00:00:00 [keventd]

root 3 1 0 10:01 ? 00:00:00 [kapmd]

root 4 1 0 10:01 ? 00:00:00 [ksoftirqd_CPU0]

root 5 1 0 10:01 ? 00:00:24 [kswapd]

root 1130 1 0 10:02 ? 00:00:00 /usr/sbin/apmd -p 10 -w 5 -W -P /etc/sysconfig/apm-scripts/apmd_proxy

gserg 3172 3126 0 18:01 pts/2 00:00:00 ps -efw

Процессы в ОС Linux обладают теми же правами, которыми обладает пользователь, от чьего имени был запущен процесс.

На самом деле операционная система воспринимает работающего в ней пользователя как набор запущенных от его имени процессов. Ведь и сам сеанс пользователя открывается в командной оболочке (или оболочке Х) от имени пользователя. Поэтому когда мы говорим «права доступа пользователя к файлу» то подразумеваем «права доступа процессов, запущенных от имени пользователя к файлу».

Для определения имени пользователя, запустившего процесс, операционная система использует реальные идентификаторы пользователя и группы, назначаемые процессу. Но эти идентификаторы не являются решающими при определении прав доступа. Для этого у каждого процесса существует другая группа идентификаторов — эффективные.

Как правило, реальные и эффективные идентификаторы процессов одинаковые, но есть и исключения. Например, для работы утилиты passwd необходимо использовать идентификатор суперпользователя, так как только суперпользователь имеет права на запись в файлы паролей. В этом случае эффективные идентификаторы процесса будут отличаться от реальных. Возникает резонный вопрос — как это было реализовано?

У каждого файла есть набор специальных прав доступа — биты SUID и SGID. Эти биты позволяют при запуске программы присвоить ей эффективные идентификаторы владельца и группы-владельца соответственно и выполнять процесс с правами доступа другого пользователя. Так как файл passwd принадлежит пользователю root и у него установлен бит SUID, то при запуске процесс passwd будет обладать правами пользователя root.

Устанавливаются биты SGID и SUID командой chmod:

chmod u+s filename — установка бита SUID

chmod g+s filename — установка бита SGID

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

Родителем всех процессов в системе является процесс init. Его PID всегда 1, PPID — 0. Всю таблицу процессов можно представить себе в виде дерева, в котором корнем будет процесс init. Этот процесс хоть и не является частью ядра, но выполняет в системе очень важную роль — определяет текущий уровень инициализации системы и следит чтобы были запущены программы, позволяющие пользователю общаться с компьютером (mingetty, X или другие).

Процессы, имена которых заключены в квадратные скобки, например «[keventd]» — это процессы ядра. Эти процессы управляют работой системы, а точнее такими ее частями, как менеджер памяти, планировщик времени процессора, менеджеры внешних устройств и так далее.

Остальные процессы являются пользовательскими, запущенными либо из командной строки, либо во время инициализации системы.

Жизнь каждого процесса представлена следующими фазами:

Создание процесса — на этом этапе создается полная копия того процесса, который создает новый. Например, вы запустили из интерпретатора на выполнение команду ls. Командный интерпретатор создает свою полную копию.

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

Выполнение процесса

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

Умирание процесса — после всех завершающих стадий удаляется запись из таблицы процессов — процесс завершил свою работу.

Во время работы процесса, ядро контролирует его состояние, и в случае возникновения непредвиденной ситуации управляет процессом с помощью посылки ему сигнала. Сигнал — это простейший способ межпроцессорного (то есть между процессами) взаимодействия. Существует несколько типов сигналов. Для каждого из типов предусмотрено действие по умолчанию. Процесс может воспользоваться действием по умолчанию, или, если у него есть обработчик сигнала, то он может перехватить и обработать или игнорировать сигнал. Сигналы SIGKILL и SIGSTOP невозможно ни перехватить, ни игнорировать.

По умолчанию возможны несколько действий:

игнорировать — продолжать работу, несмотря на то, что получен сигнал.

завершить — завершить работу процесса.

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

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

Вот список всех сигналов, существующих в системе на сегодняшний день:

Мастер Йода рекомендует:  Правильный файл robot.txt
Добавить комментарий