请参阅以下代码。
<div class="drop">
<input type="text" name="class" placeholder="Class" onfocus="dropdown(0)"/>
<ul class="content">
<li onclick="input(0)">Option 1</li>
<li onclick="input(1)">Option 2</li>
<li onclick="input(2)">Option 3</li>
<li onclick="input(3)">Option 4</li>
</ul>
</div>
我按如下方式编译并运行它。
#include <stdio.h>
#include <unistd.h>
int main()
{
printf("ttyname(0): %s\n", ttyname(0));
printf("ttyname(1): %s\n", ttyname(1));
printf("ttyname(2): %s\n", ttyname(2));
printf("ctermid(NULL): %s\n", ctermid(NULL));
/* Sleep for sometime so that we can manually run the ps command to
* see the terminal associated with the process. */
sleep(10);
return 0;
}
在另一个终端中,我运行$ gcc foo.c
$ ./a.out
ttyname(0): /dev/pts/3
ttyname(1): /dev/pts/3
ttyname(2): /dev/pts/3
ctermid(NULL): /dev/tty
命令确认终端名称。
ps
到目前为止一切都很好。我的程序正确打印终端。
但是,当stdin,stdout和stderr被重定向时,我的程序无法输出终端信息。
$ ps -ef | grep a.out | grep -v grep
coder 1498 1473 0 19:19 pts/3 00:00:00 ./a.out
在另一个终端,我运行$ ./a.out < /dev/null > foo.txt 2> /dev/null
,我可以看到ps
确实与他的过程相关联。
/dev/pts/3
但在$ ps -ef | grep a.out | grep -v grep
coder 1536 1473 0 19:22 pts/3 00:00:00 ./a.out
退出并在./a.out
检查其输出后,我看不到这些信息被捕获。
foo.txt
由于{st}在stdin,stdout和stderr重定向时$ cat foo.txt
ttyname(0): (null)
ttyname(1): (null)
ttyname(2): (null)
ctermid(NULL): /dev/tty
无法提供任何有意义的信息,因此ctermid()
always returns /dev/tty
,我能做些什么来可靠地确定与进程关联的终端?我理想地寻找适用于任何标准Unix或Linux系统的解决方案,但如果不可行,那么Linux特定的解决方案也可以。
答案 0 :(得分:3)
当stdin,stdout和stderr被重定向时,我的程序无法输出终端信息
是的,ttyname()
返回(a)在指定文件描述符上打开的终端设备的名称。当文件描述符不引用终端时,没有这样的设备。在这种情况下,ttyname()
被记录为返回NULL
,以及指定文件描述符未与终端关联的任何其他文件。
如何可靠地确定与流程关联的终端?
您首先必须自己确定与该过程相关的“终端”是什么意思。原则上,文件描述符0,1和2以及甚至更多可能都连接到不同的终端设备。它们的 none 可能是进程的控制终端,我认为这可能是您实际需要的。
如果进程想要访问其控制终端(假设它有一个),独立于其标准流的重定向,那么它应该打开由{{1返回的字符串命名的设备如果有的话。那个glibc ctermid()
总是返回ctermid()
是无关紧要的 - 因为设备通常被命名,它作为访问进程控制终端的同义词。
然而,据我所知,没有便携,可靠的方法来确定任何设备(包括控制终端)的与流程无关的名称。内核在设备名称方面本身并不起作用 - 这些名称存在于文件系统中,是为了方便用户空间进程而提供的。此外,任何给定的设备原则上都可以有多个引用它的文件名。
但是,在Linux上,您可以从/proc/self/stat
获取进程控制终端的主设备号和次设备号。原则上,您可以解压缩这些数字
将它们转换为相应的传统文件名,大概是在"/dev/tty"
的帮助下,或
扫描/proc/devices
文件系统以查找匹配的设备文件,并报告其名称。
前者较便宜,但有点投机;后者,如果成功,将返回存在的设备文件的名称,并且肯定会引用所需的设备。
您还可以在此处查看建议:https://unix.stackexchange.com/questions/151812/get-device-node-by-major-minor-numbers-pair,但我发现其中至少有一些不适用于我的系统。