java子进程通信,与子进程stdout / stdin通信

我正在尝试与进程通信(它本身写入stdin和stdout以在终端中与用户进行交互)并读取它的stdin并在C中写入它的stdout .

因此,我尝试以编程方式替换shell用户 . 一个美国式的例子:想象一下,我想出于某种原因在C中使用VIM . 然后我还需要编写命令(stdout)并从编辑器中读取东西(stdin) .

最初我认为这可能是一项微不足道的任务,但似乎没有标准方法 . int system(const char *command); 只执行命令并将命令stdin / stdout设置为调用进程之一 .

因为这无处可去,我看了 FILE *popen(const char *command, const char *type); 但手册页说明:

由于管道根据定义是单向的,因此类型参数可以仅指定读取或写入,而不是两者;结果流相应地是只读的或只写的 .

及其含义:

popen()的返回值在所有方面都是普通的标准I / O流,除非必须用pclose()而不是fclose(3)来关闭它 . 写入这样的流写入命令的标准输入;命令的标准输出与调用popen()的进程相同,除非命令本身改变了它 . 相反,从“popened”流读取读取命令的标准输出,命令的标准输入与调用popen()的进程相同 .

因此,使用popen()并不是完全不可能,但在我看来它非常不优雅,因为我必须解析调用进程的stdout(调用popen()的代码)以解析从popened命令(当使用popen类型'w'时) .

相反,当使用类型'r'调用popen时,我需要写入调用的进程stdin,以便将数据写入popened命令 . 在这种情况下,我甚至不清楚这两个进程是否在stdin中都接收到相同的数据......

I just need to control stdin and stdout of a program. 我的意思是不能有这样的功能:

stdin_of_process, stdout_of_process = real_popen("/path/to/bin", "rw")

// write some data to the process stdin

write("hello", stdin_of_process)

// read the response of the process

read(stdout_of_process)

所以我的 first question :实现上层功能的最佳方法是什么?

目前我正在尝试以下方法与另一个进程通信:

使用 int pipe(int fildes[2]); 设置两个管道 . 一个管道读取进程的stdout,另一个管道写入进程的stdin .

福克 .

使用 int execvp(const char *file, char *const argv[]); 执行我想在分叉子进程中与之通信的进程 .

使用原始流程中的两个管道与孩子沟通 .

这很容易说机器人没有那么简单地实现(至少对我而言) . 我奇怪地设法在一个案例中这样做,但当我试图通过一个更简单的例子来理解我在做什么时,我失败了 . 这是我目前的问题:

我有两个程序 . 第一个只是每100毫秒写一个递增的数字到它的标准输出:

#include

#include

#include

#include

#include

void sleepMs(uint32_t ms) {

struct timespec ts;

ts.tv_sec = 0 + (ms / 1000);

ts.tv_nsec = 1000 * 1000 * (ms % 1000);

nanosleep(&ts, NULL);

}

int main(int argc, char *argv[]) {

long int cnt = 0;

char buf[0x10] = {0};

while (1) {

sleepMs(100);

sprintf(buf, "%ld\n", ++cnt);

if (write(STDOUT_FILENO, buf, strlen(buf)) == -1)

perror("write");

}

}

现在第二个程序应该读取第一个程序的stdout(请记住我最终想要读取和写入一个进程,因此对于上层用例使用popen()的技术正确解决方案可能是正确的在这个特定的情况下,因为我简化了我的实验,只是捕获底部程序的stdout) . 我希望从底层程序中读取上层程序写入stdout的任何数据 . 但它没有读任何东西 . 可能是哪里的原因? (第二个问题) .

#include

#include

#include

#include

#include

#include

void sleepMs(uint32_t ms) {

struct timespec ts;

ts.tv_sec = 0 + (ms / 1000);

ts.tv_nsec = 1000 * 1000 * (ms % 1000);

nanosleep(&ts, NULL);

}

int main() {

int pipe_fds[2];

int n;

char buf[0x100] = {0};

pid_t pid;

pipe(pipe_fds);

char *cmd[] = {"/path/to/program/above", NULL};

if ((pid = fork()) == 0) { /* child */

dup2(pipe_fds[1], 1); // set stdout of the process to the write end of the pipe

execvp(cmd[0], cmd); // execute the program.

fflush(stdout);

perror(cmd[0]); // only reached in case of error

exit(0);

} else if (pid == -1) { /* failed */

perror("fork");

exit(1);

} else { /* parent */

while (1) {

sleepMs(500); // Wait a bit to let the child program run a little

printf("Trying to read\n");

if ((n = read(pipe_fds[0], buf, 0x100)) >= 0) { // Try to read stdout of the child process from the read end of the pipe

buf[n] = 0; /* terminate the string */

fprintf(stderr, "Got: %s", buf); // this should print "1 2 3 4 5 6 7 8 9 10 ..."

} else {

fprintf(stderr, "read failed\n");

perror("read");

}

}

}

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值