33

如何运行外部程序并使用 C 传递命令行参数?如果您必须使用操作系统 API,请提供适用于 Windows、Mac 和 Linux 的解决方案。

4

8 回答 8

25

这真的取决于你想要做什么,确切地说,因为它是:

  1. 取决于操作系统
  2. 不太清楚你想做什么。

不过,我会尽力提供一些信息供您决定。
在 UNIX 上,fork()从调用 fork 的位置创建进程的克隆。意思是,如果我有以下过程:

#include <unistd.h>
#include <stdio.h>

int main()
{
    printf( "hi 2 u\n" );
    int mypid = fork();

    if( 0 == mypid )
        printf( "lol child\n" );
    else
        printf( "lol parent\n" );

    return( 0 );
}

输出将如下所示:

嗨 2 你
大声笑 孩子
大声笑 父母

当你fork()在子进程中返回的 pid 为 0 时,在父进程中返回的 pid 是子进程的 pid。请注意,“hi2u”只打印一次......由parent

execve()并且它的函数家族几乎总是用fork(). execve()你传递给它的应用程序的名称覆盖当前堆栈帧。execve()几乎总是与fork()你 fork 一个子进程的地方一起使用,如果你是父母,你会做任何你需要继续做的事情,如果你是孩子,你会执行一个新进程。execve()也几乎总是与 --waitpid 一起使用waitpid()- waitpid 获取子进程的 pid,并且从字面上看,一直等到子进程终止并将子进程的退出状态返回给您。

使用这些信息,您应该能够编写一个非常基本的 shell;一种在命令行上获取进程名称并运行您告诉它的进程。当然,shell 做的远不止这些,比如管道输入和输出,但是你应该能够使用fork(),execve()和来完成基本的操作waitpid()

注意:这是 *nix 特定的!这在 Windows 上不起作用。

希望这有帮助。

于 2008-08-21T18:44:38.910 回答
18

如果你想执行更复杂的操作,比如读取外部程序的输出,popen系统调用可能会更好。例如,要以编程方式访问目录列表(这是一个有点愚蠢的示例,但作为示例很有用),您可以编写如下内容:

#include <stdio.h>

int main()
{
  int entry = 1;
  char line[200];
  FILE* output = popen("/usr/bin/ls -1 /usr/man", "r");
  while ( fgets(line, 199, output) )
  {
    printf("%5d: %s", entry++, line);
  }
}

给出这样的输出

1: cat1
2: cat1b
3: cat1c
4: cat1f
5: cat1m
6: cat1s
...
于 2008-08-20T01:52:59.040 回答
12
#include <stdlib.h>

int main()
{
    system("echo HAI");

    return 0;
}
于 2008-08-19T22:58:47.757 回答
9

我想给一个很大的警告,不要在编写库时使用系统,并且 100% 永远不要使用系统。它是在 30 年前设计的,当时称为 Unix 的玩具操作系统还不知道多线程。即使今天几乎所有程序都是多线程的,它仍然无法使用。

使用 popen 或执行 fork+execvp,其他所有问题都会让您很难找到信号处理问题、环境处理代码崩溃等问题。选择和评价最高的答案是促进使用“系统”,这是纯粹的邪恶和耻辱”。提倡在工作场所使用可卡因更健康。

于 2012-12-28T18:33:44.637 回答
4

在 UNIX 上,如果您希望生成的进程与生成的进程分开运行,我认为您基本上需要分叉它:例如,如果您不希望在退出生成进程时终止生成的进程。

这是一个解释 Fork、System、Exec 之间所有细微差别的页面。

如果您在 Win、Mac 和 linux 上工作,我可以向您推荐Qt 框架及其 QProcess 对象,但我不知道这是否适合您。最大的优点是您将能够在 windows linux 和 mac 上编译相同的代码:

 QString program = "./yourspawnedprogram";
 QProcess * spawnedProcess = new QProcess(parent);
 spawnedProcess->start(program);
 // or spawnedProcess->startDetached(program);

此外,您甚至可以从母进程中杀死子进程,并通过流与它保持通信。

于 2008-08-19T23:47:13.537 回答
2

一种解决方案是在 stdlib.h 中定义的系统函数

int system(const char *string);

系统接口示例

于 2008-08-19T22:59:56.897 回答
1

说到平台相关的配方,在 Windows 上使用CreateProcess,在 Posix (Linux, Mac) 上使用fork+ execvp。但system()应该满足您的基本需求并且是标准库的一部分。

于 2008-12-23T16:30:10.977 回答
1

If you need to check/read/parse the output of your external command, I would suggest to use popen() instead of system().

于 2008-12-23T16:08:56.323 回答