如何在 C 中打开 /dev/console

how to open /dev/console in C

我正在阅读 wayland/weston 代码,设置 tty 部分。我发现它试图获取一个可用的 tty 来执行 KMS 并启动 windows.

它是这样的:

    if (!wl->new_user) {
            wl->tty = STDIN_FILENO;
    } else if (tty) {
            t = ttyname(STDIN_FILENO);
            if (t && strcmp(t, tty) == 0)
                    wl->tty = STDIN_FILENO;
            else
                    wl->tty = open(tty, O_RDWR | O_NOCTTY);
    } else {
            int tty0 = open("/dev/tty0", O_WRONLY | O_CLOEXEC);
            char filename[16];

            if (tty0 < 0)
                    error(1, errno, "could not open tty0");

            if (ioctl(tty0, VT_OPENQRY, &wl->ttynr) < 0 || wl->ttynr == -1)
                    error(1, errno, "failed to find non-opened console"); 

            snprintf(filename, sizeof filename, "/dev/tty%d", wl->ttynr);
            wl->tty = open(filename, O_RDWR | O_NOCTTY);
            close(tty0);
    }

在 src/weston-launch.c.

它会尝试 open('/dev/tty0') 并在未指定 tty 的情况下找到可用的 tty。

但是你不能那样做,/dev/tty0和'available tty'都不属于你。我用我的简单版本进行了测试。当然我无法打开 /dev/tty0.

你们知道这个魔法是怎么做到的吗?

tty 的实际 可用 设备取决于系统。在大多数交互式 Unix/Unix-like 系统上,您将拥有一个“tty”,其名称可以从命令行程序 tty 中找到。例如:

$ tty
/dev/pts/2

您可能还有一个名为“tty”的设备,例如

$ ls -l /dev/tty
lrwxrwxrwx   1 root     other         26 Feb  9  2014 /dev/tty -> ../devices/pseudo/sy@0:tty
$ ls -lL /dev/tty
crw-rw-rw-   1 root     tty       22,  0 Feb  9  2014 /dev/tty

您不能只打开 任何 tty 设备,因为它们中的大多数都属于 root(或其他用户)已分配)。

有关 /dev/console/dev/tty 和其他 tty 设备之间差异的进一步讨论,请参阅 Cannot open /dev/console

根据 console_codes(4) 手册页:

VT_OPENQRY

Returns the first available (non-opened) console. argp points to an int which is set to the number of the vt (1 <= *argp <= MAX_NR_CONSOLES).

例如,在 Linux 系统上,我在 /dev 中看到了这个:

crw-rw-rw-   1 root        5,  0 Mon 04:20:13   tty
crw-------   1 root        4,  0 Mon 03:58:52   tty0
crw-------   1 root        4,  1 Mon 04:00:41   tty1  
crw-------   1 tom         4,  2 Mon 04:30:31   tty2
crw-------   1 root        4,  3 Mon 04:00:41   tty3
crw-------   1 root        4,  4 Mon 04:00:41   tty4
crw-------   1 root        4,  5 Mon 04:00:41   tty5
crw-------   1 root        4,  6 Mon 04:00:41   tty6
crw-------   1 root        4,  7 Mon 03:58:52   tty7
crw-------   1 root        4,  8 Mon 03:58:52   tty8
crw-------   1 root        4,  9 Mon 03:58:52   tty9
crw-------   1 root        4, 10 Mon 03:58:52   tty10  
crw-------   1 root        4, 11 Mon 03:58:52   tty11

所有这些 tty 设备,除了我已经为其打开控制台会话的设备外,都归 root 所有。为了能够登录其中一个,getty 之类的程序会临时更改其所有权。例如,在我的机器上执行 ps 显示

root      2977     1  0 04:00 tty1     00:00:00 /sbin/getty 38400 tty1          
root      2978     1  0 04:00 tty2     00:00:00 /bin/login --                   
root      2979     1  0 04:00 tty3     00:00:00 /sbin/getty 38400     tty3          
root      2980     1  0 04:00 tty4     00:00:00 /sbin/getty 38400 tty4          
root      2981     1  0 04:00 tty5     00:00:00 /sbin/getty 38400 tty5          
root      2982     1  0 04:00 tty6     00:00:00 /sbin/getty 38400 tty6

请注意 getty 是 运行 作为 root。这使它有权根据需要更改 tty 设备的所有权。也就是说,虽然 ioctl 可能 识别未使用的 tty,但您需要提升权限才能真正打开它。 Linux(与任何其他类 Unix 系统一样)没有办法确保一个进程对终端具有真正的独占访问权限。因此它使用设备所有权和权限来确保此访问。

如果您不是超级用户,那么您应该只尝试访问 /dev/tty。这是控制当前进程的 tty 的特殊设备同义词。