【问题标题】:How assign a new terminal window to each child process如何为每个子进程分配一个新的终端窗口
【发布时间】:2016-08-01 20:21:37
【问题描述】:

我想分叉多个进程并为每个子进程分配它自己的终端窗口,以便可以轻松地演示 IPC。 分叉进行得很好,如果我在同一个终端上运行子进程,它运行得很好。 但是为了让每个子进程都有自己的终端窗口,我这样做了

execl("/usr/bin/xterm", "xterm", "-e", "yourprogram", NULL);

程序在新窗口中运行,但它的 PID 与派生该进程的父进程显示的不同。我做错了什么?

谢谢

edit1 - 这是我的主要功能(父进程)。我分叉了 4 个子进程。我希望每个子进程都有自己的终端窗口。然而,子进程刚刚退出,具有不同 PID 的新进程继续在新终端中运行。

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/shm.h>

int main()
{

pid_t pid[4]; 
int i = 0;
int status;

//Fork four new processes
for(i=0; i<4; i++)
{
    pid[i] = fork();

    if(pid[i] == 0 && i == 0)
    {
        execl("/usr/bin/xterm", "xterm", "./child1", NULL);
        exit(1);
    }
    else if(pid[i] == 0 && i == 1)
    {
        execl("/usr/bin/xterm", "xterm", "./child2", NULL);
        exit(1);
    }
    else if(pid[i] == 0 && i == 2)
    {
        execl("/usr/bin/xterm", "xterm", "./child3", NULL);
        exit(1);
    }
    else if(pid[i] == 0 && i == 3)
    {
        execl("/usr/bin/xterm", "xterm", "./child4", NULL);
        exit(1);
    }
    else
    {
        //Parent process
        printf("The main function has forked a process with pid: %d\n", pid[i]);
    }
}

for(i=0;i<4;i++)
{
    status = waitpid(pid[i], NULL, 0);
    if(status == pid[i])
        printf("%d: Process Terminated Successfully\n", pid[i]);
    else
    {
        perror("waitpid");
        exit(1);
    }
}

return 1;
}

edit2 - 添加 ps -u 输出:

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
dell-pc   3024  0.1  0.0  26872  5480 pts/0    Ss   16:54   0:00 bash
dell-pc   3038  0.0  0.0   4200   632 pts/0    S+   16:54   0:00 ./main
dell-pc   3039 22.5  0.1 109240 11116 pts/0    S+   16:54   0:01 xterm ./child1
dell-pc   3040 26.1  0.1 109240 11268 pts/0    R+   16:54   0:02 xterm ./child2
dell-pc   3041 28.7  0.1 109240 11180 pts/0    S+   16:54   0:02 xterm ./child3
dell-pc   3042 27.0  0.1 109240 11288 pts/0    S+   16:54   0:02 xterm ./child4
dell-pc   3044  4.1  0.0   4200   648 pts/24   Ss+  16:55   0:00 child3
dell-pc   3046  3.7  0.0   4200   680 pts/26   Ss+  16:55   0:00 child4
dell-pc   3048  3.8  0.0   4200   792 pts/25   Ss+  16:55   0:00 child2
dell-pc   3050  3.3  0.0   4200   660 pts/14   Ss+  16:55   0:00 child1
dell-pc   3060  2.0  0.0  26816  5412 pts/27   Ss   16:55   0:00 bash
dell-pc   3072  0.0  0.0  22648  2688 pts/27   R+   16:55   0:00 ps -u

edit3:添加 main: 的输出:

The main function has forked a process with pid: 3491
The main function has forked a process with pid: 3492
The main function has forked a process with pid: 3493
The main function has forked a process with pid: 3494
3491: Process Terminated Successfully
3492: Process Terminated Successfully
3493: Process Terminated Successfully
3494: Process Terminated Successfully

【问题讨论】:

  • 您可能在这里有答案:stackoverflow.com/questions/11040334/…
  • 看到了该解决方案,但它不使用 C 代码。我需要使用 C
  • 我想你没有做错任何事。终端使用另一个子进程运行您需要的命令。
  • 但是父进程和子进程返回的子进程的PID(使用getpid())是不同的。这就是我认为有问题的原因。此外,子进程(具有父进程给出的 PID)实际上在 exec 调用之后退出。可能,execl 在内部分叉?
  • 因为你有三个进程,你的主程序,它是运行 xterm 的子进程,它有他自己的子进程运行你的命令。

标签: c linux fork exec ipc


【解决方案1】:

我做了一个像你这样的程序(命名为 stackoverflow),在 xterm 中执行 vi,当它运行时我打开第三个 xterm 来运行 ps -u。输出是:

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
osboxes   1713  0.0  0.2   6588  4756 pts/0    Ss   18:56   0:00 bash
osboxes   1780  0.0  0.2   6508  4484 pts/1    Ss   19:12   0:00 bash
osboxes   1836 88.4  0.0   2020   532 pts/0    R+   19:21   0:29 ./stackoverflow
osboxes   1837  0.1  0.4  12844  8952 pts/0    S+   19:21   0:00 /usr/bin/xterm -e vi stackoverflow.txt
osboxes   1839  0.0  0.1   6072  3536 pts/2    Ss+  19:21   0:00 vi stackoverflow.txt
osboxes   1840  0.0  0.1   4772  2452 pts/1    R+   19:22   0:00 ps -u

程序的输出是:

PID=1836
child PID=1837

所以孩子还在运行xtermcommand。它创建了另一个运行 vi (pid 1839) 的子进程。

【讨论】:

  • 但这不是我想要的。我希望新终端具有最初分叉的相同子 PID
  • @neoprogrammer 但事实就是如此。 “child PID=1837”是我打印这个数字的时候。与ps -u 结果中的第四个条目进行比较。
  • 你先fork一个子进程吗?在我的情况下,分叉子的 PID 和新的终端窗口是不同的
  • @neoprogrammer 你确定你没有把 xterm 进程误认为是在里面运行的程序吗? (ps -u 输出的第五行)。是的,我做了fork(),否则我不会让stackoverflowxterm 一起运行。
  • 我在里面运行的程序中使用getpid()来显示里面运行的程序的PID。此外,当程序仍在 xterm 中执行时,会执行“进程成功终止”语句
【解决方案2】:

IPC Demo 和使用终端窗口的示例,在

因为在下很容易:

这需要简单的终端工具,例如xterm。这已通过lxtermmate-terminalkonsolegnome-terminal 成功测试。当然,tmuxscreen 也应该可以……

好的,我们走吧。我们假设您已经在某个终端窗口中,我们将把这个初始控制台命名为

1。首先打开一个显示窗口:

所以,从初始控制台,打开日志窗口

exec 5> >(xterm -T 'Log window...' -e sh -c "cat /proc/$$/fd/5")

exec 5> >(xterm -e sh -c "printf '\\e];Log window...\\a';cat /proc/$$/fd/5")

exec 5> >(konsole --nofork -e sh -c "cat /proc/$$/fd/5")
exec 5> >(lxterm -T "Log window..." -e sh -c "cat /proc/$$/fd/5")
exec 5> >(mate-terminal -t 'Log window...' -x sh -c "cat /proc/$$/fd/5")
exec 5> >(gnome-terminal --window -x sh -c "printf '\\e];Log window...\\a';cat /proc/$$/fd/5")

对调试有用的变体

exec 5> >(xterm -e sh -c "printf '\\e];Log window...\\a';
              tee </proc/$$/fd/5 /dev/tty | sed -u s/.*/now/|date -f -")

将在每行输出中打印日期和时间。

exec 5> >(xterm -e sh -c "printf '\\e];Log window...\\a';
              tee </proc/$$/fd/5 /dev/tty | sed -u s/.*/now/|date -f - ; read foo")

相同,但在从父级关闭后会保持窗口打开,等待终端输入(Return)然后再关闭(或由窗口管理器关闭)。

2。测试,然后使用:

总是在初始控制台,点击:

echo >&5 This is a test string.

这必须在日志窗口中提示

好的,现在:

xterm -T 'Input window' -e bash --rcfile <(echo "exec 1>/proc/$$/fd/5") &

注意:这里,双引号将确保$$将从初始窗口的外壳级别。

现在,您可以在输入窗口中输入命令,然后在日志窗口中读取结果。

3。关闭窗口

当文件描述符关闭时窗口将关闭:

exec 5>&-

使用 3 个窗口的完整脚本

你可以在那里找到完整的脚本:

【讨论】:

  • 不错!我正在寻找xterm 语法。但不幸的是,演示不会在我的系统上启动(Debian 9)
  • @techno 抱歉,我错过了第 18 行的 touch $HISTFILE。现在工作正常!在 Debian 9 下测试!谢谢! +1 反馈!
【解决方案3】:

对于我使用的 gnome 终端:

execl("/usr/bin/gnome-terminal", "gnome-terminal", "-q", "-e", "./my_binary", (char*)0);

【讨论】:

    猜你喜欢
    • 2020-09-18
    • 2013-05-03
    • 1970-01-01
    • 2015-05-02
    • 2012-06-12
    • 1970-01-01
    • 2012-05-30
    • 1970-01-01
    • 2013-10-28
    相关资源
    最近更新 更多