windows C++ 中的 System() 调用及其在编程中的作用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/900666/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
System() calls in C++ and their roles in programming
提问by Gordon Gustafson
I've often heard that using system("PAUSE")
is bad practice and to use std::cin.get()
instead. Now my understanding of system calls is that they take a string which they enter into a system command line and talk with the OS, so PAUSE is a DOS command that pauses the output in the command window. I assume this works similarly with Mac and unix with different keywords, and using system calls is discouraged because of a lack of cross OS compatibility. (If I'm wrong with any of this, please correct me)
我经常听说使用system("PAUSE")
是不好的做法,std::cin.get()
而是使用它。现在我对系统调用的理解是,它们将一个字符串输入到系统命令行并与操作系统对话,因此 PAUSE 是一个 DOS 命令,可以在命令窗口中暂停输出。我认为这与使用不同关键字的 Mac 和 unix 类似,并且由于缺乏跨操作系统兼容性,不鼓励使用系统调用。(如果我有任何错误,请纠正我)
my question is this: When is it appropriate to use system() calls? How should they be applied? When should they NOT be applied?
我的问题是:什么时候使用 system() 调用合适?它们应该如何应用?什么时候不应该应用它们?
回答by SingleNegationElimination
system("PAUSE")
is certainly less than ideal. using a call to system creates a subprocess, which on windows is fairly expensive and in any case not terribly cheap on any operating system. On embedded systems the memory overhead is significant.
system("PAUSE")
肯定不太理想。使用对 system 的调用会创建一个子进程,这在 Windows 上相当昂贵,而且在任何操作系统上都不是非常便宜。在嵌入式系统上,内存开销很大。
If there is any way to do it without much pain natively then do it. In the case of waiting for the user to press a single button, cin.get() will be very hard to beat. In this case, your applications process will just block on stdin, setting only a few flags visible to the kernel, and most importantly, allocates no new memory and creates no new scheduling entities, not even an interrupt handler.
如果有任何方法可以在本机没有太多痛苦的情况下做到这一点,那么就去做吧。在等待用户按下单个按钮的情况下,cin.get() 将很难被击败。在这种情况下,您的应用程序进程将只在 stdin 上阻塞,只设置几个内核可见的标志,最重要的是,不分配新内存,不创建新的调度实体,甚至不创建中断处理程序。
Additionally, it will work the same on all operating systems with all c++ compilers, since it uses only a very basic feature of a very standard part of the language, rather than depend on anything the OS provides.
此外,它在所有带有所有 c++ 编译器的操作系统上都可以正常工作,因为它只使用语言非常标准部分的一个非常基本的特性,而不是依赖于操作系统提供的任何东西。
EDIT: predicting your concern that it doesn't matter if it's expensive because the whole ideais to pause. Well, first off, if its expensive, then it's going to hurt performance for anything else that might be going on. Ever notice (on windows) when one application is launching, other, already open apps become less responsive too? Additionally, your user might not be a live human, but rather another program working on behalf of a human user (Say, a shell script). The script already knows what to do next and can pre-fill stdin with a character to skip over the wait. If you have used a subprocess here, the script will experience a (noticeable to a human) delay. If the script is doing this hundreds (or hundreds of millions!) of times, a script that could take seconds to run now takes days or years.
编辑:预测您的担忧,它是否昂贵并不重要,因为整个想法是暂停。好吧,首先,如果它很昂贵,那么它会损害可能发生的任何其他事情的性能。有没有注意到(在 Windows 上)当一个应用程序启动时,其他已经打开的应用程序响应速度也变慢了?此外,您的用户可能不是活生生的人,而是代表人类用户工作的另一个程序(例如,一个 shell 脚本)。脚本已经知道下一步要做什么,并且可以用字符预填充 stdin 以跳过等待。如果您在此处使用了子流程,则脚本将经历(对人类而言很明显)延迟。如果脚本执行此操作数百(或数亿!)次,则可能需要几秒钟才能运行的脚本现在需要数天或数年。
EDIT2: when to use system()
: when you need to do something that another process does, that you can't do easily. system()
isn't always the best candidate because it does two things that are somewhat limiting. First, the only way to communicate with the subprocess is by command line arguments as input and return value as output. The second is that the parent process blocks until the child process has completed. These two factors limit the cases in which system is useable.
EDIT2:何时使用system()
:当您需要做其他进程所做的事情时,您无法轻松完成。 system()
并不总是最好的候选者,因为它做了两件有点限制的事情。首先,与子进程通信的唯一方法是通过命令行参数作为输入和返回值作为输出。第二个是父进程阻塞,直到子进程完成。这两个因素限制了系统可用的情况。
on unixy systems, most subprocesses happen with fork
because it allows the same program to continue in the same place as two separate processes, one as a child of the other (which is hardly noticeable unless you ask for it from the OS). On Linux, this is especially well optimized, and about as cheap as creating a pthread. Even on systems where this is not as fast, it is still very useful (as demonstrated by the apache process-pool methodology) (unavailable on windows/link to unix docs)
在 unixy 系统上,大多数子进程都会发生,fork
因为它允许同一个程序作为两个单独的进程在同一位置继续运行,一个作为另一个进程的子进程(除非您从操作系统要求它,否则几乎不会引起注意)。在 Linux 上,这是特别好的优化,并且与创建 pthread 一样便宜。即使在速度不那么快的系统上,它仍然非常有用(如 apache 进程池方法所证明的那样)(在 windows 上不可用/链接到 unix 文档)
other cases (on windows too!) are often handled by popen
or exec
family of functions. popen
creates a subprocess and a brand new pipe connecting to the subprocesses' stdin or stdout. Both parent and child processes can then run concurrently and communicate quite easily. (link to windows docs/link to unix docs)
其他情况(在 Windows 上也是如此!)通常由函数popen
或exec
函数系列处理。 popen
创建一个子进程和一个连接到子进程的标准输入或标准输出的全新管道。然后父进程和子进程可以同时运行并且很容易地进行通信。(链接到 Windows 文档/链接到 unix 文档)
exec
* family of functions (there are several, execl, execv and so on) on the other hand causes the current program to be replaced by the new program. The original program exits invisibly and the new process takes over. When then new process returns, it will return to whatever called the original process, as if that process had returned at that point instead of vanishing. The advantage of this over exit(system("command"))
is that no new process is created, saving time and memory (though not always terribly much) (link to windows docs/link to unix docs)
exec
* 函数族(有几个,execl,execv 等等)另一方面会导致当前程序被新程序替换。原程序隐形退出,新进程接管。当新进程返回时,它将返回到任何称为原始进程的进程,就好像该进程在那时返回而不是消失一样。这样做的好处exit(system("command"))
是没有创建新进程,节省时间和内存(虽然并不总是非常多)(链接到 windows 文档/链接到 unix 文档)
system
could plausibly be used by some scripted tool to invoke several steps in some recipe action. For example, at a certain point, a program could use system
to invoke a text editor to edit some configuration file. It need not concern itself too much with what happens, but it should certainly wait until the user has saved and closed the editor before continuing. It can then use the return value to find out if the editing session was successful, in the sense that the editor actually opened the requested file (and that the editor itself existed at all!), but will read the actual results of the session from the edited file directly, rather than communicating with the subprocess. (link to windows docs/link to unix docs)
system
一些脚本工具可能会使用它来调用某些配方操作中的几个步骤。例如,在某个时刻,程序可以system
调用文本编辑器来编辑某个配置文件。它不需要太关心会发生什么,但它肯定应该等到用户保存并关闭编辑器再继续。然后它可以使用返回值来确定编辑会话是否成功,从某种意义上说,编辑器实际上打开了请求的文件(并且编辑器本身根本存在!),但将从中读取会话的实际结果直接编辑编辑的文件,而不是与子进程通信。(链接到 Windows 文档/链接到 unix 文档)
回答by Prashast
System calls are sent to the shell or command line interpreter of the OS (dos, bash, etc) and its up to the shell to do what it wants with this command.
系统调用被发送到操作系统的外壳程序或命令行解释器(dos、bash 等),并由外壳程序使用此命令执行它想要的操作。
You would avoid using these kind of calls as it would reduce your programs portability to work with other operating systems. I would think only when you are absolutely sure that your code is targeting a specific OS that you should use such calls.
您将避免使用这些类型的调用,因为它会降低您的程序与其他操作系统一起工作的可移植性。我认为只有当您绝对确定您的代码针对特定操作系统时,您才应该使用此类调用。
回答by Jherico
But my question is this: When is it appropriate to use system() calls? How should they be applied?
但我的问题是:什么时候使用 system() 调用合适?它们应该如何应用?
When you can't do the thing you're trying to do with your own code or a library (or the cost of implementing it outweighs the cost of launching a new process to do so). system() is pretty costly in terms of system resources compared to cin.get(), and as such it should only be used when absolutely necessary. Remember that system() typically launches both an entire new shell and whatever program you asked it to run, so thats two new executables being launched.
当你不能用自己的代码或库做你想做的事情时(或者实现它的成本超过启动新流程的成本)。与 cin.get() 相比,system() 在系统资源方面的成本非常高,因此它应该只在绝对必要时使用。请记住,system() 通常会同时启动一个全新的 shell 和您要求它运行的任何程序,因此会启动两个新的可执行文件。
回答by dk1844
By the way, system()call should never be used with binaries with SUIDor SGIDbit set, quoting from the man page:
顺便说一下,system()调用永远不应该与设置了SUID或SGID位的二进制文件一起使用,引用自手册页:
Do not use system() from a program with set-user-ID or set-group-ID privileges, because strange values for some environment variables might be used to subvert system integrity. Use the exec(3) family of functions instead, but not execlp(3) or execvp(3). system() will not, in fact, work properly from programs with set-user-ID or set-group-ID privileges on systems on which /bin/sh is bash version 2, since bash 2 drops privileges on startup.
不要在具有 set-user-ID 或 set-group-ID 权限的程序中使用 system(),因为某些环境变量的奇怪值可能会被用来破坏系统完整性。请改用 exec(3) 系列函数,但不要使用 execlp(3) 或 execvp(3)。事实上,system() 将无法从具有 set-user-ID 或 set-group-ID 权限的程序在 /bin/sh 是 bash 版本 2 的系统上正常工作,因为 bash 2 在启动时删除权限。
回答by Deinumite
As far as i know system("PAUSE") is a windows only thing, and that is why it is frowned upon.
据我所知 system("PAUSE") 是 Windows 唯一的东西,这就是为什么它不受欢迎。
回答by Michael J
system()
is used to ask the operating system to run a program.
system()
用于要求操作系统运行程序。
Why would your program want the operating system to run a program? Well there are cases. Sometimes an external program or operating system command can perform a task that is hard to do in your own program. For example, an external program may operate with elevated privileges or access propriety data formats.
为什么您的程序要操作系统运行程序?嗯,有案例。有时,外部程序或操作系统命令可以执行在您自己的程序中难以完成的任务。例如,外部程序可能以提升的权限运行或访问专有数据格式。
The system()
function, itself, is fairly portable but the command string you pass it is likely to be very platform-specific -- though the command string can be pulled from local configuration data to make it more platform-agnostic.
该system()
函数本身是相当可移植的,但是您传递给它的命令字符串可能是特定于平台的——尽管可以从本地配置数据中提取命令字符串以使其与平台更加无关。
Other functions like fork()
, exec*()
, spawn*()
and CreateProcess()
will give you much more control over the way you run the external program, but are platform-specific and may not be available on your platform of choice.
其他功能,如fork()
, exec*()
,spawn*()
和CreateProcess()
将使您对运行外部程序的方式有更多的控制,但特定于平台,可能在您选择的平台上不可用。
system("PAUSE")
is an old DOS trick and is generally considered to be fairly grotty style these days.
system("PAUSE")
是一个古老的 DOS 技巧,现在通常被认为是相当糟糕的风格。