我的最终目标是让父进程将文本行传递给子进程,然后子进程将文本打印到stdout。当父母获得用户输入并将其传递给孩子时,孩子将在后地“永久”跑。我更喜欢这个孩子参加一个单独的课程。通过if语句作为软糖混乱来区分孩子和paretn。
我正在调查管道,但我不确定在孩子将exec()
调用到另一个程序之后,管道是否可以在父母/子女之间进行通信。
这可能吗?如果是的话,有什么例子可以指点我吗?如果没有,在这种情况下我可以使用哪种IPC方法?
答案 0 :(得分:2)
标准方案是让程序作为子项执行时与管道无关,只需使用stdin
/ stdout
即可。您可以通过dup2()
管道的相应末端{f} 0
或1
(或两者都有两个管道进行双向通信)来实现此目的,对应STDIN_FILENO
和{{ 1}}。在此之后,执行您的孩子计划。
当然,有一些替代品,例如如果您需要STDOUT_FILENO
/ stdin
用于孩子的其他目的,请使用“命名管道”。
如果你自己编写两个部分,你可能想要考虑更简单的解决方案:
通过if语句将软件弄得一团糟,区分孩子和父母。
无论如何你必须这样做,至少是为了连接管道并调用exec()。只需创建单独的代码文件,并根据需要调用stdout
和parent_main()
等内容(无论您喜欢称呼它们)。
答案 1 :(得分:0)
在exec *()函数之后,子进程共享父进程的所有文件描述符。因此,如果在fork()之前创建管道,则可以访问它们中的读/写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;
},
一起使用。