控制台驱动

Linux 内核有两种通用类型的控制台驱动。第一种类型在引导过程中由内核分配给所有虚拟控制台。这种类型将被称为“系统驱动”,并且只允许存在一个系统驱动。系统驱动是持久的,它永远不能被卸载,尽管它可能会变为非活动状态。

第二种类型必须显式加载和卸载。本文档将其称为“模块化驱动”。多个模块化驱动可以随时共存,每个驱动与其他驱动(包括系统驱动)共享控制台。但是,模块化驱动不能接管当前被另一个模块化驱动占用的控制台。(例外:调用 do_take_over_console() 的驱动无论占用控制台的驱动类型如何,都将成功接管。)它们只能接管被系统驱动占用的控制台。同样,如果模块化驱动被控制台释放,系统驱动将接管。

从程序员的角度来看,模块化驱动必须调用

do_take_over_console() - load and bind driver to console layer
give_up_console() - unload driver; it will only work if driver
                    is fully unbound

在较新的内核中,以下也可用

do_register_con_driver()
do_unregister_con_driver()

如果 sysfs 已启用,可以检查 /sys/class/vtconsole 的内容。这显示了系统当前注册的控制台后端,其命名为 vtcon<n>,其中 <n> 是 0 到 15 的整数。因此

ls /sys/class/vtconsole
.  ..  vtcon0  vtcon1

/sys/class/vtconsole 中的每个目录都有 3 个文件

ls /sys/class/vtconsole/vtcon0
.  ..  bind  name  uevent

这些文件代表什么?

  1. bind - 这是一个读/写文件。读取时显示驱动状态,写入时用于将驱动绑定或解除绑定到虚拟控制台。可能的值为

    0
    • 表示驱动未绑定,如果执行 echo 命令,则指示驱动解除绑定

    1
    • 表示驱动已绑定,如果执行 echo 命令,则指示驱动进行绑定

  2. name - 只读文件。以这种格式显示驱动名称

    cat /sys/class/vtconsole/vtcon0/name
    (S) VGA+
    
        '(S)' stands for a (S)ystem driver, i.e., it cannot be directly
        commanded to bind or unbind
    
        'VGA+' is the name of the driver
    
    cat /sys/class/vtconsole/vtcon1/name
    (M) frame buffer device
    
        In this case, '(M)' stands for a (M)odular driver, one that can be
        directly commanded to bind or unbind.
    
  3. uevent - 忽略此文件

解除绑定时,模块化驱动首先被分离,然后系统驱动接管该驱动腾出的控制台。另一方面,绑定操作会将驱动绑定到当前被系统驱动占用的控制台。

注意1

绑定和解除绑定必须在 Kconfig 中选择。它位于

Device Drivers ->
    Character devices ->
            Support for binding and unbinding console drivers
注意2

如果任何虚拟控制台处于 KD_GRAPHICS 模式,则绑定或解除绑定将不会成功。将控制台设置为 KD_GRAPHICS 的应用程序示例是 X。

此功能有多大用处?这对控制台驱动开发者非常有用。通过将驱动从控制台层解除绑定,可以卸载驱动、进行更改、重新编译、重新加载并重新绑定驱动,而无需重新启动内核。对于可能希望从帧缓冲控制台切换到 VGA 控制台,反之亦然的普通用户,此功能也使其成为可能。(注意注意注意:请阅读 Documentation/fb 下的 fbcon.txt 以获取更多详细信息。)

开发者须知

do_take_over_console() 现已分解为

do_register_con_driver()
do_bind_con_driver() - private function

give_up_console()do_unregister_con_driver() 的一个封装,并且驱动必须完全解除绑定才能使此调用成功。con_is_bound() 将检查驱动是否已绑定。

控制台驱动编写者指南

为了使绑定和解除绑定控制台功能正常工作,控制台驱动必须遵循以下准则

  1. 所有驱动(系统驱动除外)都必须调用 do_register_con_driver() 或 do_take_over_console()。do_register_con_driver() 只会将驱动添加到控制台的内部列表。它不会接管控制台。do_take_over_console(),顾名思义,也将接管(或绑定到)控制台。

  2. 所有在 con->con_init() 期间分配的资源都必须在 con->con_deinit() 中释放。

  3. 所有在 con->con_startup() 中分配的资源都必须在驱动(之前已绑定)解除绑定时释放。控制台层没有与 con->con_startup() 互补的调用,因此由驱动检查何时可以合法释放这些资源。在 con->con_deinit() 中调用 con_is_bound() 会有所帮助。如果调用返回 false(),则可以安全地释放资源。必须确保这种平衡,因为当重新绑定驱动到控制台的请求到达时,con->con_startup() 可能会再次被调用。

  4. 驱动退出时,请确保驱动完全解除绑定。如果满足条件,驱动必须调用 do_unregister_con_driver()give_up_console()

  5. do_unregister_con_driver() 也可以在驱动无法服务控制台请求的条件下调用。这可能发生在突然失去所有驱动的帧缓冲控制台上。

当前的控制台驱动应该仍然可以正常工作,但绑定和解除绑定它们可能会导致问题。通过最少的修复,这些驱动可以正常工作。

Antonino Daplas <adaplas@pol.net>