为什么 execve 系统可以在没有任何 argv 参数的情况下调用 运行“/bin/sh”,但不能调用“/bin/ls”?

Why can the execve system call run "/bin/sh" without any argv arguments, but not "/bin/ls"?

我对 __NR_execve 的系统调用感到困惑。当我学习linux系统调用时。我知道使用 execve 的正确方法是这样的:

char *sc[2]; 
sc[0]="/bin/sh"; 
sc[1]= NULL; 
execve(sc[0],sc,NULL); 

然后函数 execve 将调用 syscall() 进入系统内核,并将参数放在寄存器 EAXEBXECXEDX。但是,如果我使用

它仍然会成功
execve("/bin/sh",NULL,NULL);

但是如果我用"/bin/ls"替换"/bin/sh",它会失败:

A NULL argv[0] was passed through an exec system call.

我想知道为什么"/bin/sh"没有足够的参数可以执行成功而"/bin/ls"执行失败?

这不是内核问题。内核将 运行 与 execvefilename arg 无关,无论 argvenvp 是否为 NULLargv[0] 指向程序名只是 Unix 约定。

而你所看到的是正常的,即没有任何问题。因为 ls 是 GNU 的 coreutils 的一部分,并且 coreutils 包中的所有程序都调用 set_program_name 来做一些设置工作。您可以在源代码中看到这一点:它检查 argv[0] 是否为 NULL,如果为 NULL,它将调用 abort

另一方面,/bin/sh 显然是一个不属于 coreutils 的程序,并且不检查 argv[0]。这就是 运行 没有问题的原因。

参考源码: