ILD

controlling terminal
作者:Yuan Jianpeng 邮箱:yuanjp89@163.com
发布时间:2024-8-8 站点:Inside Linux Development

每个进程可以有控制终端,通常从交互式shell启动的程序,它的标准输出和标准错误输出到控制终端,它的标准输入从控制终端读取输入。


控制终端收到CTRL+C等按键时,会发送信号给控制终端前的端进程组(foreground process group)。

注意是发给group,因为前端进程可能有多个,比如 echo 123 | hexdump


再终端启动一个交互式shell

$ sh -i

它会打开/dev/tty这个虚拟的字符设备(表示当前进程的控制终端)。

修改自己的组id为自己的pid。然后调用TIOCSPGRP ioctl把自己的组设置成前端进程组。


strace记录如下:

getpid()                                = 1090

getppid()                               = 1087

openat(AT_FDCWD, "/dev/tty", O_RDWR|O_LARGEFILE) = 3

fcntl64(3, F_DUPFD_CLOEXEC, 10)         = 10

close(3)                                = 0

ioctl(10, TIOCGPGRP, [1087])            = 0

getpgrp()                               = 1087

setpgid(0, 1090)                        = 0

ioctl(10, TIOCSPGRP, [1090])            = 0


进程的标准输入输出可以关闭、重定向等,但是这不影响进程的控制终端。进程仍然可以获取并打开控制终端。

通过ctermid() 接口,可以获得进程控制终端的路径。这个接口通常是返回/dev/tty.


另外ttyname()接口,可以返回一个终端fd的路径。

printf("stdout tty: %s\n", ttyname(1));

attach controlling terminal

只要open一个终端,不指定O_NOCTTY选项即可。

dettach controlling terminal 

要关闭一个进程的控制终端,可以


1 打开控制终端,然后调用 TIOCNOTTY ioctl

int fd = open(ctermid(NULL), O_RDWR);

ioctl(fd, TIOCNOTTY);


2 调用setsid(),这个接口会创建一个新的session,并且没有控制终端。

注意 process group leader不能调用setsid,会返回-1。因为setsid会创建新session,且把调用者变成新leader,且新process group id等于调用者的pid。因此如果本身就是leader。那么一个进程组中的进程可能跨越多个session。

Copyright © linuxdev.cc 2017-2024. Some Rights Reserved.