结论

结论

我最近了解到pidof,并将其与 进行比较pgrep。在执行此操作时,我注意到pidofFirefox 返回了多个 PID,而pgrep仅返回了一个。

我检查了pgrep的手册页并尝试了它的切换,并得到了预期的输出-f

   -f, --full
          The pattern is normally only matched against the process name.  
          When -f is set, the full command line is used.

现在,我知道如何ps区分命令的完整路径、“简单”命令名称(如basename完整路径)和完整的命令名称args,但我从未听说过进程名称。

在下面的例子中,所有其他进程都是 的子进程4661,所以我猜测 Firefox 将它们分叉以利用多处理。

那么问题来了:

  • 什么是进程名称?
  • 流程如何以及为何设置它们?

看着这些 帖子,似乎它可能或可能不会通过更改argv[0]或调用来完成prctl(PR_SET_NAME),并且它仅用于帮助调试,识别哪个子进程正在做什么(或者有时,欺骗用户认为进程是其他东西)。

是这样吗?或者进程名称是除了 之外的东西吗argv

$ pidof firefox
5495 5463 5391 5384 5380 5351 5330 5311 5239 5184 4661
$ pgrep firefox
4661
$ pgrep -f firefox
4661
5184
5239
5311
5330
5351
5380
5384
5391
5463
5495
$ pgrep -fl firefox
4661 firefox
5184 Web Content
5239 Web Content
5311 Web Content
5330 Web Content
5351 Web Content
5380 Web Content
5384 Web Content
5391 Web Content
5463 Privileged Cont
5495 WebExtensions
$ 

答案1

大多数exec函数至少接收两个参数,其中第一个是可执行文件的路径,第二个是参数列表。该列表包括argv[0],因此程序员始终可以选择更改它。就是这样bash 为了exec -a new_name。因此,进程的父进程可以定义,argv[0]同时仍然指向预期的可执行文件。

Firefox,从最初的问题开始,将进程名称更改为呼叫 prctl (PR_SET_NAME,...)。根据prctl(2),它设置线程的名称:

该属性与可以通过 pthread_setname_np(3) 设置并使用 pthread_getname_np(3) 检索的属性相同。该属性同样可以通过 /proc/self/task/[tid]/comm 访问(请参阅 proc(5)),其中 [tid] 是调用线程的线程 ID,由 gettid(2) 返回。

至于这样做的原因,代码有以下评论:

// Update the process name so about:memory's process names are more obvious.

man 5 proc在这里非常有帮助:对于cmdline,它解释了程序可以通过几种方式更改它,并将文件定义为 '将此文件视为该进程希望您看到的命令行'。 comm被定义为'与进程关联的命令名称',它还解释了如何更改它。

因此,至少有两种“更改进程名称”的方法,每种方法都会使pidofpgrep(实际上是其他工具)以不同的方式工作:

  • 该方法在流程开始时或之后argv[0]更改流程,并影响argv/proc/PID/cmdline
  • 实际上prctl (PR_SET_NAME,...)更改了进程主线程的名称,并且影响了/proc/PID/comm/proc/PID/task/PID/comm
什么 argv[0] prctl (PR_SET_NAME,...)
pidof 原创和全新 仅限原创
pgrep 仅限原创 仅限新品
pgrep -f 仅限新品 仅限原创
ps -o comm 原来的 新的
ps -o cmd 新的 原来的

pidofpstop显然pgrep都在procps-ng项目。

pidof 检查和实际二进制文件cmdline的链接/proc/PID/exe,因此它适用于该argv[0]方法的原始方法和新方法,但仅适用于其他方法的原始方法。

结论

pgrep手册页的内容进程名称/proc/PID/comm。这不一定与argv[0]存储在 上的名称相同/proc/PID/cmdline,并且这两个名称都可以通过多种方式独立更改。

显然,该功能的主要用途是调试和易于维护。

相关内容