【问题标题】:How to make a child process use another terminal input and output?如何让子进程使用另一个终端输入和输出?
【发布时间】:2015-10-15 17:45:02
【问题描述】:

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

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

#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


【解决方案1】:

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

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

总体方法是分叉两个子进程。一个用于虚拟终端,一个用于工作进程。然后,您将执行虚拟终端进程,使其在 shell 退出时不会关闭。你真的不希望它启动一个 shell 或任何程序,因为你将提供与它交互的正在运行的进程。使用 gnome-terminal,在进程退出后告诉它挂断并不是很容易。您应该read this 获得有关如何保留它的建议。另一种方法是使用具有“--hold”选项的“xterm”,该选项似乎适合该目的。 "xterm" 也有 "-S" 选项,听起来和你需要的完全一样。要使用“-S”选项,您需要阅读PTS

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

在您的子程序中,您需要打开 /dev/ptmx 以获取主伪终端文件描述符。然后在 FD 上调用 ptsname() 以获取 PTS 的名称。您需要该名称来告知 XTERM 要使用的从 PTS。您必须通过在主 FD 上调用 grantpt() 和 unlockpt() 来授予访问权限并解锁 FD。接下来,fork 另一个进程并使用 -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 试试。

【讨论】:

  • 您能否推荐任何从头开始涵盖此内容的书籍或教程? /跨度>
  • 哦,我会读得很辛苦
【解决方案2】:

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...

【讨论】:

  • 这样做会阻止父级访问终端的标准输入不是吗?
  • 您的回答似乎不错,但我无法理解您要做什么。 int open(const char *pathname, int flags); /dev/input/tty1 与终端有什么关系 tty1 是什么 对不起,我有点新手
  • /dev/input/tty1 是一个示例设备,您的系统可能没有它。但是要将另一个终端附加到您的子进程,您必须知道或弄清楚要使用的设备是什么。
  • 我需要使用终端与子进程交互
猜你喜欢
  • 2014-04-07
  • 2019-02-24
  • 1970-01-01
  • 1970-01-01
  • 2018-09-11
  • 2022-11-26
  • 2021-04-24
  • 2014-01-01
  • 1970-01-01
相关资源
最近更新 更多