进程从硬盘读取文件的过程

在知乎回答的一个问题,贴在这里 CPU与硬盘关系的几点疑问? - 中央处理器 (CPU) - 知乎

CPU 和硬盘的关系是不太好描述,CPU 本质上只是用来执行指令,具体的读取文件的操作是操作系统来做的,从操作系统的角度来说可能要方便一些。像其他答案说的,你的这些疑问应该去看操作系统和计算机组成原理相关的教材,形成一个整体上认识,而不应该片面的了解某一个方面。

我下面简单叙述一下操作系统在从硬盘读文件的流程。

为简单起见,假设场景是一个x86体系的32位Linux操作系统中运行的进程 P 需要读取文件 /home/user/test.txt,文件系统使用 ext3。

  1. Linux 系统提供了和 IO 相关的系统调用,进程 P 如果要读取文件,首先需要发起系统调用(System Call) open,传入文件路径”/home/user/test.txt” 和相关参数,来打开文件,执行系统调用以后操作系统会从用户态转换到内核态,部分 CPU 提供了”trap”或者”syscall” 指令来完成状态切换,切换到内核态以后,操作系统调用相应的处理器(handler) 开始处理读取文件的请求。
  2. 系统调用 open 并不会直接读取文件内容返回给进程,而是先进行权限方面的检查,如果进程可以访问这个文件,就根据文件路径去查找文件对应的 inode 编号。这部分属于文件系统的内容,在这里简单说一下,每一个非软链接的文件或者目录都具有一个惟一的 inode 编号,对应 inode table 中的一个 inode 数据结构,inode 中包含文件大小,修改时间之类的元信息,也包括一个树形的结构,这个树形结构里面索引了文件内容存储在硬盘的哪些扇区(sector)里。每个目录也有一个对应的磁盘文件来存储该目录中直接包含的子文件或子目录的名字和 inode 编号。比如查找”/home/user/test.txt”,需要按照路径逐级查找,首先根目录 / 的 inode 编号是约定的,为2,操作系统通过 inode 编号2这个信息去 inode table 中找到根目录对应的 inode 信息,根据 inode 信息读取磁盘扇区获取文件内容(这里已经需要访问磁盘了,下面再详细说访问过程),里面存储的内容比较复杂,为了提升检索效率可能会使用 B+树之类的进行了索引,这里为描述方便,简化一下,比如 根目录下有3个目录home、etc、bin,1个文件 eg.txt,那么根目录对应的文件内容大概类似于
     home 3
     etc 4
     bin 5
     eg.txt 5
     

    后面的数字就是目录或者文件对应的 inode 编号,通过检索可知,我们需要的找到 home 目录的inode 编号为3,重复这个过程,直到定位到 /home/user/test.txt 的 inode 编号。文件系统所有的 inode 信息也是存储在硬盘上的,也就是说硬盘中不仅有文件内容,还有文件系统的数据,这可以解释你的第二、三个问题,为什么换了硬盘仍然能够开机和识别文件,开机是存储在主板上的 BIOS 引导的,操作系统启动以后从硬盘读取文件系统的数据就可以获得整个磁盘的文件信息,CPU 只是执行操作系统的指令。

  3. 在获取 inode 以后,操作系统生成了一个文件描述符(file descriptor),存储在进程 P 自己的 file descriptors 数据结构中,通过文件描述符可以索引到文件的打开方式(只读、读写等)还有 要打开文件的 inode。然后操作系统将文件描述符返回给进程 P,至此系统调用 open 完成。
  4. 进程 P 获取到文件 /home/user/test.txt 的描述符以后,还需要再发起系统调用 read,传入文件描述符来读取文件内容,同样读取操作需要切换到内核态由内核代为完成。切换到内核态以后,操作系统通过文件描述符找到对应的 inode ,通过 inode 来确定文件存储在磁盘哪些扇区中,然后向磁盘发送指令来读取这些扇区,把内容读取到内核的地址空间里面。一般来说操作系统会通过 memory mapped IO 技术把键盘、磁盘等硬件上的寄存器连接到 IO 总线,再通过 IO 控制器连接到内存总线,这样硬件上的寄存器也被映射到了一段内存地址上,CPU 可以直接通过读写内存的指令来读写硬件寄存器中的数据。同时还会通过 DMA 技术来让硬件不通过 CPU,直接读写内存的内容,这样磁盘在传输文件的同时 CPU 可以去执行其他线程。
  5. 磁盘的 IO 操作完成后,磁盘会触发一个中断(interrupt),CPU 会暂时中止当前线程的执行,保存相关的寄存器信息后,调用对应的中断处理器(interrupt handler),把读取到的内容从内核地址空间拷贝到进程 P 的地址空间里面,然后将进程 P的状态设置为 runnable, 进程 P 排队等待自己的 CPU 时间片,被调度器调度以后可以继续执行。

支持中文搜索的gitbook

如何安装

fork项目地址: codepiano/gitbook · GitHub

官方仓库地址: GitbookIO/gitbook · GitHub

由于使用的分词插件模块nodejieba,是使用nodejs对c++库的封装,所以安装依赖的时候要求机器上安装有c++编译环境

windows的情况我不了解,linux使用的是g++,mac使用clang ,可能需要安装一下 command line tools ,具体安装方式请google

npm install -g codepiano/gitbook

添加的插件

  1. 集成多说评论,见 codepiano/gitbook-plugin-duoshuo
  2. 集成畅言评论,见 codepiano/gitbook-plugin-changyan

    进行的主要改动

  3. 支持中文搜索 需要生成所有文章内容的json格式索引文件,内容过多的话需要注意文件的体积,开启压缩的话应该不会造成太大的负担
  4. 支持搜索后关键字高亮
  5. 支持分享到qq、微信(二维码)
    • 分享到qq直接跳转至qq connect分享页面,该页面也可实现分享到qq空间和qq微博的功能
    • 分享到微信直接生成二维码,也可分享到其他平台
    • 需要在配置文件中设置相关选项为true
  6. 修改了介绍页面(即生成网站的主页)的方式,增加了一个新的指定方式
    • 原始的gitbook介绍页面文件名必须为README.md,只可以自定义标题名称
    • 修改后可以在配置文件book.json中指定介绍页面的标题和文件(相对)路径,可以不在SUMMARY.md文件中指定,在book.json中添加

        "introduction": {
            "path": "你的介绍文件的路径",
            "title": "你的介绍文件的标题"
        }
        
  7. 可以在目录栏底部添加自定义链接,在book.json中添加配置项

     "tail": {
         "tilte1": "url1",
         "title2": "url2"
     }
     
  8. 不再把google、facebook、twitter分享设置为默认,所有分享需要在配置文件中设置,才会出现在分享栏。

     "links": {
         "sharing": {
             "all"      : true,
             "google"   : true,
             "facebook" : true,
             "twitter"  : true,
             "weibo"    : true,
             "qq"       : true,
             "qrcode"   : true
         }
     }
     
  9. 为了便于SEO,添加了keywords的meta标签,可以在book.json中配置

     "keywords": "keyword1,keyword2,keyword3"
     

溯洄于时光的洪流

总是在不知不觉中,迎来又一个新年,仿佛清晨被人从酣睡中唤醒:“喂,再不起床就迟到了”,你的大脑瞬间紧绷,一切事物都被慌张和焦急浸湿、染色,这个世界被重新拧紧了发条,秒针的每一声嘀嗒都清晰可辨。时间和生活逐渐远去,就像追赶不上的公车,最后你终于发现并且承认,这一年又被消磨掉了。

不知道从什么时候,开始感觉时间不够用,于是想办法利用零碎时间来看书,成为习惯后才意识到,时间真的像海绵里面的水,只要你愿意,可以挤出来很多,以前还无知的认为这种名人名言除了作为考试题没有任何价值。如《道德经》所说:“上士闻道,勤而行之;中士闻道,若存若亡;下士闻道,大笑之。不笑,不足以为道”,无知且自以为能确实非常愚蠢。两年前给自己定了目标,争取每周看一本书,通过对零碎时间的利用,一直坚持了下来,由于上半年时间比较充裕,还超额不少,这或许是我长这么大惟一值得骄傲的事情,如果有精力,会一直坚持下去。

庆幸在很早的时候就接触了新浪微博和知乎,有机会了解到很多聪明的人,从他们的言论里面获得了很多经验和知识,经常有听君一席话,胜读十年书的感觉。同时将很多“不知道自己不知道”转变成“知道自己不知道”,借用知乎的一句宣传词,就是“发现更大的世界”,免得成为坐井观天的夜郎。

经过一年的尝试,英文阅读水平进步很大,看了一二十本英文书了,阅读速度达到了可以接受的程度,尽量做到了有原版书的情况下不读译本。而且互联网上的很多知识,也是别人读了英文的资料,再加工出来的,这个过程失真和噪声很大。现在回想起来,当初决心看英文书籍的原因也很简单,一是发现别人的知识来源基本都是英文,帮人解答问题都是直接给英文资料链接,二是关注的刘未鹏 | Mind Hacks | 思维改变生活推荐的书籍基本都是英文的。现在回想起来,对零碎时间的利用也受了他那篇《暗时间》的影响。还记得看的第一本英文书是《Hackers and Painters》,当时查字典断断续续看了三四个月才看完,习惯以后看书就轻松了些,受这本书的影响还学了学lisp语言,感觉就像发现了另一个宇宙。

今年年初的时候列个了时间表,规划了下要学的内容,现在回过头来看,只能说可以,但是还不够好。今年依旧列了个计划,希望能有所突破。最近看到一条微博,说三十岁以后想再有时间去学习知识简直是奢望。虽然离三十岁还有五六年,不过已经感觉到确实时间不那么充裕了,很多事情都要分心去了解和处理,人总不能在书堆里过日子。趁现在有时间,能学多少是多少吧。

总是听到这样的言论,“要是高中好好学就好了”、“要是大学好好学就好了”、“要是多看看书就好了”等等。我以前也这么后悔过,不过有一天意识到:大学的时候后悔高中没好好学,工作以后后悔大学没好好学,工作遇到瓶颈后悔刚工作的几年没多看看书,如果你只是这么想而不去想办法努力并改变的话,三年以后,你会后悔现在没好好学,六年以后,你会后悔三年前没好好学,很多人的一生,就是这么蹉跎的吧。

很喜欢写代码和学习计算机科学相关的内容,希望新年能有突破。换了新机器后把机器名改成了lunar mare,也就是月海,这个词是早期的天文爱好者观察月球时,受限于器材和知识,认为月球表面有美丽的海洋,但实际上那些只是类似于盆地的地貌。计算机科学也是这样类似的东西,远远望着觉得很神奇很精彩,接触之后会发现看起来十分乏味和贫瘠,但是当你深入研究之后,才能真正的热爱上这个学科。

突然想起一件小事,随手记在这里,北航六十年校庆的时候去玩,在学校里面的航空博物馆看神舟七号发射的动画演示,运载火箭从上到下包括逃逸塔,整流罩,多节火箭,助推器等等,发射过程要逐步的脱落。旁边两个学生,看样子像情侣,他们的对话很有意思,顿时让我想起“男人来自金星,女人来自火星”这句话。

        火箭助推器脱落
        女(呆萌脸):呀,脚没了
        男(正经脸):嗯,火箭的四个助推器脱落了
        火箭逃逸塔脱落
        女(呆萌脸):呀,头没了
        男(正经脸):嗯,火箭要抛掉逃逸塔,这个是用来救生的
        一级火箭脱落
        女(呆萌脸):呀,腿也没了
        男(正经脸):嗯,一级火箭脱落,二级火箭要开机了
        火箭整流罩脱落
        女(呆萌脸):哎呀,脖子也掉了
        男(正经脸):嗯,火箭要抛掉整流罩,这个会被回收回来,里面的黑匣子记录有数据
        星箭分离
        女(呆萌脸):呀,肚子也没了
        男(正经脸):嗯,二级火箭关机,要星箭分离
        
        然后女生蹦蹦跳跳走了,男生在后面老老实实跟着
    

learn git branching网站的题目解答-Remote部分

抽空做了Remote部分,git的分支的确很灵活,考虑看看《pro git》

1.1 Clone Intro

git clone

1.2 Remote Branches

git commit
git checkout o/master
git commit

1.3 Git Fetchin’

git fetch

1.4 Git Pullin’

git pull

1.5 Fakeing Teamwork

git clone
git fakeTeamwork master 2
git commit
git pull

1.6 Git Pushin’

git clone
git commit
git commit
git push

1.7 Diverged History

git clone
git fakeTeamwork master 1
git commit 
git pull —rebase
git push

2.1 Push Master!

git fetch
git rebase o/master side1
git rebase side1 side2
git rebase side2 side1
git rebase side3 side2
git push

2.2 Mering with remotes

git checkout master
git pull
git merge side1
git merge side2
git merge side3
git push

2.3 Remoting Tracking

git checkout -b side o/master
git commit
git pull —rebase
git push

2.4 Git push arguments

git push origin master
git push origin foo

2.5 Git push arguments — Expanded!

git push origin master~1:foo
git push origin foo:master

2.6 Fetch arguments

git fetch origin master~1:foo
git fetch origin foo:master
git checkout foo
git merge master

2.7 Source of nothing

git push origin :foo
git fetch origin :bar

2.8 Pull arguments

git pull origin bar:foo
git pull origin master:side

—  原创作品许可 — 署名-非商业性使用-禁止演绎 3.0 未本地化版本 — CC BY-NC-ND 3.0   —