如何让子进程使用另一个终端输入输出?

问题描述 投票:0回答:3

我用谷歌搜索了很多,但没有找到任何真正满足我需求的解决方案。

我需要分叉子进程来使用另一个终端的 stdinstdout,而不是在此处调用它的终端,这是我想要做的示例

#include <stdio.h>
#include <unistd.h>
#include <signal.h>

int main()
{
    pid_t pid;
    printf("process parent pid is %d\n",getpid());
    pid =fork();
    printf("process child pid is %d\n",pid);
    if(pid==0)
    {
        //int exit_status = system("gnome-terminal");
        char a[20];
        while(1)
        {
            scanf(" %s",a);
            printf("child %s \n",a);
        }
    }
    while(1)
    {
        char b[20];
        scanf(" %s",b);
        printf("parent  %s \n",b);
    }
}

例如,我需要孩子通过另一个终端与用户交互。

c fork stdout stdin
3个回答
2
投票

据我了解您的问题,您希望分叉一个子进程,该进程通过虚拟终端(即 gnome-terminal)与用户进行所有交互。 然后,首先,阅读这篇文章,了解终端和 shell 之间的区别。然后阅读关于 Unix 伪终端的这篇文章。然后阅读这篇关于 /dev/pts 文件系统的文章。这将为您提供我的回答的背景。

这是创建连接到不同终端(虚拟终端)的子进程的一种方法。我承认,我已经很长时间没有这样做了,而且是使用物理 TTY,而不是伪终端。但背景信息应该可以帮助您克服可能遇到的任何困难。

总体方法是分叉两个子进程。一种用于虚拟终端,一种用于工作进程。然后,您将执行虚拟终端进程,使其在 shell 退出时不会关闭。您实际上甚至不希望它启动 shell 或任何与此相关的程序,因为您将提供与其交互的正在运行的进程。对于 gnome-terminal,要让它在进程退出后继续停留并不容易。您应该

阅读本文以获取有关如何保留它的建议。另一种选择是使用“xterm”,它具有“--hold”选项,该选项似乎适合该目的。 “xterm”还有“-S”选项,听起来与您所需要的完全一样。要使用“-S”选项,您需要阅读PTS

由于 XTERM 具有您需要的选项,因此我将描述基于 XTERM 而不是 gnome-terminal 的方法。

在您的子程序中,您需要打开 /dev/ptmx 来获取主伪终端文件描述符。然后,您可以在 FD 上调用 ptsname() 来获取 PTS 的名称。您需要该名称来通知 XTERM 要使用哪个从属 PTS。您必须通过在主 FD 上调用 grantpt() 和unlockpt() 来授予访问权限并解锁 FD。接下来,分叉另一个进程并使用 -S 选项执行 exec() XTERM,该选项采用“-S/dev/pts/123/42”或等效的“-S123/42”形式的 PTS 名称和文件描述符编号。在这种情况下,我认为您不需要“--hold”,但如果事实证明您需要,请添加它。 (有关使用 -S 的更多信息,请参阅 XTERM 手册页)

这会将终端建立为子进程的主伪终端文件描述符上的用户 I/O 设备。因此,接下来您将把文件描述符 dup() 到 fd 0 和 fd 1 上(如果您希望 stderr 到达那里,则还可以将文件描述符复制到 fd 2 上)。

很抱歉这太笼统了。该方法应该可行,但您可能需要根据您的特定 Linux/Unix 风格进行调整。请让我知道你是怎么做的,如果有机会,我会安装一个 Linux 并亲自尝试一下。


0
投票
stdin 是文件描述符 0。要附加到另一个文件或流(或设备),您的子进程必须首先关闭文件描述符 0,然后打开另一个文件(设备)。 Open 将返回 fd 0(如果成功),因为它现在是第一个可用的。您可以使用 dup() 以原子方式执行此操作。

您需要获得权限才能打开设备。

例如,假设您感兴趣的输入设备是 /dev/input/tty1...

if(childpid == 0) { int fd = open("/dev/input/tty1", open_args); if(fd >= 0) { /* Close stdin, duplicate the fd just opened to stdin */ dup2(0, fd); // etc...
    

0
投票
我在另一个终端中分叉进程有类似的需求,我在这里描述了我的解决方案:

如何将进程分叉到另一个虚拟终端

希望对您有帮助

© www.soinside.com 2019 - 2024. All rights reserved.