进一步阅读

进一步阅读

概括

mirage一个以 shebang 开头的 python 程序为例:

#!/usr/bin/python
...

看着/proc/<pid>/comm或使用pgrep,它看起来像......

...当我通过 shebang 调用它时,进程名称是“mirage”:

/usr/bin/mirage &

...但是当我显式调用 python 时是“python”:

/usr/bin/python /usr/bin/mirage &
  • 我知道进程可以更改自己的名称,但为什么两种情况下的名称不同?
  • 是否有一种通用方法可以了解流程最初是如何启动的(仅使用/procgrep信息)?

详情-舍邦

/home/martin> /usr/bin/mirage &
[1] 22638

/proc/<pid>/comm说这是“海市蜃楼”

/home/martin> cat /proc/22638/comm 
mirage

程序包发现它是“mirage”,但不是“python”

/home/martin> pgrep -al mirage && echo "found" || echo "not found"
22638 /usr/bin/python /usr/bin/mirage
found

/home/martin> pgrep -al python && echo "found" || echo "not found"
not found

详细信息 - python

/home/martin> /usr/bin/python /usr/bin/mirage &
[1] 21348

/proc/<pid>/comm说它是“蟒蛇”

/home/martin> cat /proc/21348/comm 
python

程序包发现它是“python”,但不是“mirage”

/home/martin> pgrep -al mirage && echo "found" || echo "not found"
not found

/home/martin> pgrep -al python && echo "found" || echo "not found"
21348 /usr/bin/python /usr/bin/mirage
found

答案1

进程名称源自argv[0]调用execv()

这解释了您观察到的行为。

事实上,在 shebang 情况下,内核重新排列事物的调用方式不会影响向量argv

答案2

我知道进程可以更改自己的名称,但为什么两种情况下的名称不同?

因为涉及到的程序有不是改变自己的名字。它们被赋予 Linux 默认行为分配的名称。 (其他操作系统的行为有所不同,但这是一个 Linux 问题,因为它讨论的是/proc/*/comm文件。)

在 Linux 上,程序名称comm取自任何程序映像文件名称传递给execve()was。请注意,这不是参数向量或环境向量,并且该名称取自 Linux 上的参数向量的说法是错误的。

shell 实际传递的程序映像文件名是/usr/bin/python/usr/bin/mirage,因此pythonmirage/proc/self/comm初始化的内容。 (comm是程序图像文件名的基本名称,已截断/填充。)

参数向量初始化进程在其中的内容/proc/self/cmdline,环境向量初始化其在中的内容/proc/self/environ。因此,有了这些 和/proc/self/comm,并假设程序在运行时不会改变它们,您就知道传递给的所有三个信息execve(),因此确切地知道“进程最初是如何启动的”(尽管严格来说,这是如何该程序已推出,如过程与 ) 一起启动fork()

下面是这三个部分的实际操作示例,使用nosh 工具集中的clearenvsetenvexec 来设置一个小环境和力argv[0]以进行说明:

%clearenv setenv 1THIS '是环境字符串' setenv 2COMPRISING '所有环境。 \
> exec -a '这是 argv[0]。' /bin/sleep 100 &
[1]15564
% for i in /proc/$\!/{comm,cmdline,environ} ;执行 printf "%s:" $i ;猫 -v $i ; printf "\n" ;完毕
/proc/15564/通讯:3

/proc/15564/cmdline:这是argv[0].^@100^@
/proc/15564/environ:1THIS=环境字符串^@2COMPRISING=所有环境。^@
%

事实上,这些正是 nosh 工具集的exec命令传递给execve()运行的命令/bin/sleep。 (这3是因为exec使用了 C 库的fexecve()函数,该函数在内部使用 形式的程序映像文件名/proc/self/fd/3。)

程序映像文件恰好是一个带有命名解释器和#!幻数的脚本,导致该解释器替换程序映像文件并移动参数向量,没有改变什么进入comm.它保留最初赋予的任何程序映像文件名execve()。是的,Linux 在这里是不一致的,因为它将这种情况下的内容更改cmdline为有效的最终参数字符串。

进一步阅读

相关内容