39 printf 的输出到设备层的调试
前言
在前面 printf 的调试 我们只是调试到了 glibc 调用系统调用, 封装了参数 stdout, 带输出的字符缓冲, 以及待输出字符长度
然后内核这边 只是到了 write 的系统调用, 并未向下细看
我们这里 稍微向下 细追一下, 看看 到达设备层面 这里是怎么具体的 impl 的
测试用例
测试用例如下, 这里仅仅是一个简单的输出
(initramfs) cat Test01Sum.c #include "stdio.h"int main(int argc, char** argv) {int x = 2;
int y = 3;
int z = x + y;printf(" x + y = %d\n ", z);}
tty 输出的调试
接着 printf 的调试 的 vfs_write 的这里, 看一下 上下文, 待输出的字符串为 " x + y = 5\n"
然后 输出的 stdout 文件的 inode_no 为 7407

inode 7407 在这里对应的设备为
(initramfs) ls -ail /dev | grep console7407 crw------- 1 5, 1 console
设备 /dev/console
该字符设备初始化是在 tty_init 的时候进行初始化的
主设备号位 TTYAUX_MAJOR 为 5, 此设备号位 1, 相关操作 ops 为 console_fops
vfs 层面 write 操作映射到下层是 console_fops.redirected_tty_write

console_fops.redirected_tty_write

关于 tty->tty_ldisc->ops
这层抽象的设计, 等以后有所收获之后 再回来补充
文件关联的 tty 是来自于 file->private_data
这一层也有一层抽象, tty->tty_ldisc, 这里对应的是 n_tty_ops

process_output_block 根据 换行回车, 制表符 分割 输出数据到 tty
ntty_ops 输出是根据 tty->ops 来写出数据 
关于 tty->ops
这层抽象的设计, 等以后有所收获之后 再回来补充
拷贝待输出数据到 输出缓冲区, 然后 刷出缓冲区
此时暂时无输出
![]()
执行了 __uart_start 之后的某个时间点将待输出数据, 输出

此时输出情况如下
![]()
接下来是输出 " x + y = 5" 之后的这个 换行回车

此时输出情况如下

ntty 的初始化
ntty 是默认的 tty, 然后 start_kernel 的时候初始化 console 的时候, 首先注册了默认的 ntty 的相关 ops

tty 的初始化
kernel_init 的时候 serial8250_init 的时候注册了 ttyS 的驱动相关

kernel_init 的时候, 会尝试 open "/dev/console", 这里会触发 对应的 tty, 以及相关初始化

如下为 分配了 "/dev/console" 对应的 tty 的空间, 然后初始化 ldisc 为 n_tty_ops
上面初始化 ntty 将 ntty 注册到了 tty_ldiscs_lock

初始化 tty->ops 为 driver->ops, 上面的 uart_register_driver 中初始化 driver 的 ops 为 uart_ops

uart_ops 的定义如下

从 xmit 的 buf 输出到 8250串口
这里是接着上面的 __uart_start 之后产生了中断
然后这里具体的讲 xmit->buf 的数据输出到 8250串口
之所以叫串口 就是因为它是按照 单字节传输的, 这里循环 待处理的字符输出到 8250串口
将所有输出输出完成之后 会走 uart_circ_empty(xmit) 的判断, 进而 break 跳出循环

比如这里执行到 第五次循环, 剩余待输出字符为 5 个, "y = 5"

控制台输出如下
![]()
假设我们键盘录入 'a', 通过 8250 串口输出 'a' 到控制台
向 8250 串口依次输出的是
7 5 7 97 5 7 5
第一对 "7 5" 是 n_tty 缓冲区接收到 'a' 的输入之后
有一个 tty->ops->flush_chars, 因为缓冲区没有数据, 因此直接是一个开始字节, 一个结束字节

第一对中的 "5" 主要是 xmit->buf 中暂时没有待输出的 字节序列, 因此直接 传输了一个结束标记

开始字节中的 7, 主要是在 up->iter 中打上了 UART_IER_THRI 的标记, 由 0x101 变成了 0x111

结束字节中的 5, 主要是在 up->iter 中打上了 UART_IER_THRI 的标记, 由 0x111 变成了 0x101

开始, 结束 的 控制字符意义如下
7 表示 UART_IER_RDI + UART_IER_THRI + UART_IER_RLSI
5 表示 UART_IER_RDI + UART_IER_RLSI
#define UART_IER_MSI 0x08 /* Enable Modem status interrupt */
#define UART_IER_RLSI 0x04 /* Enable receiver line status interrupt */
#define UART_IER_THRI 0x02 /* Enable Transmitter holding register int. */
#define UART_IER_RDI 0x01 /* Enable receiver data interrupt */
第二对 "7 97 5" 主要是来自于输出了 'a' 到 "/dev/console"
开始标记, 输出第一个字节 "7"

'a' 输出到 8250 串口, 主要是来自于本文主讲的内容, 讲 xmit->buf 的数据输出到 8250 串口

第三个字节 "5" 的输出, 主要是 xmit->buf 中的输出完了之后发送的一个结束标记

第三对 "7 5" 主要是来自于 上面 ntty.n_tty_write 的流程中 process_output_block 之后
有一个 tty->ops->flush_chars 的流程
输出了一个 开始标记, 发现 xmit->buf 中暂无输出数据, 然后输出了一个结束标记 
完
相关文章:
39 printf 的输出到设备层的调试
前言 在前面 printf 的调试 我们只是调试到了 glibc 调用系统调用, 封装了参数 stdout, 带输出的字符缓冲, 以及待输出字符长度 然后内核这边 只是到了 write 的系统调用, 并未向下细看 我们这里 稍微向下 细追一下, 看看 到达设备层面 这里是怎么具体的 impl 的 测试用例…...
数字普惠金融、数字创新与经济增长—基于省级面板数据的实证考察(2011-2021年)
参照陈啸(2023)的做法,本对来自经济问题《数字普惠金融、数字创新与经济增长——基于省级面板数据的实证考察》一文中的基准回归部分进行复刻。数字普惠金融、数字创新已经成为驱动经济高质量发展的关键。利用省级面板数据,构建固…...
控制renderQueue解决NGUI与Unity3D物体渲染顺序问题
NGUI与Unity3D物体渲染顺序问题,做过UI的各位应该都遇到过。主要指的是UI与Unity制作的特效、3D人物等一同显示时的层次问题。 由于UI与特效等都是以transparent方式渲染,而Unity与NGUI在管理同是透明物体的render queue时实际上互相没有感知࿰…...
概率论与数理统计:第二、三章:一维~n维随机变量及其分布
文章目录 Ch2. 一维随机变量及其分布1.一维随机变量1.随机变量2.分布函数 F ( x ) F(x) F(x)(1)定义(2)分布函数的性质 (充要条件)(3)分布函数的应用——求概率3.最大最小值函数 2.一维离散型随机变量及其概率分布(分布律)3.一维连续型随机变量及其概率分布(概率密度)4.一般类型…...
BOLT- 识别和优化热门的基本块
在BOLT中,识别和优化热门的基本块之所以关键,是因为BOLT的主要目标是优化程序以更好地利用硬件特性,特别是指令缓存(ICache)。以下是BOLT如何识别和优化热门基本块的流程: 收集性能数据: BOLT开始的时候并不…...
Golang 中的 time 包详解(四):函数详解
在日常开发过程中,会频繁遇到对时间进行操作的场景,使用 Golang 中的 time 包可以很方便地实现对时间的相关操作。接下来的几篇文章会详细讲解 time 包,本文讲解一下 time 包中的函数。 func Now() Time 返回当前的系统时间。 package mai…...
【前端 | CSS】5种经典布局
页面布局是样式开发的第一步,也是 CSS 最重要的功能之一。 常用的页面布局,其实就那么几个。下面我会介绍5个经典布局,只要掌握了它们,就能应对绝大多数常规页面。 这几个布局都是自适应的,自动适配桌面设备和移动设备…...
腾讯云宣布VPC网络架构重磅升级,可毫秒级感知网络故障并实现自愈
8月11日,腾讯云宣布VPC(Virtual Private Cloud,云私有网络)架构重磅升级。新架构采用多项腾讯核心自研技术,能够支撑用户构建业界最大 300万节点超大规模单VPC网络,并将转发性能最大提升至业界领先的200Gbp…...
vue 路由页面跳转
从index.vue跳转到data.vue index.vue <el-table-column label"客户数" align"center" :show-overflow-tooltip"true"><template slot-scope"scope"><router-link :to"/system/enterprise-data/index/ scope.ro…...
Vue toRefs:在Vue中不失去响应式的情况下解构属性
Vue toRefs:在Vue中不失去响应式的情况下解构属性 文章目录 Vue toRefs:在Vue中不失去响应式的情况下解构属性什么是响应式?解构Props的挑战使用toRefs保持响应式结论 在Vue开发中,我们经常会在组件之间传递数据。这时候ÿ…...
自定义element-plus的弹框样式
项目中弹框使用频繁,需要统一样式风格,此组件可以自定义弹框的头部样式和内容 一、文件结构如下: 二、自定义myDialog组件 需求: 1.自定义弹框头部背景样式和文字 2.自定义弹框内容 3.基本业务流程框架 components/myDialog/index.vue完整代码: &…...
Linux:iptables防火墙
目录 绪论 1、防火墙 1.1 保护范围 1.2 网络协议划分 1.3 协议:tcp 1.4 四表 1.5 五链 1.6 iptables的规则 1.7 匹配顺序 流入本机:prerouting ------->iuput---------->用户进程(httpd服务)------请求--------响应--------->数据要返…...
MongoDB文档-进阶使用-spring-boot整合使用MongoDB---MongoTemplate完成增删改查
传送门: MongoDB文档--基本概念_一单成的博客-CSDN博客 MongoDB文档--基本安装-linux安装(mongodb环境搭建)-docker安装(挂载数据卷)-以及详细版本对比_一单成的博客-CSDN博客 MongoDB文档--基本安装-linux安装&…...
设计模式十四:责任链模式(Chain of Responsibility Pattern)
责任链模式(Chain of Responsibility Pattern)是一种行为设计模式,它允许你将请求沿着处理者链进行传递,直到有一个处理者能够处理该请求。 在责任链模式中,多个处理者对象被连接成一个链。当接收到一个请求时…...
将商城项目放到docker-centos7中
1、docker pull centos:7 2、docker run -d -it --privileged 仓库名称/shopcentos:1.1 /usr/sbin/init 注意: /usr/sbin/init 必须加,否则没法使用systemctl启动mysql 3、安装mysql教程 安装msyql教程:https://blog.csdn.net/davice_li…...
C# Winform 自动获取 软件版本号
C# Winform如何自动获取版本号 方案一 缺点是不适配,clickones发布的版本 public static string GetVersion() {try {return System.Deployment.Application.ApplicationDeployment.CurrentDeployment.CurrentVersion.ToString();}catch{return System.Ref…...
基于C++实现了最小反馈弧集问题的三种近似算法(GreedyFAS、SortFAS、PageRankFAS)
该项目是一个基于链式前向星存图、boost(boost::hash、asio线程池)以及emhash7/8的非官方实现,实现了最小反馈弧集问题的三种近似算法。该问题是在有向图中找到最小的反馈弧集,其中反馈弧集是指一组弧,使得从这些反馈弧…...
奶牛用餐 优先队列 java
👨🏫 奶牛用餐 约翰的农场有 n n n 头奶牛,编号 1 s i m n 1 \\sim n 1simn。 每天奶牛们都要去食堂用餐。 食堂一共有 k k k 个座位,也就是说同一时间最多可以容纳 k k k 头奶牛同时用餐。 已知,第 i i i …...
包管理机制pip3
pip3 安装pip3 安装pip3 apt install python3-pip yum install python3-pip从仓库出发的命令 查询仓库信息 // 获取默认pip3源 pip3 config get global.index-url查询所有软件包 查询已经安装的所有软件包 pip3 list从软件包出发的命令 从软件包名出发查询其他信息 查询…...
liunx在线安装tomcat
1、在线安装 https://dlcdn.apache.org/tomcat/tomcat-8/v8.5.91/bin/apache-tomcat-8.5.91.tar.gz 执行:wget --no-check-certificate https://dlcdn.apache.org/tomcat/tomcat-8/v8.5.91/bin/apache-tomcat-8.5.91.tar.gz ps:或者直接把tar.gz扔服务器 2、 编…...
Mac M1芯片用户看过来:保姆级教程,用VMware Fusion搞定CentOS 8虚拟机(含网络配置与SSH连接)
Mac M1芯片用户实战指南:VMware Fusion运行CentOS 8虚拟机的完整解决方案 当Apple Silicon的M1芯片重新定义移动计算性能时,开发者和运维人员却面临ARM架构带来的新挑战。特别是在需要搭建Linux开发环境时,传统x86架构的解决方案已不再适用。…...
019、未来展望:IPFS、暗网与去中心化互联网的融合趋势
当内容寻址遇见匿名路由 IPFS的核心是内容寻址(CID),暗网(以Tor为例)的核心是匿名路由。二者在协议层本无直接关联,但在实际部署中却产生了有趣的互补。传统IPFS网络依赖公共DHT和引导节点,这些…...
Word报告自动化:用poi-tl的Markdown插件优雅生成多级标题并自动更新目录(Office版)
Word报告自动化:用poi-tl实现Markdown式标题管理与智能目录生成 在技术文档编写领域,我们常常陷入这样的困境:内容创作者更习惯用Markdown的简洁语法表达结构,而最终交付却不得不妥协于Word的复杂样式调整。poi-tl的MarkdownRende…...
Web应用渗透测试系统(Python)
Web应用渗透测试系统(Python) 项目介绍 系统简介 本项目命名为 Sec-Tools,是一款基于 Python-Django 的多功能 Web 应用渗透测试系统,包含漏洞检测、目录识别、端口扫描、指纹识别、域名探测、旁站探测、信息泄露检测等功能。 …...
深入GStreamer插件生态:从good、bad、ugly到libav,如何为你的项目选对‘轮子’
深入GStreamer插件生态:从good、bad、ugly到libav,如何为你的项目选对‘轮子’ 在多媒体开发领域,GStreamer以其灵活的管道架构和丰富的插件生态著称。但面对good、bad、ugly和libav四大插件集,开发者常陷入选择困境:是…...
ESP32 RMT实战:手把手教你用ESP-IDF驱动WS2812灯带(附完整代码)
ESP32 RMT实战:手把手教你用ESP-IDF驱动WS2812灯带(附完整代码) 在智能家居和物联网项目中,可编程RGB灯带因其丰富的色彩表现和灵活的编程能力而广受欢迎。WS2812作为其中最具代表性的产品之一,仅需单线控制即可实现全…...
如何下载huggingface数据
使用 Hugging Face 新版 CLI 工具 hf 下载数据集(国内镜像加速版) 在进行机器学习和深度学习项目时,我们经常需要从 Hugging Face Hub 下载公开的数据集。然而,由于网络原因,国内用户直接访问 Hugging Face 官方源时往…...
Qwen2.5-VL-7B-Instruct在智能导航系统中的应用:牢记回家路
Qwen2.5-VL-7B-Instruct在智能导航系统中的应用:牢记回家路 想象一下,当你开车回家时,导航系统不仅能告诉你该走哪条路,还能认出你常去的超市、记得你喜欢的咖啡店,甚至提醒你:"今天常去的那家花店有新…...
Linux根目录扫盲:从/bin到/var,每个文件夹都是干嘛的?(附KDE桌面文件管理器实操)
Linux根目录探险指南:在KDE桌面中理解每个文件夹的使命 刚接触Linux的用户第一次打开文件管理器时,往往会被根目录下那一堆神秘的文件夹搞得一头雾水。这些看似随意的缩写背后,其实隐藏着Linux系统精心设计的组织逻辑。今天,我们就…...
Node.js连接SQL Server终极指南:node-mssql快速入门教程
Node.js连接SQL Server终极指南:node-mssql快速入门教程 【免费下载链接】node-mssql Microsoft SQL Server client for Node.js 项目地址: https://gitcode.com/gh_mirrors/no/node-mssql node-mssql是一款专为Node.js开发的Microsoft SQL Server客户端工具…...
