【1.7+1.8】系统漫游——操作系统管理硬件(包括网络)

        前面的hello程序中,它并没有直接跟硬盘、内存和显示器诸如此类的硬件直接打交道,而是通过操作系统,操作系统给应用程序提供的统一的接口,应用程序把命令传递给操作系统,由操作系统来直接控制硬件,过程中操作系统充当了中间人(或者说管理者)的角色。如下图所示:

         


        操作系统有两个基本功能:(1)防止硬件被失控的应用程序(因为应用程序来源多样化,并不能保证始终是“好”的)滥用,它自己要做资源分配和管理(2)给应用程序提供一个统一的接口,增加一“层”抽象,对多样的硬件进行“封装”,使应用程序员从复杂的硬件操作中解放出来,专心于功能设计。它通过几个抽象的概念来完成这两个功能,文件是对IO设备的抽象,虚拟存储器是对内存和磁盘IO设备的抽象,进程是对处理器、内存和磁盘IO设备的抽象。如下图所示:

       

扩展阅读:可以搜索unix和POSIX了解一下相关内容,posix主要是为了统一应用层接口,约束混乱的linux版本而生。

1、进程

        进程是程序的一次执行过程的抽象,是一 个有生命周期的动态的概念。当一个程序被启动运行,它就以“进程”这个实体被计算机系统来识别(从计算机系统的视角来看);同时,该程序运行需要的各种资源,都由进程结构体来体现,所以也可以认为进程是计算机系统(从程序的视角来看)的一个完整抽象。各个进程之间相互独立,每个进程都认为自己是独占计算机资源的,因为操作系统给每个物理"文件"(这里的文件包括物理设备和逻辑文件等)都提供了多个逻辑抽象,每个进程拥有一个,而每个进程都会认为自己拿到的“文件”是一个真实的文件。例如:进程a要使用打印机,a的进程信息里边就会有一个打印机(虚拟的),进程b要使用打印机,b的进程信息里边也会有1个打印机(虚拟的),但是实际上打印机只有1个(物理的),两个进程都不知道自己掌握的其实只是一个虚拟的映射,都以为是物理实体。同理,每个进程都认为自己独占整个计算机(多个资源的集合而已)的。其实生活中,这个例子并不少见,就像我们某些公仆有好几个老婆一样,在每个老婆眼中他都是老公,其实老公只有一个,他们只不过懂得分时复用罢了呵呵,看来这些人对计算机哲学理解的相当透彻啊!

        对于单处理机系统来说(双核机可以看做是两个单核机道理一样),进程数量远远大于处理机数量,那么为了系统高效利用,处理机采用分时复用技术分别依次给各个进程提供服务,处理进程请求。分时复用就设计到进程切换和上下文切换,上下文包括:程序计数器PC、寄存器文件、打开的资源列表等等。系统单个时刻只能给某一个进程服务,那么在进程切换时,就必须保存上一个进程的执行进度和现场信息,并且调入下一个要运行的进程上下文。

2、线程

        既然有了进程,为什么又出现了线程呢?答案就是效率。进程就是执行流和上下文的集合,当多进程之间进行频繁切换时,系统需要保存和切换进程的所有信息(执行流+上下文),对于实时要求比较高的场合,进程切换带来的开销就占了很大一块,这这些开销中“上下文切换”又占了大头儿。进程数量已经无法减少,那么就对“进程切换”下手。对进程进行进一步分解,进程 = 线程(执行流) + 上下文,属于一个进程的多个线程共享该进程的资源,处理器由进程切换进化到线程切换,降低切换开销提高效率。线程在网络服务中应用较广,因为网络服务器需要并发处理非常多的请求,降低等待时间;进程之间相对独立透明,所以共享数据需要用到操作系统的提供的手段耗时费劲,而线程之间共享数据则相对简单方便。

3、虚拟内存

        虚拟内存与物理内存相对,物理内存就是我们常见的硬件内存空间,每个字节有唯一的地址;虚拟内存是虚拟的假的,是操作系统对物理内存进行封装映射后提供给进程的内存空间。每个进程都有自己的虚拟内存,而且在它们眼中自己是独占内存的。例如进程a的虚拟内存为0-4G,进程b的虚拟内存是0-4G,而物理内存可能只有1G,操作系统通过内存映射技术,把物理内存映射到虚拟内存上,甚至硬盘空间都可以映射上去,操作系统能这么做的前提是:利用了进程代码的局部性原理,因为即便进程a的空间真的有4G,但是它在某一个时刻只能用到其中的某一很小的部分空间,操作系统完全可以把它暂时不用的空间分给进程b使用,把进程a其余的数据暂存到磁盘上等等。再如:进程a需要用到地址0x10003456,进程b也用到了0x10003456,显然只有一个物理空间0x10003456,为什么不冲突?因为每个进程的空间都是独立的相互透明的,操作系统给这两个进程使用不同的映射函数,这样虽然是同样的虚拟地址,映射到物理内存上肯定是不同的地址,而且这个物理地址甚至都不是物理地址0x10003456。

       每个进程的虚拟内存是一个“有组织”的空间,该空间被分成了多个“区”。如下图所示:

             

程序代码和数据:每个进程的代码都是从某一个固定地址(虚拟地址)开始,紧接着是全局变量数据区,代码和数据由代码文件直接初始化完成。其实,程序中定义的字符串常量就会保存在“只读的代码和数据”区中,因为代码和只读数据都不允许修改,所以它们放到一起是可以的,具体试验参照:玩儿转C语言:字符和字符串

堆:堆是动态内存分配区,大小随着程序的需要增长,C语言用malloc分配的内存空间就是从堆中取得的。

共享库:里边存放一些系统库文件,供程序调用。

栈:栈供函数调用使用,栈的大小随着函数调用和返回动态变化,函数非静态局部变量就是存在栈中,当函数返回时该变量也随之消失。

内核虚拟空间:这是操作系统的一部分给内核使用,应用程序不允许读写这里边的数据,也不允许直接调用内核的函数,如果想调用必须通过内核提供的接口,例如系统调用等。

基本思想:把进程虚拟内存的内容存放到磁盘中,内存做为磁盘的缓存,当用到哪一块了通过数据缺页指令从磁盘调到内存中再次执行。

4、文件

       linux的世界里一切皆“文件”,不管是硬件还是软件。这些简单的文件抽象,给应用程序员提供了一个统一简单的接口,使他们不必考虑硬件层的差异从而快速编程。例如:当调用显示部分函数时,用fopen打开,fwrite写数据,应用程序员并不需要因为显示器或者显示驱动器的改变而改变自己的函数。


带网络的系统

        接入网络的系统通过网络相互通信,从计算机的视角看过去,完全可以把网络当做一个IO设备来处理。计算机与另一个计算机通信,可以认为是计算机和网络模块通信,也可以认为是计算机和一个IO设备通信(与磁盘无异)。如下图所示:

      

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值