我读过有关系统调用的文章,我怀疑是否有任何命令在不进行任何系统调用的情况下运行。如果没有,那么系统调用次数最少的命令是什么?我使用了strace
一些命令,但它给出了一个很长的列表。有人能告诉我这样的命令吗?
答案1
/bin/true
并且/bin/false
应该是系统调用最少的预装命令。
您可以通过静态链接节省一些系统调用:
将以下内容保存为例如minimal.c
int main() {
return 0;
}
并使用编译
gcc --static -o minimal minimal.c
minimal
这将使您获得当前工作文件夹中的程序。
答案2
说到为了“运行”(因此“运行”的含义比您可能指的含义更广泛)程序实际执行了哪些系统调用,不是:首先,系统execve()
调用总是为了运行命令(在这种情况下,我认为我们最好谈论可执行文件)本身而执行,并且exit()
系统调用总是在main()
返回时执行:
C 编译器在 main() 返回后调用 exit()
(来源)
为了以某种方式解决您的问题,该问题依赖于可执行文件,因此非常广泛:作为概念证明,表明任何实际有用的可执行文件都将使用至少一个系统调用,值得说明的是,首先,如果出现错误,很可能从程序本身执行系统调用;更不用说任何打开/关闭文件描述符的可执行文件都会使用/系统exit()
调用。open()
close()
最后,任何实际有用的命令很可能至少有一个系统调用(例如,exit()
如果程序在执行过程中遇到错误和/或open()
如果close()
命令必须读取文件)。
答案3
是的。有一些命令无需进行任何系统调用即可运行。
此类命令的一个先决条件是它们内置于 shell 中(bash
对于我的系统,是 )。这既消除了设置开销(链接器和 libc 执行的大量系统调用,用于设置代码运行的环境)也消除了最终的 exit() 调用。
strace
但这无法帮助您识别这些命令,因为它们不是实际的程序。没有与内置命令相对应的文件,因此如果strace
做找到命令,它将是一个外部版本,包含任何过程所需的设置和拆卸。
该bash
命令help
列出了所有可用的内部命令。请注意,其中许多命令也会进行系统调用。有些命令不使用系统调用:
function
for
declare
true
(内置版本;不是/bin/true
)false
(内置版本;不是/bin/false
)shift
set
case
alias
/unalias
set
/unset
一般来说...如果一个命令是 shell 内部的,不读取输入,不写入输出,并且只使用内存中的变量,那么它可能不使用系统调用。
答案4
如果不进行任何系统调用,程序就无法完成很多有意义的工作。系统调用是程序与程序本身之外的任何事物进行通信的主要方法。
通过内存映射文件或共享内存进行通信是可行的,但首先仍需要系统调用进行设置。之后,无需进一步的系统调用即可进行通信。
程序可以通过信号从外部接收信息。但是,如果没有安装信号处理程序,信号只会终止程序,而安装信号处理程序首先需要系统调用。原则上,程序在处理接收信号结束时也需要进行系统调用,但如果信号设置为在接收时不阻止信号,那么无需系统调用即可离开信号处理程序。这更多的是一种好奇心,而不是一种具有实际应用的有意义的技术。
不进行任何系统调用的程序将消耗其所能获得的所有 CPU 时间,因为睡眠(在大多数情况下)需要系统调用。程序可以处于睡眠状态,因为它正在等待从磁盘加载映射页面。但如果没有系统调用,唯一要加载的映射页面将是可执行文件本身,它很快就会被缓存。
在运行程序时,可以通过修改自己的命令行或环境变量使部分结果对其他程序可见。这些都可以在不进行系统调用的情况下进行修改。
即使程序正常终止也需要系统调用。但程序可以触发信号终止,而无需系统调用。可能触发的信号包括 SIGILL、SIGBUS、SIGFPE、SIGSEGV。
考虑到所有这些,可以编写一个程序,该程序在启动时会对命令行提供的值进行一些计算,并最终根据计算结果通过不同的信号终止。这不是指示计算结果的最有用方法,但肯定是可行的。