当C程序调用system()来运行Unix命令时,我知道可以将参数传递给命令,并根据StackOverflow答案(来自非常高代表的用户) call uses the shell to execute the command。
看到system("ls -lh >/dev/null 2>&1");作为C程序的system()调用示例,我感到惊讶,因为它使用的是与shell交互使用的相同空格分隔的“单词”。
从我作为系统管理员的角度来看,我想了解在我的系统上的一些文件或命令中从C程序中执行system()调用的条件和缺陷是什么。将包含空格的文件名传递到shell脚本中的是very issue-prone;C程序调用命令时是否存在类似的问题?
或者更直截了当地说:新手编写的C程序和shell脚本一样有可能破坏包含空格的文件名吗?
发布于 2016-01-27 08:49:38
在这里的C源代码中没有什么可做的,传递给system()的字符串是在shell上下文中运行的。shell将解析该字符串,而C程序则不解析。
如果你看看system() function prototype
#include <stdlib.h>
int system(const char *command);传递给system()的参数是一个字符串。它与字符串中的空格字符无关,它获取一个字符串并将该字符串传递给其他系统调用。和你一样:
sh -c 'ls -l'这里系统()使用execve()
$ cat <<\CODE | gcc -xc -
#include <stdlib.h>
int main(void) {
system("ls -l");
return 0;
}
CODE
$ strace -fe execve ./a.out
execve("./a.out", ["./a.out"], [/* 64 vars */]) = 0
Process 16281 attached
[pid 16281] execve("/bin/sh", ["sh", "-c", "ls -l"], [/* 64 vars */]) = 0
Process 16282 attached
[pid 16282] execve("/bin/ls", ["ls", "-l"], [/* 64 vars */]) = 0
...发布于 2016-01-27 10:05:56
是也不是。
system()函数是一个C库调用,它运行一个shell来启动另一个程序,并等待其结果。对于希望运行外部命令以检查是否满足某些外部条件这一共同需要来说,这是非常有用的。它确实使用shell启动外部命令。
不是系统呼叫。系统调用是对内核的直接请求;例如“给我更多的内存”、“打开文件”和“将这些东西写入文件描述符”。system()函数是根据(至少)三个系统调用来实现的:
fork(),以生成子进程。exec()家族中的一个,由子进程调用,以另一个可执行文件替换该子进程wait(),由父进程调用,等待子进程完成并读取其退出状态。exec()调用在不涉及任何shell的情况下启动进程,因此不会发生空格扩展。理论上,可以绕过system()函数,这样就不会出现空格问题。这是很多工作,但通常不值得,因为有更多的可能出错。
这就引出了我的观点:如果您担心新手处理shell脚本,就不应该让他们处理C编译器。在C中做的错误可能比在shell中做的多.
发布于 2016-01-28 13:35:39
如果一个C程序使用system()来调用另一个程序,它必须创建一个命令来由shell (特别是/bin/sh)解析。
system(const char *command)的实现通常会在子进程中调用类似于execl('/bin/sh', 'sh', '-c', command, (char*)NULL)的东西( execl库函数将最终调用execve系统调用)。
https://stackoverflow.com/questions/35063418
复制相似问题