【问题标题】:How to figure out whether a Linux TTY is controlling a process group如何判断一个 Linux TTY 是否在控制一个进程组
【发布时间】:2010-07-06 20:04:03
【问题描述】:

所以我有一个 tty(比如说 /dev/tty5)并且想知道它当前是否是进程组或会话的控制 tty,或者它当前是否是无主的。 POSIX 有两个 API 函数,它们在这里建议自己:tcgetpgrp() 和 tcgetsid(),但这两个函数都只有在调用者将 tty 作为控制 tty 时才有效——在这种情况下,这使它们几乎无用(实际上我没有根本看不到 tcgetsid() 的意义)。

有人建议我如何从 C 中以理智的方式检测终端当前是否是进程的控制终端?我只关心 Linux,所以如果需要特定于 Linux 的 API,那对我来说没问题。

【问题讨论】:

    标签: c linux process tty


    【解决方案1】:

    BSD: int ioctl(int tty, TIOCGETPGRP, int *foreground_group);

    Linux: int tcgetpgrp(int tty, int *foreground_group);

    Linux 仅在您拥有非拥有终端的权限时才能工作,即您是 root。这是一个有意的安全实施。 BSD ioctl() 允许任何 tty 将任何进程组(甚至不存在的进程组)作为其前台 tty。 POSIX 只允许访问以 tty 作为其控制 tty 的进程组。此限制不允许 BSD ioctl 中存在一些模棱两可和破坏安全的情况。

    你想做什么?如果您是传递信号的内核,您应该只担心进程控制 tty。

    编辑:我忘了 /proc
    来自 www.die.net: /proc/[编号]/fd 这是一个子目录,其中包含进程打开的每个文件的一个条目,由其文件描述符命名,并且是指向实际文件的符号链接。因此,0 是标准输入,1 是标准输出,2 是标准错误,等等。

    【讨论】:

    • 在我最初的问题中,我已经尝试解释为什么 tcgetpgrp() 大多无用。我想要这个的原因只是为了弄清楚一个 getty 左右是否已经在终端上处于活动状态。我不关心打开 TTY 以进行写入的其他进程(这可能发生在日志记录中,yadda yadda),我想知道是否真的有人在读取/控制它。并且通过 /proc a la lsof 不是我所说的“理智”......
    • 这就是全部。除非您访问内核模式数据,或者您是 root,否则您无法使用用户模式调用执行您所描述的操作。不在 Linux 中。原因:安全。如果它冒犯了你对理智的定义,我很抱歉。与 Ulrich Drepper 合作。
    【解决方案2】:

    将此作为系统调用“ps au >tempfile.txt”执行,并解析文件。

    【讨论】:

      【解决方案3】:

      不确定这是否完全满足您的需求,无论如何它是:

      #include <stdlib.h>
      #include <stdio.h>
      
      int main()
      {
        int status = system("fuser /dev/tty1 >/dev/null 2>/dev/null") >> 8;
        printf("%s",
               status ?
                 "tty not in use as a text terminal.\n" :
                 "tty in use as a text terminal.\n");
        return 0;
      }
      

      【讨论】:

      • fuser 进程可能再次调用了某个 C 库函数。为什么不在程序中直接调用该函数呢? :p
      • @vbdoor:相当于fuser的C库函数不存在。 fuser 是一个 Linux 程序,它会调用很多库:sed -n 's/^\(.*\)(.*/\1/g;p' &lt; &lt;(ltrace fuser /dev/tty1 2&gt;&amp;1) | sort -u 我的 PC 上的输出是:bindtextdomain close closedir fclose fgets fopen64 free __fxstat64 getpid __libc_start_main malloc opendir readdir64 setlocale __snprintf_chk socket sscanf strchr __strdup strtol textdomain __xstat64。 :)
      【解决方案4】:

      如果你知道进程的PID,你可以使用proc文件系统查询进程的控制tty。

      /proc//fd/0 是到 tty 的符号链接(比如 /dev/pts/4)。

      所以你需要做的就是创建一个带有 PID 的 proc 路径(例如:/proc/7834/fd/0,其中 7834 是 PID),然后调用 readlink 系统调用来获取 tty

      见下面的C代码sn-p

      sprintf(procPath, "/proc/%s/fd/0", pid);
      int ret = readlink(procPath, buffer, MAX_LEN);
      buffer[ret] = '\0';
      

      【讨论】:

        猜你喜欢
        • 2021-10-15
        • 2012-07-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-01-14
        • 1970-01-01
        • 2018-04-15
        • 1970-01-01
        相关资源
        最近更新 更多