为什么execve系统调用不带任何argv参数运行“/ bin / sh”,而不是“/ 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"replace"/bin/sh" "/bin/ls" ,则失败:

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

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

这不是内核问题,内核会运行execve的filename arg而不管argvenvp是否为NULL ,这只是argv[0]指向程序名的unix惯例。

你看到的是正常的,没有什么是错的。 由于ls是GNU的coreutils的一部分,并且coreutils包中的所有程序都调用set_program_name来做一些设置工作,所以在源代码中可以看到argv[0]是否为NULL,如果是NULL,则会调用abort 。 另一方面, /bin/sh显然是一个不属于coreutils的程序,不会检查argv[0] ,这就是为什么它没有问题。

参考源代码:

http://git.savannah.gnu.org/cgit/coreutils.git/tree/src/ls.c#n1285

http://git.savannah.gnu.org/cgit/gnulib.git/tree/lib/progname.c#n51