gpt4 book ai didi

c - 通过 C 中的 pipe/dup2 向子进程发送命令

转载 作者:太空宇宙 更新时间:2023-11-04 04:53:53 26 4
gpt4 key购买 nike

我正在尝试在我的树莓派上为 omxplayer 编写一个远程控制程序

我可以让 omxplayer 在子进程中正常运行,但我似乎无法让管道正常工作以实际向子进程发送命令。

int fd_pipe[2];
pipe (fd_pipe);

while(1) { // main accept() loop

printf("server: got connection from %s\n", s);

/* Attempt to fork and check for errors */
if( (pid=fork()) == -1){
fprintf(stderr,"Fork error. Exiting.\n"); /* something went wrong */
exit(1);
}

if (pid==0)
{ // this is the child process
dup2(0, fd_pipe[0]);
close(fd_pipe[1]);


if(execl("/usr/bin/top","top",NULL) == -1){
fprintf(stderr,"execl Error!");
exit(1);
}

//try and send command here
write(fd_pipe[0], "q", 1);

exit(0);

} else {

close(new_fd); // parent doesn't need this
dup2(1, fd_pipe[1]);

//try and send here too
write(fd_pipe[0], "q", 1);
}
}

当我用 top 测试并运行程序时,我可以看到 top 输出出现在终端窗口中,我可以在窗口中看到 q 命令,但它看起来像是去往父进程而不是子进程。我是不是对管道做错了什么,还是无法向生成的子进程发送命令?

我尝试更改子 dup2 语句以从管道复制到标准输入

        { // this is the child process
dup2(fd_pipe[0], 0);

但随后 top 无法以失败的 tty get 消息启动

最佳答案

要与期望能够操作终端的程序进行交互,您应该使用伪 tty。这将避免 failed tty get 错误。

/*...*/
#include <pty.h>

void do_child () {
if (execlp("top", "top", (const char *)0) < 0) {
perror("exec top");
exit(EXIT_FAILURE);
}
/* NOTREACHED */
}

void do_parent (int fd, pid_t p) {
sleep(5);
char r;
write(fd, "q", 1);
while (read(fd, &r, 1) > 0) { write(1, &r, 1); }
waitpid(p, 0, 0);
close(fd);
}

int main () {
int fd;
pid_t p = forkpty(&fd, 0, 0, 0);
switch (p) {
case 0: do_child();
/* NOTREACHED */
case -1: perror("forkpty");
exit(EXIT_FAILURE);
default: break;
}
do_parent(fd, p);
return 0;
}

请注意,forkpty 不是 POSIX,而是在 BSD 和 Linux 风格的 UNIX 上可用的接口(interface)。

您可以以批处理模式执行top,但不能使用命令退出。你必须杀死它。

void do_child () {
if (execlp("top", "top", "-b", (const char *)0) < 0) {
perror("exec top");
exit(EXIT_FAILURE);
}
/* NOT REACHED */
}

void do_parent (pid_t p) {
sleep(5);
if (kill(p, SIGINT) < 0) {
perror("kill");
exit(EXIT_FAILURE);
}
waitpid(p, 0, 0);
}

int main () {
pid_t p;
switch ((p = fork())) {
case 0: do_child();
case -1: perror("fork"); exit(EXIT_FAILURE);
default: break;
}
do_parent(p);
return 0;
}

虽然以批处理模式运行将允许您使用更简单的调用(例如 mux 建议的 popen)打开进程,除非该调用返回子进程 ID,否则您不会能够杀死它(无需执行 pkill,或挖掘进程表以找到要杀死的正确子进程)。

我认为您对如何使用 dup2 有一些困惑。手册页使用术语oldfdnewfd,这意味着oldfd 将变为newfd。为了说明这一点,这里有一个简单的程序,它将 stdout 和 stderr 重定向到一个日志文件,调用一个函数,然后恢复 stdout 和 stderr。

void do_something () {
fputs("Error message\n", stderr);
puts("This is regular output.");
fputs("Error message\n", stderr);
puts("This is regular output.");
}

int main () {
int fd = creat("/tmp/output.log", 0664);
int outfd = dup(fileno(stdout));
int errfd = dup(fileno(stderr));
fflush(stdout);
fflush(stderr);
dup2(fd, fileno(stdout));
dup2(fd, fileno(stderr));
setlinebuf(stdout);

do_something();

fflush(stdout);
fflush(stderr);
dup2(outfd, fileno(stdout));
dup2(errfd, fileno(stderr));
close(outfd);
close(errfd);

fputs("Error to the screen\n", stderr);
puts("Regular output to screen");
fputs("Error to the screen\n", stderr);
puts("Regular output to screen");

return 0;
}

正如 mux 所指出的,您的程序正在写入错误的管道末端。 pipe 命令返回一对单向文件描述符,其中写入到 fd_pipe[1] 的内容可以从 fd_pipe[0] 中读取.

关于c - 通过 C 中的 pipe/dup2 向子进程发送命令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11689421/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com