运行hellow world操作系统都做了哪些工作

透彻理解操作系统最好的方法之一就是查看当一个最简单的程序在计算机上运行时,操作系统都做了些什么。

我们以一个C语言版的“”“hello world”为例:

#include <stdio.h>
void main()
{
    printf("hello world\n");
}

这段程序被编译、链接之后会生成一个可执行文件。我们在Linux操作系统上运行这个程序,最终会在屏幕上输出“hello world”。表面上看,在屏幕上显示的“hello world”都是我们写的程序的功劳,其实我们写的程序只起到了很小的作用。很明显的是,这个程序里使用了C语言的库函数printf。
那么操作系统都做了哪些工作呢?
上面的代码我们编译生成一个名叫hello的可执行文件。

第一步:用户输入命令,shell进程被唤醒,对命令进行解析。

为实现这一步,系统将至少进行如下准备工作。

(1)用户敲击键盘后,键入的信息记录在终端设备文件(tty0)上。

如果系统要以文件的形式对终端设备进行操作,首先要构建一套文件系统,之后加载该文件系统,以便在此基础上对文件进行操作。这套文件系统包括“超级块”、“逻辑块位图”、“i节点位图”、“文件i节点”、“数据块”等。其次,还要根据文件的不同功能对数据进行分类,包括普通文件、设备文件、目录文件等。tty0就属于设备文件。有了这些准备才有可能对终端设备文件tty0进行操作。

(2)敲击键盘后,还要产生键盘中断信号,系统要能够对键盘中断信号进行处理。

首先,这个中断信号会通过可编程中断控制器8259A,所以要对8259A这个中断控制器进行设置,然后,信号会被传达给CPU,CPU要通过中断描述符表寄存器(IDTR)找到内存中的中断描述符表,再通过搜索中断描述符表找到键盘中断处理程序,并执行该程序。要实现这些操作,就要构建一整套中断服务体系,其中包括中断描述符表寄存器(IDTR)进行设置和建立一个中断描述符表,用以和中断服务程序相挂接,然后还要编写中断服务程序,以便能够为具体的中断动作服务。此外,还要将这些中断服务程序与中断描述符表相挂接。

(3)中断服务程序开始执行后,唤醒shell进程,之后通过进程调度机制,由进程0切换到shell进程去执行。

这需要系统建立一整套进程管理机制。就shell来说,要创建进程并加载shell程序,这样才能构建人机交互界面;同时,还要创建一个进程0,并在其他进程都不处于就绪态时切换到进程0去执行,而且一旦有进程被唤醒,就又立即切换到该进程执行。这个机制要适用于操作系统中的所有进程。既然要支持多进程执行,就还要设计一套进程轮询机制,即产生时钟中断,导致进程切换。这个机制里面又有很多问题需要考虑,比如时钟中断服务程序的设计和8253定时器的设置,等等。

(4)shell进程通过执行自己的程序从tty0这个终端设备文件上读取用户键入的指令信息,然后解析该指令,并准备进行相应的处理。当然,这条指令不是敲击一次键盘就能输入的。每次敲击键盘,都会重复上诉动作,然后shell进程再次睡眠,并等待下一次键盘中断的产生。

到这里为止,系统仅仅是对用户键入符命令进行响应,正式处理还没有开始。

第二步:shell程序解析出用户命令后,调用fork函数创建一个用户进程,以便对hello world文件的程序进程控制。

系统在这里至少要为用户进程创建一套进程管理结构。每个进程都要有一套这样的结构,以便控制讲台加载的程序。这套结构十分复杂,包括时间片、优先级、进程状态、进程对应的文件、进程的任务状态描述符表(TSS),以及进程的局部数据描述符表(LTD),等等。其中的每一项又与系统的运行有着千丝万缕的关系。比如说TSS,它里面存放着当前进程运行时所有寄存器中的数据,一旦发生进程切换,系统就将当前各个寄存器中的数据存储在TSS中,同时用即将切换到的进程中的TSS中的数据来设置各个寄存器中的值,最后再切换。可见,这个TSS中的数据是进程切换的根本保障。再比如LDT,它里面存放着当前进程的代码段描述符和数据段描述符,这两个描述符都直接控制着进程所控制的程序,而进程运行的根本目的就是执行用户的程序。
另外,每个进程都会有TSS和LDT,为了便于管理,还需要再设计一套数据结构,就是全局描述符表(GDT)。所有进程的TSS和LDT大索引都存放在这个GDT中。系统为了方便操作GDT,并进一步操作LDT和TSS,还要对CPU中关于这三个表的专用寄存器进行设置,他们就是全局描述符表寄存器、局部数据寄存器和任务状态寄存器。
但仅有这些,还是远远不够的。系统启动之初是实模式,各个段寄存器中都是实际的地址值,直到进入保护模式,段寄存器中的数值才变成了段选择符,这样GDT才能参与应用,所以系统还要为实模式到保护模式的转换做全方位的准备工作。
以上这些只是针对TSS和LDT进行的展开分析。进程管理结构中其他成员与系统之间同样有着紧密的关系。例如,进程调度的最基本方式就是通过时间片轮转,而时间片轮转的最重要的参数数据就是当前进程的时间片。再例如,只有进程才能够操作文件,所以进程就要与文件全面建立关系,包括文件的i节点、文件管理表中的表项。进程自身的文件管理指针表,等等。
创建进程,就必须创建进程管理结构,而进程管理结构中的成员一个都不能少,都要创建并设置。除了进程管理结果就,创建进程的时候,还要为新进程复制页表和创建页目录项。这些都与内存页面的应用有直接关系,而内存的应用策略又是整个操作系统中最复杂的应用策略之一。

第三步:新进程创建完毕后,加载hello world文件对应的程序。

要完成这一步,进程就要在两方面进行全方位的准备:一方面是文件,另一方面是内存。hello world 程序一定是以可执行文件的方式存储在硬盘上的,所以,在文件加载之前一定要检测文件是否可用,主要表现在对文件i节点的检测和对文件头的检测两方面。i节点是文件的管理信息。只要涉及i节点,就一定离不开对i节点的查找,于是就要解析文件路径、操作目录文件和目录项、操作i节点表等,一件事情都不能少做。文件头存储在数据块中,要操作数据块又离不开逻辑块位图的支持,这样一来,整个文件系统中涉及的全部内容都要用到了。
具备了载入文件的条件后,就要将hello world文件载入到内存中了。这样系统就要解决所有与内存相关的问题,包括要与原来进程共享的页面接触关系,这就涉及页面引用计数、页面三级管理机制(页目录表、页表、页面)、页面数据(只读/可读可写)等一系列问题,系统就要为此简历页写保护等机制来解决这些问题。
但仅仅解决这些问题还远远不够,程序的加载也是很讲究策略的,其中最重要的就是缺页中断机制,即必须根据需要来分析是不是需要申请新的页面来加载程序的内容。为此又要对许多数据进行判断,这样才能确定加载的必要性,比如线性地址所对应的物理地址是否被映射到了线性地址空间内等,这就需要一套物理地址到线性地址的映射方案。另外,缺页中断机制的设计也很有讲究,缺页并不等于一定要把外设的程序加载进来。比如,由压栈导致的缺页同样要申请新的页面来载入数据,但这与外设一点关系都没有。这些都是缺页中断机制设计时需要全面考虑的问题。
总之,hello world程序的加载,几乎涉及文件管理与内存管理的各个方面。而且,以上所诉还仅仅是针对hello world这一个进程加载所进行的最基本的介绍。Linux是支持多进程执行的,每个进程都有可能加载自己的程序,而文件和内存有事所有程序可以共用的资源,他们之间还存在着更为复杂的管理悬系。比如,两个进程加载同一个hello world文件时,设计要不要共享,如何共享,共享后页面的引用计数如何计算,读写属性如何确定,等等。

第四步:hello world程序开始执行,将“hello world”字符串显示在屏幕上。

hello world程序加载进内存后就要开始执行了。这个程序比较简单,就是讲hello world这个字符串显示到屏幕上。但是,即便如此,系统也要为此做很多的工作。其中最主要的就是关于显示方面的工作,比如,显卡属性如何确定,显卡是单色还是彩色;显存位置如何确定,显示在屏幕上的位置又如何确定;如果字符数量过多,要不要滚动显示,如何滚动显示,等等。这些问题都要操作系统来做,而且直接与显示器的底层交互。

通过以上四点,我们归纳出,操作系统的一部分任务是为应用程序的运行提供使用硬盘、显示器、键盘灯外设的基础程序,应用程序就必须写这些程序,而且所有应用程序都要写的这部分程序的内容也都差不多。所有,我们也可以把操作系统看成所有应用程序共有的部分。
像Linux这样的现代操作系统,不仅为应用程序提供了对外设的支持,还支持多个程序同时运行。这就要求操作系统不但要支持外设,还必须对运行的多个程序进行有效的组织、管理和协调,防止某个程序独占CPU、内存、外设等资源,使得其他程序无法正常运行。此外,还要防止正在运行的程序之间相互读写和相互覆盖,确保所有程序正确运行。最关键的是,操作系统不能被应用程序直接读写,更不能被应用程序覆盖

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,319评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,801评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,567评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,156评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,019评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,090评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,500评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,192评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,474评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,566评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,338评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,212评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,572评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,890评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,169评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,478评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,661评论 2 335