8

我经常听说使用system("PAUSE")是不好的做法,std::cin.get()而是使用。现在我对系统调用的理解是,它们将一个字符串输入系统命令行并与操作系统对话,因此 PAUSE 是一个 DOS 命令,可以暂停命令窗口中的输出。我认为这与具有不同关键字的 Mac 和 unix 类似,并且由于缺乏跨操作系统兼容性,不鼓励使用系统调用。(如果我有任何错误,请纠正我)

我的问题是:什么时候适合使用 system() 调用?它们应该如何应用?什么时候不应该应用它们?

4

6 回答 6

31

system("PAUSE")肯定不太理想。使用对系统的调用会创建一个子进程,这在 Windows 上是相当昂贵的,并且无论如何在任何操作系统上都不是非常便宜。在嵌入式系统上,内存开销很大。

如果有任何方法可以在本地没有太多痛苦的情况下做到这一点,那就去做吧。在等待用户按下单个按钮的情况下,cin.get() 将很难被击败。在这种情况下,您的应用程序进程只会在标准输入上阻塞,只设置几个对内核可见的标志,最重要的是,不会分配新内存,也不会创建新的调度实体,甚至不会创建中断处理程序。

此外,它在所有具有所有 c++ 编译器的操作系统上都可以正常工作,因为它仅使用该语言非常标准部分的一个非常基本的特性,而不依赖于操作系统提供的任何东西。

编辑:预测您担心它是否昂贵并不重要,因为整个想法是暂停。好吧,首先,如果它很贵,那么它会损害可能发生的其他任何事情的性能。有没有注意到(在 Windows 上)当一个应用程序启动时,其他已经打开的应用程序也变得不那么响应了?此外,您的用户可能不是一个活生生的人,而是另一个代表人类用户工作的程序(例如,一个 shell 脚本)。该脚本已经知道下一步该做什么,并且可以在标准输入中预先填充一个字符以跳过等待。如果您在此处使用了子进程,则脚本将经历(人类可察觉的)延迟。如果脚本这样做数百(或数亿!)次,则可能需要几秒钟才能运行的脚本现在需要几天或几年。

EDIT2:何时使用system():当您需要做另一个进程所做的事情时,您不能轻易做到。 system()并不总是最好的候选人,因为它做了两件有些限制的事情。首先,与子进程通信的唯一方法是通过命令行参数作为输入,返回值作为输出。第二个是父进程阻塞,直到子进程完成。这两个因素限制了系统可用的情况。

在 unixy 系统上,大多数子进程都会发生,fork因为它允许同一个程序作为两个单独的进程在同一个地方继续,一个作为另一个的子进程(除非你从操作系统请求它,否则几乎不会注意到它)。在 Linux 上,这特别优化,并且与创建 pthread 一样便宜。即使在速度不那么快的系统上,它仍然非常有用(如 apache 进程池方法所证明的那样)(在 windows/ unix 文档链接上不可用)

其他情况(在 Windows 上也是如此!)通常由函数popenexec函数族处理。 popen创建一个子进程和一个连接到子进程的标准输入或标准输出的全新管道。然后,父进程和子进程都可以同时运行并很容易地进行通信。(链接到 windows 文档/链接到 unix 文档

exec* 另一方面,函数族(有几个,execl,execv 等)会导致当前程序被新程序替换。原始程序不可见地退出,新进程接管。当新进程返回时,它将返回到任何所谓的原始进程,就好像该进程在那个时候已经返回而不是消失一样。这样做的好处exit(system("command"))是不会创建新进程,从而节省时间和内存(尽管并不总是非常多)(链接到 windows 文档/链接到 unix 文档

system某些脚本工具可以合理地使用它来调用某些配方操作中的几个步骤。例如,在某个时刻,程序可以使用system调用文本编辑器来编辑某些配置文件。它不需要太关心发生的事情,但它当然应该等到用户保存并关闭编辑器后再继续。然后它可以使用返回值来确定编辑会话是否成功,即编辑器实际上打开了请求的文件(并且编辑器本身根本存在!),但将从中读取会话的实际结果直接编辑文件,而不是与子进程通信。(链接到 windows 文档/链接到 unix 文档

于 2009-05-23T02:12:50.803 回答
3

系统调用被发送到操作系统的 shell 或命令行解释器(dos、bash 等),并由 shell 来执行它想要使用此命令执行的操作。

您将避免使用此类调用,因为它会降低您的程序与其他操作系统一起使用的可移植性。我认为只有当您绝对确定您的代码针对的是您应该使用此类调用的特定操作系统时。

于 2009-05-23T02:14:53.467 回答
3

但我的问题是:什么时候使用 system() 调用合适?它们应该如何应用?

当你不能用自己的代码或库做你想做的事情时(或者实现它的成本超过了启动一个新流程的成本)。与 cin.get() 相比,system() 在系统资源方面的成本相当高,因此只能在绝对必要时使用它。请记住,system() 通常会同时启动一个全新的 shell 以及您要求它运行的任何程序,因此会启动两个新的可执行文件。

于 2009-05-23T02:15:10.923 回答
3

顺便说一句,system()调用不应该与设置了SUIDSGID位的二进制文件一起使用,引用手册页

不要在具有 set-user-ID 或 set-group-ID 权限的程序中使用 system(),因为某些环境变量的奇怪值可能会被用来破坏系统完整性。请改用 exec(3) 系列函数,但不要使用 execlp(3) 或 execvp(3)。实际上,system() 在 /bin/sh 是 bash 版本 2 的系统上无法从具有 set-user-ID 或 set-group-ID 权限的程序正常工作,因为 bash 2 在启动时会放弃权限。

于 2012-11-06T09:09:49.673 回答
2

system()用于要求操作系统运行程序。

为什么您的程序希望操作系统运行程序?嗯,有案例。有时,外部程序或操作系统命令可以执行在您自己的程序中难以完成的任务。例如,外部程序可以使用提升的特权或访问适当的数据格式来运行。

system()函数本身是相当可移植的,但是您传递给它的命令字符串可能是非常特定于平台的——尽管可以从本地配置数据中提取命令字符串以使其与平台更加无关。

其他功能,如fork()、和 ,exec*()可以让您更好地控制运行外部程序的方式,但它们是特定于平台的,可能无法在您选择的平台上使用。spawn*()CreateProcess()

system("PAUSE")是一个古老的 DOS 技巧,现在通常被认为是相当怪诞的风格。

于 2009-05-23T08:18:59.590 回答
1

据我所知 system("PAUSE") 是一个只有 Windows 的东西,这就是为什么它不受欢迎。

于 2009-05-23T02:08:29.673 回答