Identifying kernel threads

后端 未结 4 1023
心在旅途
心在旅途 2021-01-04 03:50

I\'d like to know how I can distinguish a kernel-thread from a user-thread for a process-scanner I\'m building. I\'m having a hard time finding a good definition of both typ

相关标签:
4条回答
  • 2021-01-04 04:14

    You can read thread flags value from /proc/[pid]/stat (see proc(5) manpage) and check if it has PF_KTHREAD bit flag set.

    PF_KTHREAD constant itself has been available since 2.6.17, which is roughly for 10 years, and it's value hasn't changed since then:

    #define PF_KTHREAD      0x00200000  /* I am a kernel thread */
    

    Even through the header file containing this constant (include/linux/sched.h) is not exported to userspace, having a copy of this definition in your source code combined with kernel version check done from userspace at runtime (e.g. using uname(2) system call) should be pretty robust.

    0 讨论(0)
  • 2021-01-04 04:15

    As you pointed out in your own comment above, all user processes are descendants of the init process (pid=1). Kernel threads are not descendants of the init process, since init is a user process, and user processes cannot create kernel threads. Therefore, to check if process p is a user process and not a kernel thread, one needs to operate on the process graph and evaluate if init dom p where dom is the Dominator operator. Concretely in 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)
    
    0 讨论(0)
  • 2021-01-04 04:23

    Here is a version that works under 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
    }
    

    To use it do

    ~$ is_user_process `pgrep kthreadd` || echo "kthreadd is kernel process"
    

    This was first useful solution for me at least, thanks for er0 of the python version.

    0 讨论(0)
  • 2021-01-04 04:32

    There are some visible differences between a kernel thread and a user-space thread:

    • /proc/$pid/cmdline is empty for kernel threads - this is the method used by ps and top to distinguish kernel threads.

    • The /proc/$pid/exe symbolic link has no target for kernel threads - which makes sense since they do not have a corresponding executable on the filesystem.

      More specifically, the readlink() system call returns ENOENT ("No such file or directory"), despite the fact that the link itself exists, to denote the fact that the executable for this process does not exist (and never did).

      Therefore, a reliable way to check for kernel threads should be to call readlink() on /proc/$pid/exe and check its return code. If it succeeds then $pid is a user process. If it fails with ENOENT, then an extra stat() on /proc/$pid/exe should tell apart the case of a kernel thread from a process that has just terminated.

    • /proc/$pid/status is missing several fields for most kernel threads - more specifically a few fields related to virtual memory.

    0 讨论(0)
提交回复
热议问题