为什么分叉的进程有时会在 ps 中的名称周围出现括号 []?

Ale*_*lex 6 linux process fork

在 Linux 系统上,一个 C 进程在启动时启动,这会创建一个自己的分支。这不是一个内核过程或其他东西。在大多数情况下,aps -ef将两个进程都显示为预期,但有时看起来如下所示:

1258 root       0:00 myproc 
1259 root       0:00 [myproc]
Run Code Online (Sandbox Code Playgroud)

即括号包围的进程之一。根据ps

If the arguments cannot be located (usually because it has not been set, 
as is the case of system processes and/or kernel threads) the command name 
is printed within square brackets.
Run Code Online (Sandbox Code Playgroud)

我不明白“无法​​找到参数”是什么意思。该过程始终以完全相同的方式启动,并且分支始终以完全相同的方式创建。怎么会发生有时“无法找到论点”而有时却能找到的情况?

此外,该过程始终在没有任何参数的情况下启动......

我的问题:

  • 这些括号的真正含义是什么?进程是否在/proc/{pid}/cmdline为空时运行?
  • 为什么我有时会得到这些括号而不是总是?
  • 如何/在哪里解决这个问题?

附加信息:

  • 该过程始终在没有任何参数的情况下启动!只是命令的名称myproc
  • 主进程似乎总是正确运行(名称周围没有括号,在 中可执行/proc/x/cmdline)。
  • 有时子进程的名称在括号中。
  • 的内容/proc/child-pid/cmdline正确运行的子进程是myproc
  • 的内容/proc/child-pid/cmdline不正确的运行的子进程是空的!
  • 再次:相同的代码,不同的子进程!

Sté*_*las 9

ps -f通常显示传递给execve()进程或其任何祖先执行的最后一个系统调用的参数列表。

当您xxx arg1 arg2在 shell 提示符下运行命令时,您的 shell 通常会派生一个进程,按xxx名称搜索命令并将其执行为:

execve("/path/to/that/xxx", ["xxx", "arg1", "arg2"], @exported_variables)
Run Code Online (Sandbox Code Playgroud)

应该注意的是,第一个参数在xxx那里。

执行后,进程的整个内存被擦除,这些参数(和环境)在进程堆栈的底部找到。

您将获得这些参数的前 4096 个字节,这/proc/<the-pid>/cmdline就是ps它的来源。

在分叉或克隆时,子级继承其父级的整个内存,包括该 arg 列表。

你得到[xxx]when/proc/<the-pid>/cmdline是空的。在这种情况下,不是显示 arg 列表,而是显示它在其中找到ps进程名称/proc/<the-pid>/stat(对于已执行的命令,这是传递给最后一个的可执行文件的基本名称的前 16 个字节execve())。这可能有以下三个原因(我能想到的):

  • 该进程或其任何祖先从未执行过任何操作。这就是内核线程的情况(并且只能是内核线程的情况,因为所有其他进程都是init(被执行)的后代)。

    $ ps -fp2
    UID        PID  PPID  C STIME TTY          TIME CMD
    root         2     0  0 Jan13 ?        00:00:00 [kthreadd]
    
    Run Code Online (Sandbox Code Playgroud)
  • 该进程执行了一个带有空参数列表的命令。这通常永远不会发生,因为程序通常总是至少传递一个参数,即命令名称,但您可以强制使用例如:

    int main(int argc, char *argv[]) {
      if (argc) execve("/proc/self/exe",0,0);
      else system("ps -fp $PPID");
    }
    
    Run Code Online (Sandbox Code Playgroud)

    编译并运行后:

    $ test1
    UID        PID  PPID  C STIME TTY          TIME CMD
    stephane 31932 29296  0 15:16 pts/5    00:00:00 [exe]
    
    Run Code Online (Sandbox Code Playgroud)
  • 该进程argv[]在其堆栈上覆盖它。

    参数是内存中以 NUL 结尾的字符串。例如,如果您将 arg 列表的最后一个字符设为非空envp[0][-1]=1envp[]值跟在argv[]堆栈中的后面),则内核假定您已经修改了它,并且只返回/proc/xxx/cmdline第一个参数直到第一个 NUL 字符。所以

    int main(int argc, char* argv[], char *envp[]) {
      envp[0][-1]=1;
      argv[0][0]=0;
      system("ps -fp $PPID");
    }
    
    Run Code Online (Sandbox Code Playgroud)

    也会显示[xxx]

    鉴于arglist(和environ)位于堆栈的底部,如果您的代码中有一个错误,使您在堆栈上写入超出了要编写的内容的末尾,则可能会发生这种情况,例如例如,如果使用strcpy代替strncpy. 调试这类问题,valgrind非常有用。