framebuffer注册源码解读

注册的源码解读

framebuffer主要是填充fb_info然后调用register_framebuffer()函数

获取到注册fb的锁之后,开始调用do_register_framebuffer

do_register_framebuffer

第一段

1622行,检查显示控制器的大小端配置是否与当前CPU的大小端兼容,如果不兼容,有没有转换支持

1625行,系统早期U-boot会提供一个极简缓冲区用来显示临时画面,当真的显卡驱动加载时,二者的显存物理地址会冲突,所以将之前旧的移除掉

1631-1643行,给当前fb找个合理的次设备号,同时增加系统中注册进去的fb数量

创建一个fb_class的类设备,并且带上主次设备号

device_create会在内核中创建对应的device实体,同时还会让devtmpfs创建/dev下的设备inode节点

对于/dev下fb对应的inode字符节点的统一file_operations,则是由fbmem_init进行创建的

它通过register_chrdev这个函数为一个主设备号(FB_MAJOR)下的0-255次设备号都映射到同一个file_operations,即fb_fops

同时创建fb_class为名为graphics的类

之后,fb的设备就会被注册为graphics类设备,同时由deftmpfs负责去/dev下创建对应的inode节点,到file_operations的映射由VFS(虚拟文件系统)通过主次设备号进行映射

第二段

这里的pixmap是给内核在屏幕上画图用的中转缓冲区,比如开机企鹅logo,还有fbcon在屏幕上输出控制台字符用的

如果当前显卡驱动没分配这块缓冲区,则这里按照默认配置分配一份

1664则是设置位图掩码,表示支持1到32像素宽高的字体

第三段

1670行,创建一个双向链表,用来保存当前屏幕支持的所有显示模式(分辨率、刷新率、时序等,即 struct fb_videomode)

1673行,控制休眠时需不需要切换图形界面到文本终端

1678,1679,这个地方实际上就是把可变参数固定下来,写到modelist中

因为可变参数在frame_buffer注册过程中,可能会因为一些原因被修改,所以最后这里固定下来(真正支持的参数),挂到modelist上

1680行,registered_fb[i]中的下标i对应着次设备号,这里就很方便让file_operations从这个全局数组拿到当前的fb_info结构体了

1683行,因为接下来马上要通知控制台子系统(fbcon)来接管这块新屏幕作为终端输出,而控制台子系统在内核中是由全局的console_lock保护的,所以这里获得该lock

1685行,对当前的fb_info也加锁,防止在广播注册事件的瞬间,被其他线程修改

1691行,**向所有调用过fb_register_client()的内核模块广播,**一个新的fb_info已经注册好了

  • 最核心的订阅者是 fbcon(Framebuffer Console) :当 fbcon 收到 FB_EVENT_FB_REGISTERED 事件后,它的回调函数 fbcon_fb_registered() 会立刻被触发,将该 fb_info 与虚拟终端(/dev/tty1 等)绑定,紧接着你就能在物理屏幕上看到开机企鹅 Logo 了
  • 这个通知机制实际上是调用挂在该事件上的所有函数
    如果要让该fb打印出控制台信息,还需要修改启动参数,将控制台输出重定向到该tty,一般是tty1

fb_fops

这里和v4l2需要维持复杂的vb2_buffer和v4l2_buffer之间的转换来从内核态与用户态之间转换数据不同

往fb写数据的位置 本质上是写一块DDR中分配的给显卡读的(即显存)专用的内存区域

在不开启垂直同步的情况下,直接往里写数据,显卡负责自己按照配置好的刷新率从这个DDR分配的内存区域读取数据

这种读取数据的方式不是DMA,而是由于显示控制器本来就是一个总线设备,其能自己通过总线读取总线地址上的数据

所以它还是需要参与总线仲裁与竞争

总线地址是SOC设计的时候就规划好的,DDR只是挂在其中的一块区域

显示控制器通过总线地址访问的时候实际上走的是DDR控制器

当给出一段总线地址比如 0x8000_0000 + 0x1234

bash 复制代码
总线地址:  0x8000_1234
            │
            ├─ 高位 [31:28] = 0x8  → 解码出"这是 DDR 窗口"
            ├─ 中位           → 行地址 (row)
            └─ 低位           → 列地址 (column) + bank
相关推荐
LongRunning12 小时前
【Linux】RK3568-OpenCV+YOLO(八)
linux·opencv·yolo
Zwawa15 小时前
屏幕不止一种:OLED、LCD1602字符屏、TFT/IPS图形屏和串口屏怎么用,这与TTY和PTY又有什么关系
c语言·单片机·嵌入式
民乐团扒谱机15 小时前
【微实验】NSGA-II(非支配排序遗传算法)——解决多目标优化问题的“自然选择模拟器”
linux·人工智能·算法
물の韜16 小时前
ZYNQ/FMQL系列Linux之I2C开发实战
linux·arm开发·嵌入式硬件·设备树·iic·zynq
qq_3718021116 小时前
Ubuntu Linux中安装WorkBuddy
linux·运维·服务器·ubuntu
无足鸟ICT16 小时前
【RHCA+】iptraf-ng(网络监控分析)
linux·网络
独隅16 小时前
WebStorm 在 Linux 环境下的实战安装与高效开发指南
linux·ide·webstorm
坤坤子吖18 小时前
Linux网络编程:TCP服务器的多进程与多线程实现
linux·服务器·开发语言·网络·c++·笔记·学习
阡陌数智18 小时前
Claude API新版本重大变更与安全升级指南
java·linux·安全
奶茶树19 小时前
【Linux】环境开发工具(vim,gcc,g++,Makefile)
linux·运维·vim