Процессы и потоки в Linux
Процесс - это абстракция виртуализации
Ядро linux предоставляет каждому процессу, многозадачность, виртуализированный процессор, виртуальную память
Процессы - это объектный код, находящийся в процессе выполнения, который содержит в себе не только код, но и данные, ресурсы и виртуализированный процесс.
Объектный код, понятный для исполнения на машине и ядру ( наиболее распространенный в linux формат исполняемых и компонуемых файлов ELF ) или по другому исполняемый формат содержит метаданные и множество разделов с кодом и данными
Разделы - это линейные фрагменты объектного кода загружаемые в память, имеют одинкаковые права и цели исполнения
Самый важный раздел - текстовый и bss
В текстовом разделе содержатся исполняемый код и данные только для чтения, в том числе константы и переменные
В разделе данных хранятся инициализированные переменные, обычно данный раздел доступен для чтения и записи
Раздел bss содержит инициализированные глобальные данные
Кроме вышеизложенного процесс ассоциирован с различными ресурсами, которые выделяются и управляются ядром. Процессы запрашивают и манипулируют ресурсами посредством системных вызовов.
В качестве ресурсов процессора могут относиться таймеры, ожидающие сигналы, открытые файлы, сетевые соединения, аппаратное обеспечение, механизмы межпроцессорного взаимодействия
Ресурсы процессора, данные и статистика о нем сохраняются внутри ядра в дескрипторе процессора
Новый процессы в linux создаются с помощью системного вызова fork(). В результате этого вызова создается дубликат вызывающего процесса
Если родительский процесс завершается раньше дочернего, то ядро переназначает предка для потомка. После завершения процесса, он какое то время еще живет в системе, ядро сохряняет фрагменты процесса в памяти, обеспечивая процессу-предку доступ к информации. Такое запрашивание называется обслуживанием завершенного процесса.
Процесс, который уже завершился, но еще не был обслужен, называется зомби
Потоки
Каждый процесс состоит из одного или нескольких потоков выполнения
Поток - это еденица активности в процессе, отвечает за выполнение кода и поддержки процесса в рабочем состоянии
Процесс состоящий из нескольких потоков называется многопоточным
Поток состоит из стека в котором хранятся локальные переменные, состояния процесса и местоположения в объектном коде
Местоположение кода хранится в указателе команд процесса
Адресное пространство делится между всеми потоками
Нормальные процессы - это процессы переднего плана, у которых продолжительность жизни ограничивается сеансом, завершаются по истечении определенного времени или выходом пользователя, от которого был запущен процесс
Осиротевшие процессы - процессы, которые имели родительский процесс, но по какой то причине родительский процесс был завершен непринудительно и родителем осиротевших процессов стал init процесс. Процесс init будет ждать и завершения или остановки
Процессы демоны - независимые процессы которые намеренно сделаны осиротевшими и после инициации были отключены от контролирующего терминала(родителя), данные процессы работают в фоновом режиме, пока их задание не будет выполнено.
Процессы хранятся в /proc/ в виде директорий, в этих директориях хранятся данные о процессе
Например:
/proc/1/fd - хранит дескрипторы процесса 1 (init), которые в своем большинстве являются сетевыми соединениями или принадлежат каким то файлам
Удобнее просматривать дескрипторы процесса утилитой lsof, она выводит дополнительную информацию:
lsof -p 1
cwd - текущая директория процесса
rtd - директория процесса выше которой процесс подниматься не может
txt - бинарный файл
.so - разделяемая библиотека(в windows dll)
mem - адресное пространство процесса
/proc/
/proc/stat - общая информация о потреблении cpu процессами
Команда ps
Опции команды ps
l Вывод результата в длинном формате
u Вывод в пользовательском формате (показывает имя пользователя и время запуска)
j Вывод результата в рабочем формате (показывает идентификаторы GID и SID процесса)
s Вывод результата в сигнальном формате
v Вывод результата в vm -формате
m Отображает состояние памяти
f Использует для вывода forest -формат (показывает процессы в виде дерева)
a Показывает процессы других пользователей
x Показывает процессы, не отображая управляющий терминал
S Показывает дочерний CPU, а также время и страницу сбоев
c Название команды для task_struct
e Показывает состояние после командной строки и а+
w Выводит результат в расширенном формате
h Не выводит заголовок
r Показывает только запущенные процессы
n Показывает числовой вывод для USER и WCHAN
txx Показывает процессы, управляемые терминалом ttyxx
O Сортирует вывод процессов по ключам к1, к2 и т.д.
Pids Показывает только процессы с указанными PID
Расшифровка всех возможных кодов состояния процесса
D Непрерываемый, находящийся в ожидании
R Выполняется
S Ожидающий
T Отслеживается или остановлен
Z Нефункциональный процесс-"зомби"
W У процесса нет страниц в памяти (процесс свопирован)
< Процесс с высоким приоритетом
N Процесс с низким приоритетом
L Некоторые страницы оперативной памяти блокированы
Процессы заключенные в квадратные скобки - это которые вследствие низкой активности были перекачаны из памяти в пространство подкачки на жестком диске
top
Load Average (LA ) рассчитывается как среднее значение загрузки системы за определённый период времени. Как правило, это усреднённые величины за последние 1, 5 и 15 минут
Пример: load average: 0.08, 0.04, 0.05
LA высчитывается на основании процессов, которые выполняются и находятся в очереди на выполнение (CPU, RAM, I/O)
В многоядерной (многопроцессорной) системе значения Load Average (LA) рассчитываются пропорционально числу ядер
LA нужно сравнивать с количеством ядер процессора. LA = 2 на 2-ядерном процессоре — это высокая загрузка, а LA = 2 на 8-ядерном — вполне нормальная нагрузка.
Для четырёхядерной системы LA 15 не должен превышать 3,00, для двухядерной — 1,5, а для одноядерной — 0,75
В выводе утилиты top:
us - процессорное время потребляемое приложениями
sy - время потребляемое системой
ni - время потребляемое пользовательскими процессами с низким приоритетом
id - время в процентах которое не потребляется, этот показатель должен быть высоким
wa - время операций ввода вывода. Высокий показатель означает, что процессор очень долго ждет ответы от устройств ввода/вывода. Чаще всего это связано с большим количеством операций на диске.
hi si - время на обработку аппаратных и программных прерываний
st - время затраченное виртуальной машиной
Команды top
M — сортировка по используемой памяти
P — сортировка по нагрузке на процессор (используется по умолчанию)
T — сортировка по времени работы процесса
A — сортировка по максимальному потреблению различных ресурсов
u — сортировка по имени пользователя (потребуется ввести имя пользователя)
k — завершить процесс (потребуется указать его идентификатор, PID)
n — изменить количество процессов в выводе (потребуется указать нужное количество)
c — вывести полный путь запущенного процесса
Более подробно узнать о /proc можно с помощью команды man
man proc
strace
strace ls
Выводит цепочку выполнения работы приложения, информацию о процессе приложения, например какие библиотеки использовал процесс, настройки безопасности, вывод дескрипторов, системные вызовы и мн.др.
Второй вариант использования утилиты это подстановка номера процесса:
strace -p 1
Следующая опция -с команды покажет в реальном времени какие системные вызовы использует процесс
strace -c -p 1
Сигналы
Сигналы - это механизм, который обеспечивает односторонние асинхронные уведомления.
Сигнал может быть отправлен от ядра к процессу, от процесса к другому процессу, от процесса к самому себе
Сигнал может сообщать процессу о каком либо событии, например пользователь нажал ctrl+c или возникла ошибка сегментации памяти
Ядро linux реализует около 30 разновидностей сигналов, зависит от архитектуры продукта
Сигналы прерывают исполнение работающего процесса
Все сигналы за исключением SIGKILL и SIGSTOP, оставляют процессам выбор действий
Если сигнал не игнорируется, тогда происходит обработка сигнала обработчиком сигнала, после чего контроль переходит обратно инструкции, которая была прервана
CTRL+C = SIGINT и SIGQUIT
kill по умолчанию отправляет процессу сигнал SIGTERM, который как SIGINT или SIGQUIT могут быть перехвачены процессом и не дать нужного результата
Следующие две команды эквивалентны:
kill -9 2700
kill -KILL 2700
Но даже при явном указании сигнала ( в редких случаях ) процесс не исчезает. Такое возможно если процесс уже завершился, но все еще остается в системе, потому как его предок по какой то причине отказался затребовать у ОС подтверждение о завершении. Зомби убить нельзя, он уже мертвый, если только не убить его предка
Процесс зомби не потребляет ресурсы системы, но остается в таблице процессов
Другая причина. Процесс мог выполнить системный вызов ( обратился к ОС за определенной услугой ) в ходе выполнения которого система перевела процесс в состояние непрерывного сна. Если процесс не выходит из этого состояния, возможно есть проблемы с устройством, например испорченный диск и вывести процесс из такого состояния невозможно
Процесс зомби помечается буквой Z ( defunct )
Процесс состояния "Непрерывного сна" помечается буквой D ( badblocks )
Сигналы управления процессами
Доп. информация man signal
Список всех сигналов:
$ kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX
Лимит процессов
Выделение того или иного ресурса процесса может быть ограничено при достижении определенного значения(кол-во дескрипторов, кол-ва памяти и др.)
Лимит выделяется не конкретного процесса, а на все процессы пользователя
Какие лимиты существуют:
ulimit -a
Для управления лимитами существует файл /etc/security/limits.conf
В нем два вида лимита soft или hard мягкие и жесткие
Переменные окружения
/proc/pid/environ
Переменные окружения динамически изменяемый набор ключей и значений относящихся к конкретному процессу.
Если при написании приложении необходимо задействовать свою собственную библиотеку функций, можно использовать переменную окружения LD_PRElOAD чтобы указать путь к библиотеке и путь к запуску приложения. Сначала будет загружена библиотека, затем приложение
Еще одна важная системная переменная LD_LIBRARY_PATH
Задать переменную окружения export FOO=....
Лимит PID
Остановить зомби апокалипсис
pstack
Отследить действия процесса, если он не делает системных вызовов, но потребляет ресурсы можно с помощью утилиты pstack
pstack
Альтернатива gdb. Есть возможность установить дополнительную библиотеку для отладки glibc-debuginfo
perf
Утилита ipcs
ipcs -m - используется для просмотра текущих сегментов памяти с совместным доступом
pidof
Возвращает идентификатор процесса (pid) по его имени
pstree
Вывод исполняющихся процессов в виде дерева
jobs
jobs - выводит список заданий, исполняющихся в фоне, однако команда ps более информативна
Такие команды как kill, disown, wait принимают в качестве параметра номер процесса или номер задания
Команды fg, bg, jobs принимают в качестве параметра, только номер задания
~$ sleep 100 &
[1] 4848
~$ jobs
[1]+ Запущен sleep 100 &
disown 4848
[1] - номер задания
4848 - номер процесса
disown - удаляет задание из таблицы активных заданий командной оболочки
fg - переводит задания из фона в консоль
bg перезапускает приостановленное задание в фоновом режиме
Источники
Связанные темы
Структура каталогов linux(Debian)
Поиск уязвимостей и следов взлома в Linux
Сценарий инициализации в Linux
Оптимизация производительности
Сброс пароля root в grub (Linux)
Оптимизация производительности Postgresql
Сценарии инициализации в Linux Ubuntu