16

私が構築しているプロセス スキャナーのカーネル スレッドとユーザー スレッドを区別する方法を知りたいです。両方のタイプの適切な定義を見つけるのに苦労しています。

カーネルスレッドには独自のメモリがないため、/proc/$pid/status に Vm* 値がなく、/proc/$pid/exe の統計が何も返さないことがわかりました。

したがって、プロセスに Vm* 値と inode 番号がない場合、カーネル スレッドを識別できると考えました。私は間違っていると考えました...私のスクリプトは、いつかカーネルプロセスとして識別されるphp-cgiプロセスを認識します。

これらの誤って識別されたプロセスのほとんどが、1 秒後に消滅したゾンビであることが判明した場合。そこで、ステータスが「Z」かどうかを確認する簡単なチェックを実装しました。その場合は、無視してください。これにより、多くの誤検知を回避できましたが、それでも php-cgi カーネル プロセスに関するメッセージを受け取ります。

カーネルスレッドとユーザースレッドを正しく区別する方法を誰か教えてもらえますか?

4

4 に答える 4

13

カーネル スレッドとユーザー空間スレッドの間には、いくつかの目に見える違いがあります。

  • /proc/$pid/cmdlineカーネル スレッドの場合は空です。これは、カーネル スレッドで使用され、カーネル スレッドを区別するために使用される方法psですtop

  • シンボリック リンクにはカーネル スレッドの/proc/$pid/exeターゲットがありません。ファイル システムに対応する実行可能ファイルがないため、これは理にかなっています。

    より具体的には、readlink()システム コールはENOENT( "No such file or directory" ) を返し、リンク自体が存在するにもかかわらず、このプロセスの実行可能ファイルが存在しない (存在しなかった) ことを示します。

    したがって、カーネル スレッドを確認する信頼できる方法は、呼び出しreadlink()/proc/$pid/exeそのリターン コードを確認することです。成功した場合$pidは、ユーザー プロセスです。で失敗した場合ENOENTは、追加のstat()on/proc/$pid/exeによって、カーネル スレッドのケースと終了したばかりのプロセスを区別する必要があります。

  • /proc/$pid/statusほとんどのカーネル スレッドでいくつかのフィールドが欠落しています。具体的には、仮想メモリに関連するいくつかのフィールドが欠落しています。

于 2012-09-01T20:13:20.207 に答える
5

上記のコメントで指摘したように、すべてのユーザー プロセスは init プロセス (pid=1) の子孫です。init はユーザー プロセスであり、ユーザー プロセスはカーネル スレッドを作成できないため、カーネル スレッドは init プロセスの子孫ではありません。したがって、プロセス p がカーネル スレッドではなくユーザー プロセスであるかどうかを確認するには、プロセス グラフを操作し、init dom pdom がドミネーターオペレーターであるかどうかを評価する必要があります。具体的には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)
于 2012-12-21T04:21:12.770 に答える
1

以下は、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"

これは、少なくとも私にとっては最初の有用なソリューションでした。python バージョンの er0 に感謝します。

于 2016-06-10T21:57:51.870 に答える