22.IO与显示器

【README】

1.本文内容总结自 B站 《操作系统-哈工大李治军老师》,内容非常棒,墙裂推荐;

2.显示器是输入型外设;
3.本章主要内容是讲 显示器是如何被驱动的;或操作系统是如何让用户来使用显示器的;
4.Printf是如何把字符打在显示器上的;


【1】cpu操作外设背景

1)终端设备管理

  • 包括 键盘和显示器;

【图解】
本章主要讲中断 IO设备 ,包括键盘和显示器;

2)如何让外设工作起来 ;

【图解】
1)外设工作原理:

  • 步骤1:Cpu向外设控制器发出指令(如写命令),向外设控制器中的寄存器(或存储器)读写数据;如显卡控制器;
  • 步骤2:写入完成后,外设控制器发出中断请求通知cpu写入完成; 随后,外设控制器会根据寄存器(或存储器)的内容实际来操控外设;如显存;
  • 步骤3:cpu在处理外设控制器中断时,可能会读数据到内存,当然还会进行其他后续处理;

补充: cpu向外设控制器发送的指令示例。

  • out xx, al  , 其中xx是外设控制器端口,即cpu向外设端口发送命令;  

2)总结:cpu让外设工作起来做3件事情

  • 事情1: 向外设控制器发送out指令;
  • 事情2: 外设控制器执行指令完成后,发出中断请求,cpu处理中断;
  • 事情3: 为了让使用外设简单,操作系统要提供一种统一的文件视图(因为各个厂商外设控制器设计不一样,如接口不一样,数据格式不一样,所以要提供统一的文件视图,或统一接口),即把外设看做一个文件

 


【2】CPU操作外设

【2.1】操作外设的程序

printf 函数: 就是操作外设的程序;

【图解】

1)一段操作外设的程序

// 一段操纵外设的程序 
// 打开外设对应的文件(dev,device设备) 
int fd = open("/dev/xx"); 
for (int i=0; i<10; i++) 
{write(fd, i, sizeof(int)); 
}
close(fd); 

 2)操作系统为用户提供统一接口:

  • 无论什么设备都是,操作接口都是 open, read, write, close ;

3)根据设备文件找到控制器的地址,内容格式等;

  • 不同设备对应不同的设备文件 (/dev/xxx)

3)统一的文件视图


操作系统无论操作哪种设备,都需要调用统一的文件接口(文件视图),包括open,read,write,close ;


【2.2】输出到显示器

1)Printf 函数:

  • Printf不是真相,printf底层调用了 系统调用write 把数据写入到显存,
  • 而write系统调用或接口 最终会形成类似 out xx,al 指令发送给显存控制器 ;

 【图解】
1)系统调用 write

// 在 linux/fs/read_write.c 中 
// fd等于1,则写到显存; fd等于2,则写到打印机(举例)
// buf 对应内存缓冲区,要写出的数据先缓存到缓冲区,然后再写出到外设,如显存;
// count 写入字节数 
int sys_write(unsigned int fd, char *buf, int count) 
{struct file* file; // fd等于1,打开显示器(显存)的文件 // current 指的是当前进程pcb file = current->filp[fd]; // 获取文件信息 inode = file -> f_inode; 
}

补充: inode  

  • inode (index node)是指在许多“类Unix文件系统”中的一种数据结构,用于描述文件系统对象(包括文件、目录、设备文件、socket、管道等)。

2)fd=1的filp(文件指针)从哪里来 ?

【图解】
file = current->filp[fd];

其中fd=1;即fd=1对应到设备dev/tty0 ,而tty就是中断设备;
Open方法也是一个系统调用 sys_open ;

 

 小结:

  • write(1, buf, ...) 中的1 是 open(“dev/tty0”) 产生的;
  • 所以就形成了 父进程pcb文件指针 指向 dev/tty0的inode的链条;
  • 核心就是把 dev/tty0的设备信息放入(通过open系统调用)inode,并把inode读入内存;  
  • 根据inode把数据写入外设文件;

补充:inode (index node)是一种结构体用于描述文件信息 或用于描述文件系统对象(包括文件、目录、设备文件、socket、管道等)。

3)向显存(屏幕)写出数据

【图解】
Write系统调用 

// write 系统调用 
在 linux/fs/read_write.c 中 
int sys_write(unsigned int fd, char *buf, int cnt) 
{// 获取外设  /dev/tty0 的inode inode = file -> f_inode;// 判断是否字符设备; 计算机设备分为字符设备或块设备;  if (S_ISCHR( inode -> i_mode )) {// 读写字符,WIRTE 是写;// inode->i_zone[0]表示字符设备列表中的第几个设备的设备号(本例取4) ; return wr_char(WRITE, INODE->I_ZONE[0],buf, cnt) ; }
} 
// rw_char 
// 在 linux/fs/char_dev.c 中 
int rw_char(int rw, int dev, char *buf, int cnt) 
{// crw_table 表示字符设备操作的处理函数列表,其中 call_addr是函数指针; crw_ptr call_addr = crw_table[MAJOR(dev)]; call_addr(rw, dev, buf, cnt); ... 
}

4)字符设备处理函数列表 crw_table  (第4个字符设备处理函数是 rw_ttyx )

【图解】

  • 补充:终端设备指的是键盘和显示器; 其中键盘是读的,显示器是写的;
  • tty_write:写出数据到字符设备的核心函数; 其中 tty->write_q 是把数据写入到缓冲区(队列write_q);

4) tty_write(unsigned channel, char* buf, int nr) 写出数据的核心函数

 

【图解】
缓冲区写完之后,tty->wirte(tty) 把缓冲区数据刷新到显存(显卡)

5)tty->write(*write) 把缓冲区数据刷新到显存

【图解】

  • con_write  == console_write ;指的是显示器写函数(显存写入函数,属于显存驱动程序);
  •   从write_q队列或缓冲区中取出字符,并写入到显存;
  • Movb _attr, %%ah, 把属性值 送入 ax寄存器高位;
  • Movw %%ax, %1 把 ax 寄存器内容 写入到 外设控制器的存储空间(%1 指向pos指针);其中al存储了缓冲区字符,pos指针指向了显存基址(显存与内存统一编址,在同一个内存空间中);
  • con_write函数每次只能写出一个字符到显存,多个字符循环调用 con_write 即可;

补充1:

  • 有些外设控制器的寄存器地址(或存储器地址)可以与内存地址空间统一编址;寻址用mov;
  • 如果外设控制器的寄存器地址独立编址,寻址用out;
  • 即 mov 和 out 是一样的,没有本质区别;
  • 又显存特别大,通常是与内存统一编址,所以使用的是 mov汇编指令;

补充2:如何写设备驱动程序?

  • 步骤1:写出核心的out指令;
  • 步骤2:然后将相应函数注册到这些表上;
  • 步骤3:创建一个dev/xxx 外设文件;这个文件和你注册表上的设备名对应上;

【小结】
操作系统中最核心的kernel内核还是cpu进程管理与内存管理; 外围的设备驱动与文件系统很简单;

6)mov pos
把缓存区的数据写出到显存;

 

【图解】

  • 显存的初始地址pos 是由 con_init() 函数初始化的,pos从0xA0000 开始 ;

6)修改 pos 显存

  • pos +=2  
  • Pos 指向了显存基址;每写入一个字符到显存后,pos指针都会加2;因为写入一个字符占1个字节,字符属性占1个字节,所以是加2,往后移动2个字节;

 


 【3】printf 整个过程 

【图解】

  • 步骤1:调用printf 库函数;
  • 步骤2:调用系统调用 sys_open 打开终端文件 "dev/tty0" 获得设备号fd(显示器的设备号是1),和文件指针file;
  • 步骤3:传入设备号fd 调用系统调用 sys_write;sys_write 通过文件指针找到外部设备文件的inode,判断该文件是否是字符文件;
  • 步骤4:若是字符文件,则通过 inode 从 字符设备操作函数数组  crw_table  中查询 设备操作函数指针 rw_ttyx (外设文件读写函数);
  • 步骤5:rw_ttyx 设备操作函数 通过传入的 WRITE标识 调用 tty_write() 函数写出数据到外设文件;
  • 步骤6:tty_write函数 先把数据写出到缓冲区(或队列) write_q;
  • 步骤7:写出数据到缓冲区 write_q 完成后,调用 显示器写函数 con_write();
  • 步骤8: con_write() 把缓冲区的字符循环写入到 显存; 写入显存命令为 mov pos,c ; pos+=2;其中 pos指针指向了显存基址;每写出一个字符,pos自加2;因为写入了2个字节,pos需要向后移动2个字节;1个字节是字符内容,1个字节是字符属性; 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/329431.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

d3 i5 神舟精盾k480n_神舟精盾k480n i5 d3和精盾i5 d1哪个好?

(这是D3的数据)主板芯片组IntelHM76CPU系列英特尔酷睿i53代系列CPU型号Intel酷睿i53210MCPU主频2.5GHz最高睿频3100MHz总线规格DMI5GT/s三级缓存3MB核心类型IvyBridge核心/线程数双核...(这是D3的数据)主板芯片组Intel HM76CPU系列英特尔 酷睿i5 3代系列CPU型号Intel 酷睿i5 32…

[开源 .NET 跨平台 数据采集 爬虫框架: DotnetSpider] [一] 初衷与架构设计

一 &#xff0c;为什么要造轮子 有兴趣的同学可以去各大招聘网站看一下爬虫工程师的要求&#xff0c;大多是JAVA&#xff0c;PYTHON甚至于还有NODEJS&#xff0c;C&#xff0c;再或者在开源中国查询C#的爬虫&#xff0c;仅有几个非常简单或是几年没有更新的项目。从我看的一些文…

Oracle入门(十三B)之高级查询(上)

下章&#xff1a;Oracle入门&#xff08;十三C&#xff09;之高级查询&#xff08;下&#xff09; 一、多表格查询 &#xff08;1&#xff09;定义将两个或两个以上的表格&#xff0c;按照一定的关系连接起来进行查询。&#xff08;2&#xff09;多表格查询分类 连接查询嵌套查…

23.键盘

【README】 1.本文内容总结自 B站 《操作系统-哈工大李治军老师》&#xff0c;内容非常棒&#xff0c;墙裂推荐&#xff1b; 2.键盘 是输出型外设&#xff1b; 【1】外设工作原理 【图解】外设工作原理&#xff1a; 步骤1&#xff1a;Cpu向外设控制器发出指令&#xff08;如…

like左匹配索引失效_Mysql索引失效的情况

一、前提条件1、创建三张测试表&#xff1a;DROP TABLE IF EXISTS user;CREATE TABLE user (idint(11) NOT NULL,name varchar(25) DEFAULT NULL,ageint(11) NOT NULL DEFAULT 0,update_time datetime DEFAULT NULL,first_name varchar(25) DEFAULT NULL,last_name varchar(25)…

基于DDDLite的权限管理OpenAuth.net 1.0版正式发布

距离上一篇OpenAuth.net的文章已经有5个多月了&#xff0c;在这段时间里项目得到了很多朋友的认可&#xff0c;开源中国上面的Star数接近300&#xff0c;于是坚定了我做下去的信心。最近稍微清闲点&#xff0c;正式推出1.0版&#xff0c;并在阿里云上部署了一个在线演示&#x…

24.原生磁盘的使用

【README】 1.本文内容总结自 B站 《操作系统-哈工大李治军老师》&#xff0c;内容非常棒&#xff0c;墙裂推荐&#xff1b; 2.磁盘操作抽象 第1层抽象&#xff1a;通过盘块号读写磁盘&#xff08;或逻辑盘块号&#xff09;&#xff1b;第2层抽象&#xff1a;用队列缓存多个…

Oracle入门(十三C)之高级查询(下)

上章&#xff1a;Oracle入门&#xff08;十三B&#xff09;之高级查询&#xff08;上&#xff09; 四、常见组函数 SUM、AVG、COUNT、MIN、MAX分组函数忽略null 值。不能在WHERE 子句中使用组函数。MIN 和MAX 可用于任何数据类型&#xff1b;SUM、AVG只能用于数字数据类型五、子…

微软将降低Visual Studio对操作系统的影响

在过去几年中&#xff0c;为了将Visual Studio变成Windows上的第一开发工具&#xff0c;而不管用户的目标平台是什么&#xff0c;微软作出了重大努力。最近收购Xamarin及通过大力支持开源工具来支持非Windows设备&#xff0c;极大地增加了它对于各类开发人员的用处。这一做法的…

代码设置margintop_关于元素设置margin-top能够改变body位置的原因及解决(子元素设置margin-top改变父元素定位)...

关于元素设置margin-top能够改变body位置的原因及解决(子元素设置margin-top改变父元素定位)起因&#xff1a;在进行bootstrap的.navbar-brand内文字设置垂直居中时采用line-height高度&#xff0c;无法居中&#xff0c;发现源码.navbar-brand 设置了 padding: 15px 15px;(默认…

Oracle入门(九A)之用户的权限或角色

转载自 查看Oracle用户的权限或角色 前几天被问到一些关于权限和角色的问题&#xff0c;今天抽时间总结一下如何查看Oracle用户的权限或角色&#xff0c;在之前的博文中&#xff0c;写过 SYS,SYSTEM,DBA,SYSDBA,SYSOPER的区别与联系 以及 Oracle中定义者权限和调用者权限案例分…

25.从生磁盘到文件

【README】 1.本文内容总结自 B站 《操作系统-哈工大李治军老师》&#xff0c;内容非常棒&#xff0c;墙裂推荐&#xff1b; 2.文件&#xff1a;煮熟的磁盘&#xff0c;或熟磁盘&#xff1b; 本节的主要内容是讨论 如何从文件得到盘块号&#xff1b; 3.磁盘操作抽象&#xf…

Storm 1.0.1发布 .NET 适配也已到来

Apache Storm 1.0.0刚发布不久&#xff0c;1.0.1版本也在几天前到来&#xff1b;该版本主要是完成一些BUG修复和小的改进&#xff0c;通过一段时间新版本的使用&#xff0c;特将个人感受和一些遇到的问题归纳如下&#xff1b;另外 .NET 版本的 Storm 适配器也已经发布&#xff…

布隆过滤器速度_详解布隆过滤器的原理、使用场景和注意事项

今天碰到个业务&#xff0c;他的 Redis 集群有个大 Value 用途是作为布隆过滤器&#xff0c;但沟通的时候被小怼了一下&#xff0c;意思大概是 “布隆过滤器原理都不懂&#xff0c;还要我优化&#xff1f;”。技术菜被人怼认了、怪不得别人&#xff0c;自己之前确实只是听说过这…

Oracle入门(十四)之PL/SQL

一、PL/SQL 基本语法 PL/SQL语言是模块式的过程化SQL,是oracle公司对SQL的扩展。 &#xff08;1&#xff09;&#xff08;2&#xff09;&#xff08;3&#xff09;&#xff08;5&#xff09;&#xff08;6&#xff09;&#xff08;7&#xff09;数据类型Number 数字型Varchar2 …

26.文件使用磁盘的代码实现

【README】 1.本文内容总结自 B站 《操作系统-哈工大李治军老师》&#xff0c;内容非常棒&#xff0c;墙裂推荐&#xff1b; 2.文件内容复习&#xff1a; 1&#xff09;如何从生磁盘抽象为文件&#xff1f; 核心是从字符流位置算出盘块号&#xff1b;2&#xff09;如何算出盘…

.NET Core全新的配置管理[共9篇]

提到“配置”二字&#xff0c;我想绝大部分.NET开发人员脑海中会立马浮现出两个特殊文件的身影&#xff0c;那就是我们再熟悉不过的app.config和web.config&#xff0c;多年以来我们已经习惯了将结构化的配置信息定义在这两个文件之中。到了.NET Core的时候&#xff0c;很多我们…

redis存opc_KEPServerEX6完整免费版

KEPServerEX6完整免费版是一款先进的连接平台&#xff0c;主要用于为您的应用程序提供单一来源的工业自动化数据&#xff0c;通过连接、管理、监视和控制不通的自动化设备和应用程序来实现工业数据。具有严谨的技术特征&#xff0c;支持多达250种以上的通讯协定&#xff0c;可连…

Oracle入门(十四B)之PL/SQL异常处理

定义&#xff1a;程序执行过程的警告或错误成为例外(Exception) 一、常见预定义错误 二、非预定义错误及用户定义错误 &#xff08;1&#xff09;非预定义oracle错误其他标准的oracle错误,可以自定义异常名&#xff0c;将其与指定oracle错误关联&#xff0c;由系统触发。 例子…

C#读书雷达 | TW洞见

大家都知道&#xff0c;ThoughtWorks的技术雷达每年都会发布两到三次&#xff0c;它不但是业界技术趋势的标杆&#xff0c;更提供了一种卓有成效的方法论&#xff0c;即打造自己的技术雷达。在这种思想的驱动下&#xff0c;我们诞生了自己的读书雷达。但这份雷达略显high level…