我们如何在C中产生另一个进程?

时间:2020-03-05 18:40:56  来源:igfitidea点击:

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

解决方案

回答

#include <stdlib.h>

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

    return 0;
}

回答

一种解决方案是stdlib.h中定义的系统功能

int system(const char *string);

系统API范例

回答

在UNIX上,如果希望使生成的进程从运行的进程中脱离出来,则基本上需要对其进行分叉:例如,如果我们不希望在退出生成进程时终止生成的进程。

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

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

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

另外,我们甚至可以从母进程中杀死子进程,
并通过信息流与之保持联系。

回答

如果我们想执行更复杂的操作,例如读取外部程序的输出,则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
...

回答

确实,这实际上取决于我们要执行的操作:

  • 取决于操作系统
  • 不太清楚我们要做什么。

不过,我会尽力提供一些信息供我们决定。
在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 );
}

输出将如下所示:

hi 2 u

    lol child

    lol parent

当我们使用fork()时,子代返回的pid为0,而父代返回的pid是子代的pid。请注意," hi2u"仅由父级打印一次。

execve()及其功能系列几乎总是与fork()一起使用。execve()等类似的东西会使用传递给它的应用程序的名称覆盖当前的堆栈框架。 execve()几乎总是与fork()一起使用,在其中派生一个子进程,如果我们是父进程,则我们需要做的一切都要做,而如果我们是孩子,则执行一个新进程。 execve()也几乎总是与waitpid()一起使用-waitpid接受子进程的pid,从字面上看,等到子进程终止并将子进程的退出状态返回给我们。

使用此信息,我们应该能够编写一个非常基本的shell。一种在命令行中使用进程名称并运行我们告诉它的进程。当然,shell可以做更多的事情,比如管道输入和输出,但是我们应该能够使用fork()execve()waitpid()来完成基础知识。

注意:这是* nix特有的!在Windows上将无法使用。

希望这对我们有所帮助。

回答

如果我们需要检查/读取/解析外部命令的输出,我建议使用popen()而不是system()。

回答

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