子调用exec()

时间:2015-10-14 15:40:24

标签: c pipe exec parent-child ipc

我的最终目标是让父进程将文本行传递给子进程,然后子进程将文本打印到stdout。当父母获得用户输入并将其传递给孩子时,孩子将在后地“永久”跑。我更喜欢这个孩子参加一个单独的课程。通过if语句作为软糖混乱来区分孩子和paretn。

我正在调查管道,但我不确定在孩子将exec()调用到另一个程序之后,管道是否可以在父母/子女之间进行通信。

这可能吗?如果是的话,有什么例子可以指点我吗?如果没有,在这种情况下我可以使用哪种IPC方法?

3 个答案:

答案 0 :(得分:2)

标准方案是让程序作为子项执行时与管道无关,只需使用stdin / stdout即可。您可以通过dup2()管道的相应末端{f} 01(或两者都有两个管道进行双向通信)来实现此目的,对应STDIN_FILENO和{{ 1}}。在此之后,执行您的孩子计划。

当然,有一些替代品,例如如果您需要STDOUT_FILENO / stdin用于孩子的其他目的,请使用“命名管道”。

如果你自己编写两个部分,你可能想要考虑更简单的解决方案:

  

通过if语句将软件弄得一团糟,区分孩子和父母。

无论如何你必须这样做,至少是为了连接管道并调用exec()。只需创建单独的代码文件,并根据需要调用stdoutparent_main()等内容(无论您喜欢称呼它们)。

答案 1 :(得分:0)

在exec *()函数之后,子进程共享父进程的所有文件描述符。因此,如果在fork()之前创建管道,则可以访问它们中的读/写fd。

通常的方法是:

  • 创建一个管道(读取fd,写入fd)
  • fork()的
  • 父母中的
    • close read fd(你不会在这里读到父母)
    • 将数据写入write fd
    • 等待/管芯
  • 小孩子里面的:
    • 关闭写fd(你不会从孩子写)
    • 从read fd
    • 读取数据
    • 等待/管芯

无法理解为什么要执行新流程。如果真的需要你必须使用标准的stdin / stdout(参见其他答案)或者有一个程序接受fd(filedescriptor,一个整数)作为参数,以便知道哪一个是管道。对我来说似乎不太好。

答案 2 :(得分:0)

实际上,使用popen(它可以自动管理通信渠道)进行操作要容易得多

  

FILE *popen(const char *command, const char *mode);   popen()函数应执行由字符串指定的命令   命令。它将在调用程序和   执行的命令,并应返回一个指向可以   用于读取或写入管道。

     

已执行命令的环境应类似于子进程   是使用fork()函数在popen()调用中创建的,并且   孩子使用以下调用了sh实用程序:

     

execl(shell路径,“ sh”,“ -c”,命令,(char *)0);

     

其中shell路径是sh实用程序的未指定路径名。

     

popen()函数应确保来自上一个的任何流   在父进程中保持打开状态的popen()调用在   新的子进程。

     

popen()的mode参数是一个指定I / O模式的字符串:

     

如果mode为r,则子进程启动时,其文件描述符   STDOUT_FILENO应该是管道的可写端,并且文件   调用过程中的描述符fileno(stream),其中stream是   popen()返回的流指针应为   管道。

     

如果mode为w,则子进程启动时其文件描述符   STDIN_FILENO应该是管道的可读端,并且文件   调用过程中的描述符fileno(stream),其中stream是   popen()返回的流指针应为   管道。

     

如果mode是其他任何值,则结果不确定。

     

popen()之后,父进程和子进程都应能够   在任一终止之前独立执行的操作。

     

管道流是面向字节的。

     

返回值

     

成功完成后,popen()应返回一个指向open的指针   可以用于读取或写入管道的流。否则   应该返回一个空指针,并可以设置errno来指示错误。

例如,假设您要将Hello world发送给孩子:

#include<stdio.h>
#include<stdlib.h>
#include <unistd.h>
int main()
{
  FILE* toChild;
  toChild = popen("./child", "w");//child is executable of the other file: change the name
  int res = fputs( "Hello World\n", toChild);
  pclose(toChild);
  return 0;
}

和孩子:

int main()
{
  char p[100];
  int n;
  do{
    n = scanf("%s", p);
    if (n>0) {
    printf("INPUT MESSAGE: \"%s\n\"", p);
    //free(p);
    }
    else {
      printf( "%d, No matching characters\n", n);
    }
  }while(n>0);
  return 0;
}

如果您使用的是纯POSIX系统(而不是OSX),也可以将scanf("%ms", &p)char* p一起使用,然后将free(p) GetMandatoryFieldsforUser: function (data) { var field = []; $.get("api/mapping/mandatoryfield?type=USER", function (data) { var self = this; self.dt = []; self.firmdata = JSON.parse(data.Data); console.log(self.firmdata); self.firmdata.forEach(function (item) { field.push(item.DisplayName); }) console.log(field) //able to print value }) console.log(field) // not able to print value return MandatoryFields.User; }, 一起使用。