控制台驱动¶
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
这些文件代表什么?
bind - 这是一个读/写文件。读取时显示驱动状态,写入时用于将驱动绑定或解除绑定到虚拟控制台。可能的值为
- 0
表示驱动未绑定,如果执行 echo 命令,则指示驱动解除绑定
- 1
表示驱动已绑定,如果执行 echo 命令,则指示驱动进行绑定
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.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()
将检查驱动是否已绑定。
控制台驱动编写者指南¶
为了使绑定和解除绑定控制台功能正常工作,控制台驱动必须遵循以下准则
所有驱动(系统驱动除外)都必须调用 do_register_con_driver() 或 do_take_over_console()。do_register_con_driver() 只会将驱动添加到控制台的内部列表。它不会接管控制台。do_take_over_console(),顾名思义,也将接管(或绑定到)控制台。
所有在
con->con_init()
期间分配的资源都必须在con->con_deinit()
中释放。所有在
con->con_startup()
中分配的资源都必须在驱动(之前已绑定)解除绑定时释放。控制台层没有与con->con_startup()
互补的调用,因此由驱动检查何时可以合法释放这些资源。在con->con_deinit()
中调用con_is_bound()
会有所帮助。如果调用返回false()
,则可以安全地释放资源。必须确保这种平衡,因为当重新绑定驱动到控制台的请求到达时,con->con_startup()
可能会再次被调用。驱动退出时,请确保驱动完全解除绑定。如果满足条件,驱动必须调用
do_unregister_con_driver()
或give_up_console()
。do_unregister_con_driver()
也可以在驱动无法服务控制台请求的条件下调用。这可能发生在突然失去所有驱动的帧缓冲控制台上。
当前的控制台驱动应该仍然可以正常工作,但绑定和解除绑定它们可能会导致问题。通过最少的修复,这些驱动可以正常工作。
Antonino Daplas <adaplas@pol.net>