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、 编…...
UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...
eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)
说明: 想象一下,你正在用eNSP搭建一个虚拟的网络世界,里面有虚拟的路由器、交换机、电脑(PC)等等。这些设备都在你的电脑里面“运行”,它们之间可以互相通信,就像一个封闭的小王国。 但是&#…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
Appium+python自动化(十六)- ADB命令
简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...
边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...
.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
NLP学习路线图(二十三):长短期记忆网络(LSTM)
在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...
Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...
Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...
