Идентификация потоков ядра
Я хотел бы знать, как я могу отличить поток ядра от пользовательского потока для процесса-сканера, который я создаю. Мне трудно найти хорошее определение обоих типов.
Я обнаружил, что потоки ядра не имеют собственной памяти, поэтому значения Vm * в /proc/ $pid/status отсутствуют, а stat on/proc/$pid/exe ничего не возвращает.
Итак, я решил, что могу идентифицировать потоки ядра, если процесс не имеет значений Vm * и не имеет номера inode. Я ошибался... мой script видит процессы php-cgi, которые когда-то идентифицируются как процессы ядра.
Если окажется, что большинство из этих неправильно идентифицированных процессов - это зомби, которые ушли через секунду. Поэтому я выполнил простую проверку, чтобы узнать, является ли статус "Z". Если это так, игнорируйте его.
Это избавило меня от множества ложных срабатываний, но все же я получаю сообщения о процессах ядра php-cgi.
Может ли кто-нибудь сказать мне, как я могу отличить поток ядра от пользовательского потока правильно?
Ответы
Ответ 1
Есть некоторые видимые различия между потоком ядра и потоком пользовательского пространства:
-
/proc/$pid/cmdline
пуст для потоков ядра - это метод, используемый ps
и top
для различения потоков ядра.
-
Символьная ссылка /proc/$pid/exe
не имеет цели для потоков ядра - это имеет смысл, поскольку у них нет соответствующего исполняемого файла в файловой системе.
В частности, системный вызов readlink()
возвращает ENOENT
( "Нет такого файла или каталога" ), несмотря на то, что сама ссылка существует, чтобы обозначить тот факт, что исполняемый файл для этого процесса не существует (и никогда не был).
Поэтому надежным способом проверки потоков ядра должно быть вызов readlink()
на /proc/$pid/exe
и проверка его кода возврата. Если это удается, то $pid
является пользовательским процессом. Если с ENOENT
он терпит неудачу, дополнительный stat()
на /proc/$pid/exe
должен отличать случай от потока ядра от только что завершившегося процесса.
-
/proc/$pid/status
отсутствует несколько полей для большинства потоков ядра - более конкретно несколько полей, связанных с виртуальной памятью.
Ответ 2
Как вы указали в своем собственном комментарии выше, все пользовательские процессы являются потомками процесса init (pid = 1). Нити ядра не являются потомками процесса init, поскольку init - это пользовательский процесс, и пользовательские процессы не могут создавать потоки ядра. Поэтому, чтобы проверить, является ли процесс p пользовательским процессом, а не потоком ядра, нужно работать на графике процесса и оценить, если init dom p
где dom является Dominator. Конкретно в Python:
def is_user_process(p):
if (p=='1'):
print 'User process'
else:
pstat = open('/proc/%s/stat'%p).read().split()
parent = pstat[3]
if (parent=='1'):
print 'User process'
elif (parent=='0'):
print 'Kernel thread'
else:
is_user_process(parent)
Ответ 3
Вот версия, которая работает под bash:
# check if pid is user process and not a kernel thread
is_user_process() {
if [[ $1 -eq 1 ]]; then
return 0
else
parent=$(grep -e '^PPid:' /proc/$1/status | cut -c6-)
if [[ $parent -eq 1 ]]; then
return 0
elif [[ $parent -eq 0 ]]; then
return 1
else
is_user_process $parent
fi
fi
}
Чтобы использовать его,
~$ is_user_process `pgrep kthreadd` || echo "kthreadd is kernel process"
Это было первое полезное решение для меня, по крайней мере, спасибо за er0 версии python.