计算机的软件如何与硬件交流?

计算机的软件如何与硬件交流

在我们知道什么是软件,什么是硬件的时候,我们就要思考一个事情了: 既然用了硬件才有软件,此时它两有什么关系呢?
我可以说,它们的关系就在于互相通信、软件访问硬件、硬件通知软件。
软件所做的操作,最终都会通知硬件来做相应的处理的。
而硬件也可以主动向软件发起通信,告诉软件要做什么。

简单的软件硬件交流过程

比如我要打开一个软件,此时就要移动鼠标,或者按快捷键,此时鼠标、硬盘作为硬件,就会告诉操作系统这个软件(我将鼠标移动到某(X,Y)坐标,你帮我记录一下这个坐标,或者是我刚刚按了Ctrl+E快捷键,系统系统,你帮我执行相关的操作吧),此时操作系统就会记录鼠标的位置,再通知显示屏硬件,跟显示屏说,请在(X,Y)坐标上生成我指定的光标图片(也就是鼠标图片样式)。于是我们就能看见鼠标移动到了指定的位置,之后双击也同理,由鼠标通知操作系统,操作系统判断出点击位置是什么东西后,执行相应的操作(比如打开软件),最终还是要告诉显示屏,这个软件霸占了多少个(X,Y)格子,要求显卡跟显示屏互相交流从而显示软件样貌出来。

真正的软件硬件交流过程

上面只是一种不严谨的表达,我只是介绍了软件硬件是怎么大致配合与交流,实际上它们交流要复杂的多。比如,我们操作系统想通知硬件去做相应的操作,而硬件有可能在执行先前的操作,来不及下一步的操作,此时操作系统的总不可能一直向硬件发起通知吧,就像你打电话给一个在忙音的人,他知道你要跟他交流,可他在忙,也交流不了,你也只能一直打电话给他,希望他接受,而你打电话的过程你什么都做不了,只能等待。
所以,为了避免这个过程,咱们计算机科学家就利用一种硬件,该硬件叫内存,内存你把它想象成一个空间,咱们的计算机程序、数据都可以往这个空间存放,它就是一个储物地方。
有了内存后,咱们的操作系统就可以跟要交流的硬件达成一条约定,彼此将要通信的数据放在内存中,等自己忙完了就从内存A中按一定的排队规则领取所需的数据,进行下一步运算,忙完后将运算结果放回内存B,之后又从内存A中拿到想要的数据去重复上面的操作,哦,这一切就变得仅仅有条了。说个题外话,这种思想是不是很像现在现实生活中的邮局,咱们投递邮件或者寄快递,只需要将我们所需要发送的东西放到信箱或者快递柜中,自然就有人来接收并且传递给你想要传递的对象,对象忙完有空了就可以去接受这个东西。在一些场景中,为了提高系统的处理速度、响应时间,更加有效的利用计算资源,就出现了一种叫消息队列的东西,其思想就是这个了。哈哈,搞网页开发的同学应该挺熟悉了吧。

然而,你读到这里,仍然不是真正的软件与硬件访问流程,不过快了,在介绍软件访问外部硬件之前,有两个术语你需要了解。

标准

在技术和规范的语境中,"标准"指的是一组共同约定的规则、规范、准则或规程,旨在确保在特定领域或行业中实现一致性、互操作性和可互换性。标准的制定通常由专门的标准化组织或机构负责,这些组织致力于协调和制定行业、国家或国际范围内的标准。

计算机中的接口是根据协议制作的(接口在下面有介绍),协议是根据标准规则定制的,而规则是由相关的计算机委员会开会商量出来的,而计算机委员会中的成员都是计算机行业中的大佬,所以就是大佬们开会制定了一系列的规则,希望通过统一的接口来减少这样的兼容性问题。所以以后计算机学习,你学到XXX接口、XXX协议、XXX标准,实际上就是解决兼容性,方便你我的东西。

再说一点吧,在计算机早期发展的时候,有新东西出来都是没有标准、没有规则、没有接口的,而各家为了争夺有利场景,都会推崇自己家的驱动、标准,最终使用者最高的那家获胜,而获胜者就有了定义该标准所有权,所以早期计算机蓬勃发展的时候,什么标准、驱动都有,各种神奇操作都有,所以也导致了开发者头大的混乱场景,比如我们都吐槽IE浏览器的网页容易出问题,这就是因为IE浏览器一直都不支持某些定义的网页标准导致的,所以早期网页开发者花费了很多时间在IE浏览器适配网页上,而近代基本由w3c、mozilla、谷歌、微软、苹果之类的行业委员会拍板了不少通用的网页开发标准,所以现在网页前端开发不会再多少苦恼网页适配兼容性的问题了,前端混乱的百家争鸣到此告一段落。

接口

实际上不单单计算机有接口,现实生活中也有接口,我更倾向于接口这词源自于其他工程领域定义出来的,最终移植进了计算机里面,比如网络开发的套接字Socket接口,名字灵感来源应该就是生活中那些电路板插槽的Socket(槽)。

在计算机上,我们会常常听见接口这个词,接口是根据协议写代码写出来的,被开发者使用的东西。就像你平时电路板是不是也有插槽,那个东西就是接口,最终我们利用不同的插头插进去插槽从而使用接口、“调用”接口。

严谨的说,"接口"通常指的是两个系统、设备或组件之间的连接点或交互方式。它定义了它们之间的通信规则、数据格式、协议以及可以交换的信息类型。接口在计算机中起到了桥梁的作用,使得不同的系统或设备可以相互通信和协作。

计算机中的接口可以有多种类型,包括以下几种常见的:

  1. 硬件接口:硬件接口是用于连接计算机的硬件设备的接口。例如,USB、HDMI、VGA、Ethernet等是常见的硬件接口类型,用于连接外部设备如打印机、显示器、网线等。

咱们手机充电线Type-C也是一种接口,用的U盘也是一种USB接口,像现在的显示屏一般都是HDMI接口,你们可以看一下你电脑连的那条线是不是扁长的,如果是蓝色很大块头的可能就是VGA口了,Ethernet的话是网卡硬件接口。

主板上的PCIE接口,显卡基本插这里了,当然也可以插其他的支持PCIE的硬件,比如PCIE兼容的硬盘
计算机的接口
2. 软件接口:软件接口是用于不同软件模块或应用程序之间进行通信的接口。例如,应用程序编程接口(API)是一种软件接口,允许不同的应用程序之间共享功能和数据。开发上咱们说的软件接口一般都是指API。

  1. 用户界面接口:用户界面接口是用户与计算机系统进行交互的接口。它可以是图形用户界面(GUI,Graphical User Interface)或命令行界面(CLI,Command Line Interface),用户通过这些接口与计算机进行沟通和操作。

这里说的很高大上,实际上GUI相当于你平时看到的页面,打开的软件、命令行的界面,至于为什么要说成接口,是因为该界面只负责展示,具体的数值计算逻辑都在另外的地方处理,当数据处理完后就会传输到这个界面中进行展示,如果用户在这个界面点击了之类的,就会传输点击了什么到数据处理的地方进行逻辑执行,也就是计算逻辑代码与负责数据展示的代码解耦了,分离了,这样就不会因为修改计算逻辑代码影响展示界面原有的代码,或者修改界面的代码影响原有的计算逻辑代码。

  1. 网络接口:网络接口是计算机连接到网络的接口。它可以是以太网接口、Wi-Fi接口等,允许计算机通过网络与其他计算机进行通信和数据传输。

我觉得网络接口要分两种吧,一种是硬件网络接口,一种是软件网络接口。硬件的网络接口相当于你插网线的RJ45接口,你可以顺着你家路由器的网线找到它。而软件网络接口则是我们平时说的网卡驱动,负责连接操作系统与网卡硬件交流的一种特殊软件。
RJ45网卡接口
网卡驱动接口

  1. 应用程序编程接口:API(Application Programming Interface)是一组定义在软件中的接口,它允许不同的软件模块或应用程序之间进行交互。通过API,程序可以请求其他模块或服务执行特定的功能或获取特定的数据。

很多学编程的小白都会听到API这词,经常有人说我调库的API就可以了,或者是调API就完事了这样的话,实际上API本身上就可以是一个函数、一个接口(编程语言上的面向对象才有的东西),不过我觉得不管它是什么,你只要理解为有一个东西,你想要获取一些数据的时候,你把你要查询的内容输入给它,它自然会根据你要求的东西返回给你,这种就可以说是一个接口,只不过这个接口对于函数来说会更加抽象,因为它实用性更广泛,比如它支持查询不同公司的卖家信息、买家信息,我们只要传入公司这个参数进去,就会给我们显示不同的公司买卖家信息,而我们并不用思考它是怎么做到的,我们只要无脑传入我们想要的数据,它就会提供我们想要的数据。举例这个可能还不太好,所以我让GPT生成了个通俗易懂的例子,看看大家能不能感受一下吧。

GTP: 什么是API?

小明:喂,我听说你很懂计算机,能不能告诉我什么是API?

小李:当然可以!你看,API就像是一家汉堡店的点餐窗口。

小明:点餐窗口?我听不懂……

小李:没关系,听我继续说。想象你现在坐在汉堡店的外面,你不能直接进入厨房告诉厨师你要什么汉堡,对吧?

小明:对对对,那太乱了!

小李:没错,所以汉堡店搞了一个点餐窗口,顾客只需要在窗口告诉服务员想要什么汉堡,然后服务员会把你的需求传达给厨师。这样,顾客和厨师之间的交流就变得有条不紊了。

小明:哦!我明白了,API就是汉堡店的点餐窗口,让软件和硬件能够有序地交流!

小李:对对对,没错没错!软件通过API就像顾客通过点餐窗口告诉厨师自己想要什么,而API会把软件的需求传达给硬件或其他软件模块。这样,软件和硬件之间就可以愉快地合作啦!

小明:太好了,终于搞懂了,谢谢你的解释!

小李:不客气,随时欢迎!快来点餐,汉堡可好吃了哦!

小明:好的,那我来一份API特制汉堡!

哈哈,我觉得GPT的描述也不太好,大家还是到时候写多点代码就自然感受到API是什么了。

最后,接口的设计和实现对于计算机系统的性能、可靠性和可扩展性至关重要。良好设计的接口能够提供清晰简洁的交互方式,并促进系统模块化,使得不同的组件可以独立开发和维护,从而提高系统的可维护性和可扩展性。

软件访问外部硬件的方式

别看它好像好多种方式,实际上本质都是对内存操作来实现的,最后面我会解释一下的。

驱动程序

你要是想知道你电脑有啥驱动,或者想更新卸载驱动,那就下载个驱动精灵看个够吧,高级点的是在硬件供应商官网查询它发布的驱动,像我买了耳机、音箱,要更新驱动的时候都是直接找官网去下载,之后通过软件以及我耳机插电脑USB后进行驱动、固件更新的。(固件相当于一个操作系统的内核了,跟驱动不同的哦)

定义:操作系统通常提供一组标准的驱动程序接口,允许软件通过驱动程序来访问硬件。驱动程序是一种特殊的软件,它允许操作系统与硬件交互,并向上层软件提供抽象接口。通过调用驱动程序的API,软件可以与硬件进行通信。

首先,软件与硬件可以直接进行交流,但要根据硬件要求的规则去访问,不同的硬件会有不同的规则,所以我们会遇到一个问题。
比如在Window操作系统上的软件要去访问键盘,去获取键盘A发过来的信息,这时候就要针对键盘A的开发手册去发送消息,去接收消息。这里写的软件与硬件交流的程序 被称之为驱动(Driver),驱动也是一种特殊的软件,它的作用在于操作系统和应用程序通过驱动来与硬件进行通信,驱动程序提供了一种抽象接口,隐藏了底层硬件的细节,使得上层的软件可以使用统一的API来访问不同类型的硬件设备。
问题来了,如果用户将键盘A换成了键盘B,这时候软件又要去修改自己的代码,以达到兼容键盘B的一些特有功能。
可是,世界上键盘这么多,我总不可能为了不同键盘而写不同的代码去兼容识别吧…… 就像世界上有这么多的国家,咱们互相交流多麻烦,不如都学英语,统一用英语交流就好了。
虽然驱动程序需要针对不同的硬件设备进行编程,但为了避免为每种键盘都编写一个全新的驱动程序,通常会采用一些抽象层和标准化的接口。这样一来,大多数键盘都可以共用同一个通用的驱动程序,只需要对少数特殊键盘进行定制化处理就可以了。
说个题外话吧,如果你是从小接触计算机,曾经有帮过人同学之类的装系统,你就会接触到安装驱动的事情,你会发现安装不同的显卡驱动会有不同的性能影响,或者缺少显卡驱动、网卡驱动,电脑就显示不了东西,或者上不了网。这就是因为软件层跟操作系统层访问不到硬件的信息,硬件接收到了数据都传不到咱们电脑系统层上处理,所以就出现显示不了跟上不了网的事情,这一切都是驱动在搞鬼。

硬件抽象层(HAL,Hardware Abstarct Level)

一些操作系统提供硬件抽象层,它是介于操作系统内核和硬件之间的一层接口。HAL提供一组标准的API,使软件可以在不考虑具体硬件细节的情况下与硬件交互。
提一嘴,咱们网络开发的Socket层并不属于硬件抽象层,它是属于软件层面的抽象,用于在应用程序之间建立通信通道,而不涉及具体的硬件细节。(不理解没关系,以后网络开发就会接触的了!)
实际上硬件抽象层跟驱动的目标都是一样的,即将软件与底层硬件解耦,使得软件在不考虑具体硬件细节的情况下可以与硬件交流。(这里就体现了计算机一些特性——解耦性、封装、黑箱,在减少代码之间的依赖同时还尽可能少暴露接口内容给调用者知道,调用者只需要负责调用就好了,不用管里面代码是怎么写的。)

硬件抽象层主要做了以下几件事情:

  1. 提供统一接口:HAL为软件提供一个统一的、抽象的硬件访问接口。软件可以通过调用这些统一的接口来访问硬件,而无需了解具体硬件的实现细节。(是不是很像驱动,但硬件抽象层做的事情比驱动做的事情更广泛)

  2. 隐藏底层硬件细节:HAL隐藏了底层硬件的复杂性,使得软件不需要关心硬件的具体寄存器、电路等细节。软件只需使用抽象的接口进行硬件访问,而无需直接与硬件通信。

  3. 提供硬件配置信息:HAL通常包含了一些硬件配置信息,如设备的ID、寄存器地址、中断号等。这些信息对于正确地与硬件设备进行交流至关重要。

  4. 支持平台独立性:HAL使得软件可以在不同的硬件平台上运行,因为它屏蔽了硬件差异,为不同硬件提供了相同的接口。

一些硬件抽象层的案例包括:

  1. Windows的硬件抽象层(HAL):在Windows操作系统中,有一个名为硬件抽象层(HAL)的组件,它负责将具体的硬件细节与操作系统内核分离,为内核提供一个统一的硬件接口。这使得Windows可以在不同的硬件平台上运行,而无需修改内核代码。

  2. Linux的设备树(Device Tree):在Linux内核中,设备树是一种数据结构,用于描述硬件设备的连接和配置信息。设备树允许Linux内核在启动时动态识别硬件,并加载相应的驱动程序,从而实现硬件抽象。

  3. Android的硬件抽象层(HAL):Android操作系统使用硬件抽象层(HAL)来实现在不同设备上运行的能力。HAL允许Android系统和硬件供应商分开开发,使得Android系统可以适配各种不同类型的设备。

  4. macOS的I/O Kit:在macOS中,I/O Kit是用于驱动程序开发的框架。它提供了一组面向对象的API,允许开发者编写驱动程序,实现与硬件设备的交互。

这些硬件抽象层在不同的操作系统中实现了类似的功能,即将底层硬件的细节与上层软件隔离,为软件提供一致的、高级别的硬件访问接口,从而实现跨硬件平台的兼容性。

I/O端口访问

在一些计算机体系结构中,特定的指令用于访问I/O(输入/输出)端口。软件可以使用这些指令来读取或写入硬件设备的状态和数据。
I/O端口访问通常需要特权级别较高的权限,因此在现代操作系统中,普通用户程序无法直接进行I/O端口访问。这是出于安全考虑,以防止用户程序直接操纵硬件设备。通常,为了安全起见,访问硬件设备需要通过设备驱动程序,由操作系统提供相应的API来进行间接访问。
在x86架构的计算机中,I/O端口实际上是一种特殊的内存地址。x86处理器将I/O端口地址与内存地址分开,这样在进行I/O操作时就不会影响常规内存的读写。在内存地址空间中,有一部分地址专门用于I/O端口,称为I/O地址空间。

在x86架构中,可以使用两个专用的指令进行I/O端口访问(这里学汇编语言才会碰到):

  1. IN指令:用于从I/O端口读取数据到寄存器。例如,IN AL, DX表示从I/O端口地址存储在DX寄存器中的端口读取一个字节的数据,并将其放入AL寄存器。

  2. OUT指令:用于将数据写入I/O端口。例如,OUT DX, AL表示将AL寄存器中的数据写入DX寄存器中存储的I/O端口。

I/O端口的地址通常比常规内存地址小,通常是16位或32位,这取决于系统的架构和设定。为了避免与常规内存地址冲突,操作系统会保留一定的地址范围用于I/O端口。

内存映射IO

这是一种将硬件寄存器映射到系统内存地址空间的技术。软件可以通过读写特定的内存地址来与硬件设备进行通信。 内存映射I/O的主要目的是为了方便软件与硬件之间的交互,并提供一种统一的编程模型,使得软件可以通过常规的内存读写指令来访问硬件设备,而无需使用特殊的I/O指令
不同的I/O指令可能是因为硬件不同而导致的,现在内存映射I/O就解决了这个问题,不管你是什么硬件,只要获取到硬件的内存地址,将它映射到我们操作系统上的内存空间中的内存地址后,直接对操作系统上的内存地址用咱们操作系统识别的内存读写指令进行操作内存就可以实现对硬件的控制了,不然就要用上面的I/O端口访问方式去修改硬件的寄存器来达到软件与硬件交流。

虽然理论上可以直接将硬件设备的寄存器映射到常规的内存地址上,但这样做会带来一些问题和限制:

  1. 硬件资源冲突: 现代计算机系统中,内存地址空间已经被大量的RAM(随机访问存储器)和其他设备(如显卡、网卡等)所占用。如果直接将硬件设备的寄存器映射到常规内存地址上,可能会导致内存地址冲突,造成系统不稳定或崩溃。(所以要划分好内存映射的地址,避免与现有的软件、硬件使用的内存地址冲突)

  2. 特权级别限制: 硬件设备通常需要更高的特权级别来访问,而普通应用程序只能在低特权级别下运行。直接在应用程序中访问硬件寄存器可能会违反系统的安全策略,并导致潜在的安全漏洞。

  3. 硬件抽象: 内存映射I/O允许操作系统或设备驱动程序在底层抽象出硬件设备的细节,为软件提供一个更高级别、更简化的硬件访问接口。这使得应用程序开发更容易,并且允许在不同硬件平台上运行相同的应用程序。

通过内存映射I/O,操作系统可以在内存地址空间中为硬件设备分配一组专用的I/O地址,而不会与常规内存地址冲突。当应用程序需要与硬件设备进行交互时,只需使用常规的内存读写指令,就可以直接读写这些专用的I/O地址,从而与硬件设备进行通信。这样,硬件设备的控制和管理可以更加简化和灵活,同时也确保了系统的安全性和稳定性。

关于内存映射I/O与端口I/O的区别

内存映射I/O和I/O端口访问是两种不同的访问硬件设备的方式,它们在计算机体系结构中有一些区别:

  1. 地址空间:

    • I/O端口访问:I/O端口访问是通过专门的I/O指令(IN和OUT)来读写设备的寄存器,这些寄存器的地址在单独的I/O地址空间中。通常,I/O地址空间的地址范围较小,通常是16位或32位,并且是单独分开的,不与常规内存地址重叠

    • 内存映射I/O:内存映射I/O将设备的寄存器映射到计算机的常规内存地址空间中。通过将设备寄存器的地址映射到内存地址,软件可以使用常规的内存读写指令(如mov指令)来读写设备寄存器,这样就实现了与设备的交互。

  2. 指令集:

    • I/O端口访问:I/O端口访问需要使用特殊的I/O指令(如IN和OUT)来进行读写操作,这些指令是专门用于访问I/O端口的。例如,在x86架构中,使用IN和OUT指令进行I/O端口访问。

    • 内存映射I/O:内存映射I/O使用常规的内存读写指令来进行读写操作,如mov指令。由于设备寄存器映射到内存地址,因此可以像访问内存单元一样使用这些指令进行设备的读写操作。

  3. 权限级别:

    • I/O端口访问:I/O端口访问通常需要更高的特权级别,普通用户程序无法直接进行I/O端口访问,需要通过设备驱动程序或操作系统提供的API来间接访问。

    • 内存映射I/O:内存映射I/O可以在用户程序的上下文中直接进行访问,因此相对于I/O端口访问,更容易在用户空间进行硬件访问。

  4. 使用场景:

    • I/O端口访问:I/O端口访问通常用于直接与外部设备(如串口、并口、显卡等)进行交互,或者用于与特定硬件设备进行低级别的通信。

    • 内存映射I/O:内存映射I/O通常用于将硬件设备的寄存器与内存地址空间进行映射,为软件提供统一的接口,从而更方便地访问硬件设备。

总的来说,I/O端口访问和内存映射I/O都是访问硬件设备的方式,选择使用哪种方式取决于具体的应用场景和硬件设备的要求。内存映射I/O在一些情况下更方便,并且允许更高级别的硬件访问接口,而I/O端口访问则适用于一些需要直接控制硬件寄存器的场景。

中断

硬件设备可以通过中断来通知CPU它们的状态或需要处理的事件。软件可以通过中断处理程序响应这些中断,并与硬件设备进行交互。
实际上中断本质是修改一个内存地址上一些标记符内容,软件层跟硬件层通过这个标记符来做出不同的响应。

硬盘中断的例子

当计算机系统需要进行硬盘读写操作时,通常会使用硬盘中断来实现异步的数据传输。这样,CPU可以继续执行其他任务,而不需要等待硬盘读写操作的完成。以下是一个简单的硬盘中断例子,假设计算机系统需要从硬盘中读取数据:

  1. 应用程序请求读取硬盘数据。

  2. CPU将硬盘读取请求转发给硬盘控制器,并设置好要读取的磁盘扇区的地址、读取数据的目标内存地址等参数。

  3. 硬盘控制器开始读取硬盘数据,同时发出一个中断请求(硬盘中断)给CPU。

  4. CPU收到硬盘中断请求后,暂停当前任务的执行,保存当前任务的状态(包括程序计数器、寄存器值等)。

  5. CPU跳转到预定义的硬盘中断处理程序(中断服务例程)开始执行。在这个例程中,CPU会将硬盘读取到的数据从硬盘控制器复制到应用程序指定的内存地址。

  6. 硬盘中断处理程序执行完毕后,CPU恢复之前被中断的任务的状态,并继续执行被中断的任务。

通过硬盘中断,CPU可以在硬盘读取数据的过程中执行其他任务,而无需等待硬盘读取操作的完成。这样可以提高计算机系统的整体效率和响应性。

需要指出的是,硬盘中断是一种硬件中断,由硬盘控制器生成并发送给CPU。处理硬盘中断的中断处理程序通常由操作系统提供,用于管理硬盘读写操作,以及处理其他硬盘相关的事件和错误。通过硬盘中断,计算机系统可以高效地进行硬盘数据传输,从而实现对硬盘的有效管理和利用。

设备文件

在类Unix系统中,硬件设备通常表示为文件。软件可以通过读写这些设备文件来与硬件进行通信。例如,在Linux中,/dev目录下的设备文件用于访问硬件设备。实际上这种也是内存映射I/O的一种特例,将硬盘的数据映射到内存上,之后再对数据进行操作。虽然设备文件可以通过内存映射来实现硬件访问,但并不是所有的设备文件都采用了内存映射方式。一些设备文件可能使用其他的方法来实现硬件访问,取决于操作系统的设计和设备驱动程序的实现。

USB和其他总线协议

对于外部设备,如USB设备,软件可以通过遵循特定的总线协议与这些设备进行通信。

软件与硬件的访问本质是对内存的操作

上面我说了那么多方式,形式上看起来不同,但它们的原理都离不开对内存的操作。

软件访问硬件的方式本质上涉及对内存的操作。
在现代计算机体系结构中,CPU(中央处理器)与内存之间的交互是非常快速和高效的,而与硬件设备直接通信的速度通常较慢。因此,为了方便和加快软件与硬件之间的交互,通常采用将硬件设备的寄存器或状态映射到内存地址空间的方式。

无论是读取硬件设备的状态、写入控制命令,还是进行数据的输入和输出,都涉及对内存的操作。这些操作可以通过访问特定的内存地址或者通过内存映射来实现。

举例来说:

  1. 设备寄存器的读写: 许多硬件设备(如显卡、网络接口、串口等)都有寄存器用于存储控制信息或状态信息。软件可以通过读写这些设备寄存器的内存地址来与设备进行通信。

  2. 数据传输: 当软件需要从硬件设备读取数据时,硬件设备可以将数据写入到特定的内存地址,软件再从该内存地址读取数据。同样地,软件也可以将数据写入到特定的内存地址,然后由硬件设备读取这些数据。

  3. 中断处理: 当硬件设备发生中断事件时,它会通过修改处理器的状态和内存中的中断向量表来通知操作系统。这样,操作系统可以通过中断处理程序对中断事件进行处理。

大道至简

在我们知道软件跟硬件交流的本质是内存操作后,我希望你的思维能够更新一下,也就是逢看见软件硬件交流,想都不用想,就是两者对内存进行操作实现的,它们都可以约定对同一个内存地址上进行存数据,取数据,内存地址就像一座桥梁,拥有了承载数据的责任,而硬件跟软件,就是这座桥梁的两端。

而我们主要的软硬件交流方式有两个:

  1. 内存映射I/O
  2. 端口I/O
    实际上它们的原理都是一样的,对同一块内存地址、寄存器进行操作。只不过内存映射是将寄存器的地址映射到了我们计算机的内存中进行操作,而端口I/O是双方直接对规定好的寄存器进行操作。

我们可以看到维基百科中的简单系统内存映射表
简单的系统内存映射表

这里就划分了不同内存地址区域以及对应的外设,想要修改外设的一些数据、状态,咱们直接对这个内存地址进行读写就可以实现控制外设了。

在内存映射这里,我们看一下操作系统真相还原书中的例子即可:
操作系统真相还原-1
至于端口I/O这里也有一个简单的端口地址表给大家看看
简单的端口地址表

只要我们针对这些端口进行读写,就一样可以达到对外设的控制。
不过我们一般不会直接端口I/O,而是基于人家给我们写好的IO接口进行调用来实现对外设的控制,而IO接口的内部实现就是利用端口I/O达到软件硬件交流的能力。

还原操作系统真相-2

好了,以上就是软件与硬件交流的一些知识概念,希望你用餐愉快!

  • 6
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bali16

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值