操作系统
快来分享你的内容吧~
- 02-22 11:06·Java后端
- wsl命令为什么显示系统找不到指定命令鱼皮哥,各位鱼友,我想问问wsl卸载后再安装,可能是因为删除不干净还是什么行为,导致我后面在power shell中输入有关wsl的命令(包括安装,下载的命令)都会给我显示系统找不到指定路径,我想问问这个问题应该如何解决?...查看全文编程导航小智:这个问题可能是由于未完全删除WSL导致的。您可以尝试以下步骤解决问题:1. 打开PowerShell,并使用管理员权限运行。2. 输入以下命令以列出您计算机上已安装的WSL分发版:wsl --list3. 如果列表为空,或者没有您预期的分发版,请继续执行以下步骤。否则,如果列表中包含您已删除的分发版,请在步骤4中卸载它。4. 输入以下命令以删除WSL分发版(其中"<distro_name>"是您要
- 2023-09-06·后端开发
聊聊买电脑被坑的一段经历
这几天买电脑被坑了。 ### 事情经过 在淘宝买了一台Y7000p。 全新的大概是9699(未开封的),然后我下单了一个一皇冠的商家,大概9100元。 原因: * 发货距离比较近 * 便宜500 * 带个皇冠,虽然只有一个 然后发给我说:已经激活过。非二手,是展示机。 我想了想,表示可以。(我以为是只激活,未使用) ### 二手机 拿到电脑以后进行验机: * 有非常严重的严重的划痕和使用痕迹。肉眼可见 * 1T的磁盘被使用了17T * 开机时间1300小时 * 充放电次数300次 * 风扇有大量的油烟味,估计上一任主人抽烟 问了问修电脑的,他表示: * 纯二手机 * 市场价5000元比较合理 5000元的二手机,被奸商当成展示机去买。 ### 为什么非要买 * 淘宝他有7天无理由退货 * 在淘宝上买了两台,前两台都是正常的 京东的虽然各种没问题,但是价格实在太贵。 这一次吃完亏,和商家商量,表示要退。商家同意了。 我:???? ### 沟通过程 沟通过程非常奇葩: * 展示机,用了17T???1T的硬盘用了17T * 商家表示:这是正常的,展示机就是这样的,有使用记录很正常,比如说看看ppt啥的 * 什么叫17T??你们家展示机正常使用17T? 我听不懂。 聊聊划痕: * 划痕这个东西我们说了,叫九五新?说划痕很严重,什么叫很严重,我认为这叫95新 和店家聊天真费劲 * 我认为你不合理 * 我认为展示机有17T很合理 * 我认为你认为划痕很严重不客观 * 我认为…… 我说:你别说我认为了。人家就是重度使用,超过展示机了。 揣着明白装糊涂。 由于我在店面上,人家有展示机。商家告诉我: * 展示机每天开机8个小时,挂15天以上。 * 也就放放视频ppt啥的 * 放在那边怎么可能有划痕 也就是收的二手机。然后装成展示机来卖。 ### 被骗的教训 首先,我在淘宝买了3台电脑,前两台都没问题。所以放松了。 淘宝有退货,退货及时。但是如果是在咸鱼上,那损失就太大了。 专业的人才懂。 买电脑要去买未激活的新机。 然后就是口头禅: * 我听不懂 * 我不明白 * 有什么问题? 这就是推卸责任的标准话术
wsl命令为什么显示系统找不到指定命令
鱼皮哥,各位鱼友,我想问问wsl卸载后再安装,可能是因为删除不干净还是什么行为,导致我后面在power shell中输入有关wsl的命令(包括安装,下载的命令)都会给我显示系统找不到指定路径,我想问问这个问题应该如何解决?
我认为比较好的计算机书籍 --- 操作系统篇
<html> <head></head> <body> <div class="content ql-editor"> <p>说到操作系统这门课程,可以说让人又爱又恨,爱它是因为它有着极其重要的地位和作用,懂操作系统的人会对硬件有一些了解,同时懂操作系统也能够把各种形式的汇编搞清楚了,而且你还掌握了高级语言的王者 --- C 语言。</p> <p>可以说懂操作系统和不懂操作系统的程序员完全是两类人,不懂操作系统的程序员可能把活能做完完并且能够做好,但是你可能做的不精细,而且涉及到原理之类的知识你无法讲出来,那么懂操作系统的程序员会把一些程序设计细节以及原理给你讲清楚并能够实现出来。</p> <p><br></p> <p>事实上,你不仅仅要学操作系统,你要打牢的是整个计算机科学,只不过本篇我们只会聊到操作系统。</p> <p><br></p> <p>软件工程师分为两种:一种充分理解了计算机科学,从而有能力应对充满挑战的创造性工作;另一种仅仅凭着对一些高级工具的熟悉而勉强应付。</p> <p><br></p> <p>这两种人都自称软件工程师,都能在职业生涯早期挣到差不多的工资。然而,随着时间流逝,第一种工程师不断成长,所做的事情将会越来越有意义且更为高薪,不论是有价值的商业工作、突破性的开源项目、技术上的领导力或者高质量的个人贡献。</p> <p><br></p> <p>学习操作系统就跟修仙一样,都会经历非常多的层级,没跨过一个层级你都会有不一样的收货和感受。</p> <p><br></p> <h2><strong style="background-color: rgb(255, 255, 255); color: rgb(52, 73, 94);">第一步 --- 炼气</strong></h2> <p><br></p> <p>如果你是个啥也不懂没接触过计算机的小白,亦或是跨行从机械等专业转过来的同学,还是刚刚入行打算深入理解计算机的程序员,我都建议你先要了解一下计算机基础。</p> <p><br></p> <p>我个人比较推荐的计算机入门书籍就是《编码》。</p> <p><br></p> <p>推荐指数 ⭐️⭐️⭐️⭐️⭐️</p> <p><span class="ql-font-monospace"><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/80csj9ox.jpeg"></span></p> <p>在本书中作者介绍了很多专业知识,包括汇编语言,数字电路,计算机组成原理,操作系统等等,作者凭借着他巧妙的写作方式,一个包袱一个包袱地把这些知识慢慢抛出,让之前完全没有听过这些东西的人也能够很容易理解。</p> <p><br></p> <p>这本书同时适合两类人:小白和大神。小白最喜欢的就是零门槛入门,然后带你一步一步推导某个物质的原理、某个公式的原理、因为知识是呈线性的,这是最容易的入门方式。这本书也适合大神,在你懂得很多原理之后,你就会明白往往一个概念、一个逻辑其实是非常简单的,正所谓的<strong>美味的食材往往只需要简单的烹饪方式</strong>,很多问题在你看过之后都会迎刃而解。</p> <p><br></p> <p>另外一本非常适合小白入门的书籍是《程序是怎样跑起来的》</p> <p><br></p> <p>推荐指数: ⭐️⭐️⭐️⭐️</p> <p><span class="ql-font-monospace"><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/780sydeo.jpeg"></span></p> <p>这本书采取通俗易懂的方式来为你讲解各种计算机硬件 --- CPU ,内存,磁盘,汇编,算法,操作系统,计算机程序等,是一本计算机入门的基础读物。</p> <p><br></p> <p>这个小日子作者还写了另外两本书《计算机是怎样跑起来的》以及《网络是怎样连接的》,个人觉得计算机是怎样跑起来的这本书写的不和我的胃口,还是《程序是怎样跑起来的》读的酣畅淋漓。</p> <p><br></p> <p>我自己也写过这本书的读书笔记,并且做成了 PDF ,可以作为辅助学习的工具。</p> <p><br></p> <p>学习操作系统就好像修仙一样(事实上不少人都已经这么认为了),要从最基础的概念开始入手,然后再把硬件和软件串联起来,最后能自己手撸一个极简版的操作系统(这是大部分人所能接触到的天花板了)。再往后就可以专精操作系统的各个细分领域了。</p> <p><br></p> <p>所以这第一步就是炼气,炼气就是筑基打基础,修成之后举手投足都有千斤之力,快若奔马,超脱人体极限,向非人转化,并且体内凝聚真元,施展一些小法术 :)</p> <p><br></p> <p>开个玩笑,炼过气之后你会觉得操作系统很有意思,从上到下焕发出来了对知识的渴望,对底层的兴趣,想要继续深入。</p> <p><br></p> <h2><strong style="background-color: rgb(255, 255, 255); color: rgb(52, 73, 94);">第二步 --- 金丹</strong></h2> <p><br></p> <p>继续深入操作系统的第一步就是需要对操作系统有个比较全面的理解了。这里给大家推荐一本书 《操作系统导论》(OS Three Easy Pieces)。</p> <p><br></p> <p>推荐指数: ⭐️⭐️⭐️⭐️⭐️</p> <p><span class="ql-font-monospace"><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/mon8xwjt.jpeg"></span></p> <p>这本书是很多国外高校的大学教材,国内也有不少知名大学引进这本书,这本书作为操作系统的第一本书非常合适,汉译过来也比较易懂,当然有条件还是直接建议原版书。这本书介绍了所有现代系统的主要组件(包括调度、虚拟内存管理、磁盘和I/O子系统、文件系统)。内容非常全面,而且给出了真实可运行的代码,非常适合高校学生和教师。</p> <p><br></p> <p>还有一本操作系统入门非常好的书籍是《现代操作系统》,这也是我入门操作系统所看的第一本书。</p> <p><br></p> <p>推荐指数: ⭐️⭐️⭐️⭐️</p> <p><span class="ql-font-monospace"><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/pj14veyr.jpeg"></span></p> <p>这本书的作者是知名的 Tanenbaum 教授,他写了著名的 MINIX 操作系统,本身就是操作系统领域的大拿那么其写出来的书也一定值得一读。这本书对于操作系统相关的介绍非常全面,而且有些地方的举例很有意思。</p> <p><br></p> <p>这本书最富有魅力最值得赞赏的地方在于——作者引入一个概念必定是由一个问题和困境带出的,也就是说,作者不会无缘无故的列提纲似的推出一个全新概念让人摸不着头脑思索为什么,而是由“既然有这样的情况,那我们迫切需要达到的效果是什么,由此我们自然而然地想出了那样的实现和解决方式”这样的思维模式来引导读者,循序渐进的方法令读者不会一下子脱离进度。</p> <p><br></p> <p>不过进一步来说,这本书太过于对概念进行介绍了,知识的连贯性不足,而且汉译过来的质量不太好,书中有不少勘误,甚至有的图都画错了,这样无疑会造成很多阅读障碍,还是建议读原版书。</p> <p><br></p> <p>这本书的译者陈向群还是北京大学的教授,她在 B 站上还有课程,翻译成这样真的太掉价了,而且 B 站上面的课程也很枯燥,不建议看。</p> <p><br></p> <p>还有一本国内的操作系统书籍也非常不错:《现代操作系统:原理与实现》</p> <p><br></p> <p>推荐指数: ⭐️⭐️⭐️⭐️</p> <p><span class="ql-font-monospace"><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/l6mzv31e.jpeg"></span></p> <p>这本书的作者是上海交大的博导陈海波和夏虞斌老师,陈老也是国内操作系统领域知名度非常高的大佬,他还是 OpenHarmony 开放原子开源基金会的主席,之前有幸见过陈老一面。</p> <p><br></p> <p>由于这本书是国人写的,所以对于阅读门槛比较低,这本书后面还有 chcore 的实验,大家有兴趣可以做一下。</p> <p>我上面推荐的三本操作系统书籍大家选一本看就可以了,当然我个人最推荐的就是操作系统导论这本书了。</p> <p>如果你掌握了操作系统的这些理论知识,那么你能成为同行眼中的大佬,你可以跟他们侃侃而谈,但凡遇到程序方面的问题,你都会从底层原理出发来解决。</p> <p><br></p> <p>元丹九转凝练成金丹,金丹一念,可掌控方圆百里,让天地元气臣服,形成领域,可掌控天地,并具备法相可肉身横渡宇宙,踏入空间领域,初步掌握空间能力,一击毁城,在天荒星域,乃是老祖掌教级人物。</p> <p><br></p> <h2><strong style="background-color: rgb(255, 255, 255); color: rgb(52, 73, 94);">第三步 --- 元婴</strong></h2> <p><br></p> <p>根据在不同平台上的运行环境,操作系统分为这几类:在 PC 上运行的操作系统比如 Windows、UNIX、Linux ;在手机上运行的操作系统比如 Symbian、安卓、IOS;嵌入式操作系统比如 Linux、eCos、FreeRTOS 等。</p> <p><br></p> <p>虽然操作系统有很多,但我们日常接触最多的就是 Windows、Linux,Windows 是闭源系统,并且是基于图形化界面的,资料比较少;而 Linux 操作系统是开源的,更符合程序员的脾性,所以我们日常研究的操作系统无外乎都是基于 Linux 的。</p> <p><br></p> <p>想要研究 Linux 操作系统,是需要有一些前置知识在里面的,这里需要你对 C 语言基础和汇编语言有一定程度的了解,因为 Linux 就是基于 C 和汇编语言的,这里的 Linux 我们只研究到早期的 Linux 内核 - v0.11。</p> <p><br></p> <p>所以先抛开操作系统不谈,这两本书是我极力推荐给大家的,都是五颗星。</p> <p><br></p> <p>《C 程序设计语言》</p> <p><br></p> <p>推荐指数: ⭐️⭐️⭐️⭐️⭐️</p> <p><span class="ql-font-monospace"><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/qxckmvrb.jpeg"></span></p> <p>C 语言最经典的书,没有之一了,因为作者就是把 C 发明出来的 Dennis M. Ritchie 丹尼斯里奇。这本书短小且经典,全书没一句废话,每一句话都需要过脑子仔细思考才行,看完这本书后,C 语言就 OK 了。</p> <p><br></p> <p>《汇编语言》王爽</p> <p><br></p> <p>推荐指数: ⭐️⭐️⭐️⭐️⭐️</p> <p><span class="ql-font-monospace"><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/v9d4f81e.jpeg"></span></p> <p>这本书我也看完了,没有汇编语言要比王爽老师写的这本教材再好的了。这本书真正做到了通俗易懂,门槛很低,章节之间的连贯性做的非常好,几乎可称国内最好的汇编语言教材。可搭配 DOSBox 模拟器使用,是入门汇编语言必看、必练的一本书。</p> <p><br></p> <p>这两本书读过之后,可以先来看一下这本书,《x86 汇编语言:从实模式到保护模式》</p> <p><br></p> <p>推荐指数: ⭐️⭐️⭐️⭐️</p> <p><span class="ql-font-monospace"><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/opwrbekq.jpeg"></span></p> <p>这本书可以在看完王爽老师汇编语言之后看,也可以一起看,也可以不看,只看王爽老师的那本书。当然视你自己的时间来定,我还是推荐看一下的。</p> <p><br></p> <p>下面来推荐一个比较王炸的书籍,《Linux 0.11 内核完全注释》</p> <p><br></p> <p>推荐指数: ⭐️⭐️⭐️⭐️</p> <p><span class="ql-font-monospace"><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/3l5xw220.jpeg"></span></p> <p>这是一本基于 Linux 0.11 内核源码写的,能让你对 Linux 0.11 内核有全面的认知。不过这本书是翻译过来的国外著作,所以有些地方比较晦涩,比如在讲第五张 Linux 内核体系结构的时候,我就有很多地方产生过歧义,不知道是我太菜还是怎样。虽然是神书,但是一页一页看下来困难也非常大,可以当做一本工具书来用,源码分析的解释非常好,重点推荐。</p> <p><br></p> <p>这部书可能你一时半会无法读完,而且这本书也没有指望你能一下子读完,这是一本能让你常读常新的书籍。随时翻看都能有所体会和感悟。</p> <p><br></p> <p>凝聚自身法则,碎丹凝婴,元婴可与法则共鸣,以己心代天心,一念之间,方圆千里云动,万里雪飘。可操控天象,举手投足,都具备毁天灭地之力,可用自身之力掌控空间,自身万寿无疆。</p> <p><br></p> <p>元婴这一步练成,就说明你有很深的造诣了,你具备手撸一个操作系统的基础和框架,下一步就直接实现一个吧!</p> <p><br></p> <h2><strong style="background-color: rgb(255, 255, 255); color: rgb(52, 73, 94);">第四步 --- 化神</strong></h2> <p><br></p> <p>写到这里我一直在思考一个问题,是把所有理论都掌握了然后再实践,还是学了一部分理论就直接上手实践,我觉得这个孰对孰错,都是选择的问题。</p> <p><br></p> <p>如果你只学了一部分理论知识就直接上手,有可能你会更加在意实验结果而忽略了过程,甚至很多细节点你注意不到,不会让实践加深你的理论认知。</p> <p><br></p> <p>如果你学了所有的理论知识再上手实践,这个过程非常痛苦,因为你会长时间浮在云上,无法落地,有可能坚持不到实践就放弃了。</p> <p><br></p> <p>所以我觉得最好的方式就是学了一部分理论之后就直接去做对应的实验,所以我推荐大家把炼气和金丹阶段修炼完,《Linux 0.11 内核完全注释》可以和我下面推荐的书籍一起看,一起练。</p> <p><br></p> <p>《操作系统真象还原》</p> <p><br></p> <p>推荐指数: ⭐️⭐️⭐️⭐️⭐️</p> <p><span class="ql-font-monospace"><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/vankxx1h.jpeg"></span></p> <p>这本书讲解了开发一个操作系统需要的技术和知识,主要内容有:操作系统基础、部署工作环境、编写 MBR 主引导记录、完善 MBR 错误、保护模式入门、保护模式进阶和向内核迈进、中断、内存管理系统、线程、输入输出系统、用户进程、完善内核、编写硬盘驱动程序、文件系统、系统交互等核心技术。</p> <p><br></p> <p>你可以根据这本书一步一步编写和调试,加深印象,渐渐会让你对操作系统有个全面的认知和理解。</p> <p><br></p> <p>《Orange'S:一个操作系统的实现》</p> <p><br></p> <p>推荐指数: ⭐️⭐️⭐️⭐️</p> <p><span class="ql-font-monospace"><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/0if3atwh.jpeg"></span></p> <p>于渊老师的著作,这本书代码非常精炼,适合大家自己动手实现一下。</p> <p><br></p> <p>《30 天自制操作系统》</p> <p><br></p> <p>推荐指数: ⭐️⭐️⭐️</p> <p><span class="ql-font-monospace"><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/kgpfm37l.jpeg"></span></p> <p><br></p> <p>元神寄托虚空,号称不灭,化身万千、滴血重生,抛弃灵石,吸收更高层次的能量,能够开辟生命世界,可以横渡宇宙星空,得到天地位格的加持,彻底掌控一片地域,把一方区域化作自己的神域神国。</p> <p><br></p> <p>修炼到这个境界就能够修改操作系统源码了,你甚至可以参与 Linux 内核代码的开发。</p> <p><br></p> <h2><strong style="background-color: rgb(255, 255, 255); color: rgb(52, 73, 94);">第五步 --- 渡劫</strong></h2> <p><br></p> <p>事实上如果你能跟着上面书中的内容一步一步撸一个极简版的操作系统,那么操作系统的框架和结构就在你的脑海里 "立" 起来了,那么你需要做的是不断的装填你所需要的材料和弹药。</p> <p><br></p> <p>《深入理解 Linux 内核》</p> <p><br></p> <p>推荐指数: ⭐️⭐️⭐️⭐️⭐️</p> <p><span class="ql-font-monospace"><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/zeat5uxh.jpeg"></span></p> <p>读这本书需要对 Linux 内核有一定了解才可以,小白当然直接劝退了!如果有条件支持的话,还是要看英文版的。而且这本书不要指望看一遍就看懂,复杂系统的知识网络往往是网状的,而非线性的,读这本书要综合起来看才会有意义和收货。</p> <p><br></p> <p>《Linux 0.11 内核完全注释》</p> <p><br></p> <p>再次推荐 Linux 0.11 内核完全注释,常读常新。</p> <p><br></p> <p>《深入 Linux 内核架构》</p> <p><br></p> <p>推荐指数: ⭐️⭐️⭐️⭐️⭐️</p> <p><span class="ql-font-monospace"><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/jobw9l8d.jpeg"></span></p> <p>如果你要从事 Linux 内核开发或者对 Linux 有极度的兴趣,可以看下这本书。这本书结合内核版本 2.6.24 源代码中最关键的部分,深入讨论了 Linux 内核的概念、结构和实现。</p> <p><br></p> <h2><strong style="background-color: rgb(255, 255, 255); color: rgb(52, 73, 94);">后记</strong></h2> <p><br></p> <p>操作系统方面的书籍有很多,我只是罗列了一下我认为比较好的学习路线,很多书籍没有提到,比如 LDK ,Linux 内核设计的艺术、操作系统概念等书。小伙伴们可以按照我的路线来学习,我保证你能有一个系统性的提高,当然欢迎各位评论区提出针对此路线的改善意见和建议。</p> </div> </body> </html>
个人面试题复习、整理集合
<html> <head></head> <body> <div class="content ql-editor"> <h2><br></h2> <p>更新:</p> <ol> <li data-list="ordered"><span class="ql-ui"></span>新增mysql部分篇章</li> <li data-list="ordered"><span class="ql-ui"></span>操作系统-文件管理篇更新</li> </ol> <p><br></p> <p>后续笔记内容会包括操作系统、计网、leetcode、mysql、redis、golang等等</p> <p>备注:我的笔记的语言组织是相对于我自己而言清晰的,可借鉴......</p> <p><br></p> <h2>操作系统面试题总结</h2> <p><br></p> <ol> <li data-list="bullet"><span class="ql-ui"></span>操作系统简介篇 :<a href="https://www.yuque.com/g/quanxiansheng-fz6sk/orde4l/fwtko3eqayyh2eca/collaborator/join?token=umM5qNjj5jhAbu1s&source=doc_collaborator#%20%E3%80%8A%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E7%AE%80%E4%BB%8B%E7%AF%87%E3%80%8B" target="_blank">https://www.yuque.com/g/quanxiansheng-fz6sk/orde4l/fwtko3eqayyh2eca/collaborator/join?token=umM5qNjj5jhAbu1s&source=doc_collaborator# 《操作系统简介篇》</a></li> <li data-list="bullet"><span class="ql-ui"></span>进程线程篇:<a href="https://www.yuque.com/g/quanxiansheng-fz6sk/orde4l/owyygn06dnarbsgf/collaborator/join?token=mIu6EPQyCp2zZFvj&source=doc_collaborator#%20%E3%80%8A%E8%BF%9B%E7%A8%8B%E3%80%81%E7%BA%BF%E7%A8%8B%E7%AF%87%E3%80%8B" target="_blank">https://www.yuque.com/g/quanxiansheng-fz6sk/orde4l/owyygn06dnarbsgf/collaborator/join?token=mIu6EPQyCp2zZFvj&source=doc_collaborator# 《进程、线程篇》</a></li> <li data-list="bullet"><span class="ql-ui"></span>死锁篇:<a href="https://www.yuque.com/g/quanxiansheng-fz6sk/orde4l/ugzuoh5716gxyfpg/collaborator/join?token=SNuTujbrQ26Q50g9&source=doc_collaborator#%20%E3%80%8A%E6%AD%BB%E9%94%81%E3%80%8B" target="_blank">https://www.yuque.com/g/quanxiansheng-fz6sk/orde4l/ugzuoh5716gxyfpg/collaborator/join?token=SNuTujbrQ26Q50g9&source=doc_collaborator# 《死锁》</a></li> <li data-list="bullet"><span class="ql-ui"></span>内存管理篇:<a href="https://www.yuque.com/g/quanxiansheng-fz6sk/orde4l/hop7dllxk6k3vun7/collaborator/join?token=vk40xww2l658itNP&source=doc_collaborator#%20%E3%80%8A%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86%E3%80%8B" target="_blank">https://www.yuque.com/g/quanxiansheng-fz6sk/orde4l/hop7dllxk6k3vun7/collaborator/join?token=vk40xww2l658itNP&source=doc_collaborator# 《内存管理》</a></li> <li data-list="bullet"><span class="ql-ui"></span>文件系统管理篇:<a href="https://www.yuque.com/g/quanxiansheng-fz6sk/orde4l/fphus767860siv7u/collaborator/join?token=wf1S3cMZ97j4lXyN&source=doc_collaborator#%20%E3%80%8A%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E3%80%8B" target="_blank">https://www.yuque.com/g/quanxiansheng-fz6sk/orde4l/fphus767860siv7u/collaborator/join?token=wf1S3cMZ97j4lXyN&source=doc_collaborator# 《文件系统》</a></li> </ol> <p><br></p> <h2>mysql 面试题总结</h2> <p><br></p> <ol> <li data-list="bullet"><span class="ql-ui"></span>基础篇:<a href="https://www.yuque.com/g/quanxiansheng-fz6sk/orde4l/eociz41eri4amgn7/collaborator/join?token=VETg885hTgMOhC51&source=doc_collaborator#%20%E3%80%8A%E5%9F%BA%E7%A1%80%E6%A6%82%E5%BF%B5%E3%80%8B" target="_blank">https://www.yuque.com/g/quanxiansheng-fz6sk/orde4l/eociz41eri4amgn7/collaborator/join?token=VETg885hTgMOhC51&source=doc_collaborator# 《基础概念》</a></li> <li data-list="bullet"><span class="ql-ui"></span>索引篇:<a href="https://www.yuque.com/g/quanxiansheng-fz6sk/orde4l/ebvkkyezauv2wk4w/collaborator/join?token=AFYJXKOTiXwFHTCg&source=doc_collaborator#%20%E3%80%8A%E7%B4%A2%E5%BC%95%E3%80%8B" target="_blank">https://www.yuque.com/g/quanxiansheng-fz6sk/orde4l/ebvkkyezauv2wk4w/collaborator/join?token=AFYJXKOTiXwFHTCg&source=doc_collaborator# 《索引》</a></li> </ol> <p><br></p> <p><br></p> <hr class="article-hr" style="height: 0px"> </div> </body> </html>
操作系统学习路线大出炉!
<html> <head></head> <body> <div class="content ql-editor"> <p>之前给大家推荐了一下学习操作系统有哪些比较不错的网站,详见</p> <p><br></p> <p><a href="https://articles.zsxq.com/id_dja3mkv2nr4s.html" target="_blank">https://articles.zsxq.com/id_dja3mkv2nr4s.html</a></p> <p><br></p> <p>有小伙伴留言说希望出一下操作系统的学习路线图,今天它就来了!!!</p> <p><br></p> <p>说到操作系统这门课程,可以说让人又爱又恨,爱它是因为它有着极其重要的地位和作用,懂操作系统的人会对硬件有一些了解,同时懂操作系统也能够把各种形式的汇编搞清楚了,而且你还掌握了高级语言的王者 --- C 语言。</p> <p><br></p> <p>可以说懂操作系统和不懂操作系统的程序员完全是两类人,不懂操作系统的程序员可能把活能做完完并且能够做好,但是你可能做的不精细,而且涉及到原理之类的知识你无法讲出来,那么懂操作系统的程序员会把一些程序设计细节以及原理给你讲清楚并能够实现出来。</p> <p><br></p> <p>事实上,你不仅仅要学操作系统,你要打牢的是整个计算机科学,只不过本篇我们只会聊到操作系统。</p> <p><br></p> <p>软件工程师分为两种:一种充分理解了计算机科学,从而有能力应对充满挑战的创造性工作;另一种仅仅凭着对一些高级工具的熟悉而勉强应付。</p> <p><br></p> <p>这两种人都自称软件工程师,都能在职业生涯早期挣到差不多的工资。然而,随着时间流逝,第一种工程师不断成长,所做的事情将会越来越有意义且更为高薪,不论是有价值的商业工作、突破性的开源项目、技术上的领导力或者高质量的个人贡献。</p> <p><br></p> <h2><strong style="background-color: rgb(255, 255, 255); color: rgb(52, 73, 94);">第一步 --- 炼气</strong></h2> <p><br></p> <p>如果你是个啥也不懂没接触过计算机的小白,亦或是跨行从机械等专业转过来的同学,还是刚刚入行打算深入理解计算机的程序员,我都建议你先要了解一下计算机基础。</p> <p><br></p> <p>我个人比较推荐的计算机入门书籍就是《编码》。</p> <p><br></p> <p>推荐指数 ⭐️⭐️⭐️⭐️⭐️</p> <p><span class="ql-font-monospace"><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/eiq51lqz.jpeg"></span></p> <p>在本书中作者介绍了很多专业知识,包括汇编语言,数字电路,计算机组成原理,操作系统等等,作者凭借着他巧妙的写作方式,一个包袱一个包袱地把这些知识慢慢抛出,让之前完全没有听过这些东西的人也能够很容易理解。</p> <p><br></p> <p>这本书同时适合两类人:小白和大神。小白最喜欢的就是零门槛入门,然后带你一步一步推导某个物质的原理、某个公式的原理、因为知识是呈线性的,这是最容易的入门方式。这本书也适合大神,在你懂得很多原理之后,你就会明白往往一个概念、一个逻辑其实是非常简单的,正所谓的<strong>美味的食材往往只需要简单的烹饪方式</strong>,很多问题在你看过之后都会迎刃而解。</p> <p><br></p> <p>另外一本非常适合小白入门的书籍是《程序是怎样跑起来的》</p> <p><br></p> <p>推荐指数: ⭐️⭐️⭐️⭐️</p> <p><span class="ql-font-monospace"><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/s6mugkxs.jpeg"></span></p> <p>这本书采取通俗易懂的方式来为你讲解各种计算机硬件 --- CPU ,内存,磁盘,汇编,算法,操作系统,计算机程序等,是一本计算机入门的基础读物。</p> <p><br></p> <p>这个小日子作者还写了另外两本书《计算机是怎样跑起来的》以及《网络是怎样连接的》,个人觉得计算机是怎样跑起来的这本书写的不和我的胃口,还是《程序是怎样跑起来的》读的酣畅淋漓。</p> <p><br></p> <p>我自己也写过这本书的读书笔记,并且做成了 PDF ,可以作为辅助学习的工具。</p> <p><br></p> <p>学习操作系统就好像修仙一样(事实上不少人都已经这么认为了),要从最基础的概念开始入手,然后再把硬件和软件串联起来,最后能自己手撸一个极简版的操作系统(这是大部分人所能接触到的天花板了)。再往后就可以专精操作系统的各个细分领域了。</p> <p><br></p> <p>所以这第一步就是炼气,炼气就是筑基打基础,修成之后举手投足都有千斤之力,快若奔马,超脱人体极限,向非人转化,并且体内凝聚真元,施展一些小法术 :)</p> <p><br></p> <p>开个玩笑,炼过气之后你会觉得操作系统很有意思,从上到下焕发出来了对知识的渴望,对底层的兴趣,想要继续深入。</p> <p><br></p> <h2><strong style="background-color: rgb(255, 255, 255); color: rgb(52, 73, 94);">第二步 --- 金丹</strong></h2> <p><br></p> <p>继续深入操作系统的第一步就是需要对操作系统有个比较全面的理解了。这里给大家推荐一本书 《操作系统导论》(OS Three Easy Pieces)。</p> <p><br></p> <p>推荐指数: ⭐️⭐️⭐️⭐️⭐️</p> <p><span class="ql-font-monospace"><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/k099vhuu.jpeg"></span></p> <p>这本书是很多国外高校的大学教材,国内也有不少知名大学引进这本书,这本书作为操作系统的第一本书非常合适,汉译过来也比较易懂,当然有条件还是直接建议原版书。这本书介绍了所有现代系统的主要组件(包括调度、虚拟内存管理、磁盘和I/O子系统、文件系统)。内容非常全面,而且给出了真实可运行的代码,非常适合高校学生和教师。</p> <p><br></p> <p>还有一本操作系统入门非常好的书籍是《现代操作系统》,这也是我入门操作系统所看的第一本书。</p> <p><br></p> <p>推荐指数: ⭐️⭐️⭐️⭐️</p> <p><span class="ql-font-monospace"><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/8gmifd5e.jpeg"></span></p> <p>这本书的作者是知名的 Tanenbaum 教授,他写了著名的 MINIX 操作系统,本身就是操作系统领域的大拿那么其写出来的书也一定值得一读。这本书对于操作系统相关的介绍非常全面,而且有些地方的举例很有意思。</p> <p><br></p> <p>这本书最富有魅力最值得赞赏的地方在于——作者引入一个概念必定是由一个问题和困境带出的,也就是说,作者不会无缘无故的列提纲似的推出一个全新概念让人摸不着头脑思索为什么,而是由“既然有这样的情况,那我们迫切需要达到的效果是什么,由此我们自然而然地想出了那样的实现和解决方式”这样的思维模式来引导读者,循序渐进的方法令读者不会一下子脱离进度。</p> <p><br></p> <p>不过进一步来说,这本书太过于对概念进行介绍了,知识的连贯性不足,而且汉译过来的质量不太好,书中有不少勘误,甚至有的图都画错了,这样无疑会造成很多阅读障碍,还是建议读原版书。</p> <p>这本书的译者陈向群还是北京大学的教授,她在 B 站上还有课程,翻译成这样真的太掉价了,而且 B 站上面的课程也很枯燥,不建议看。</p> <p><br></p> <p>还有一本国内的操作系统书籍也非常不错:《现代操作系统:原理与实现》</p> <p><br></p> <p>推荐指数: ⭐️⭐️⭐️⭐️</p> <p><span class="ql-font-monospace"><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/hfhcbn78.jpeg"></span></p> <p>这本书的作者是上海交大的博导陈海波和夏虞斌老师,陈老也是国内操作系统领域知名度非常高的大佬,他还是 OpenHarmony 开放原子开源基金会的主席,之前有幸见过陈老一面。</p> <p><br></p> <p>由于这本书是国人写的,所以对于阅读门槛比较低,这本书后面还有 chcore 的实验,大家有兴趣可以做一下。</p> <p>我上面推荐的三本操作系统书籍大家选一本看就可以了,当然我个人最推荐的就是操作系统导论这本书了。</p> <p>如果你掌握了操作系统的这些理论知识,那么你能成为同行眼中的大佬,你可以跟他们侃侃而谈,但凡遇到程序方面的问题,你都会从底层原理出发来解决。</p> <p><br></p> <p>元丹九转凝练成金丹,金丹一念,可掌控方圆百里,让天地元气臣服,形成领域,可掌控天地,并具备法相可肉身横渡宇宙,踏入空间领域,初步掌握空间能力,一击毁城,在天荒星域,乃是老祖掌教级人物。</p> <p><br></p> <h2><strong style="background-color: rgb(255, 255, 255); color: rgb(52, 73, 94);">第三步 --- 元婴</strong></h2> <p><br></p> <p>根据在不同平台上的运行环境,操作系统分为这几类:在 PC 上运行的操作系统比如 Windows、UNIX、Linux ;在手机上运行的操作系统比如 Symbian、安卓、IOS;嵌入式操作系统比如 Linux、eCos、FreeRTOS 等。</p> <p><br></p> <p>虽然操作系统有很多,但我们日常接触最多的就是 Windows、Linux,Windows 是闭源系统,并且是基于图形化界面的,资料比较少;而 Linux 操作系统是开源的,更符合程序员的脾性,所以我们日常研究的操作系统无外乎都是基于 Linux 的。</p> <p><br></p> <p>想要研究 Linux 操作系统,是需要有一些前置知识在里面的,这里需要你对 C 语言基础和汇编语言有一定程度的了解,因为 Linux 就是基于 C 和汇编语言的,这里的 Linux 我们只研究到早期的 Linux 内核 - v0.11。</p> <p>所以先抛开操作系统不谈,这两本书是我极力推荐给大家的,都是五颗星。</p> <p><br></p> <p>《C 程序设计语言》</p> <p><br></p> <p>推荐指数: ⭐️⭐️⭐️⭐️⭐️</p> <p><span class="ql-font-monospace"><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/yq7zvbx4.jpeg"></span></p> <p>C 语言最经典的书,没有之一了,因为作者就是把 C 发明出来的 Dennis M. Ritchie 丹尼斯里奇。这本书短小且经典,全书没一句废话,每一句话都需要过脑子仔细思考才行,看完这本书后,C 语言就 OK 了。</p> <p><br></p> <p>《汇编语言》王爽</p> <p><br></p> <p>推荐指数: ⭐️⭐️⭐️⭐️⭐️</p> <p><span class="ql-font-monospace"><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/xkz20c14.jpeg"></span></p> <p>这本书我也看完了,没有汇编语言要比王爽老师写的这本教材再好的了。这本书真正做到了通俗易懂,门槛很低,章节之间的连贯性做的非常好,几乎可称国内最好的汇编语言教材。可搭配 DOSBox 模拟器使用,是入门汇编语言必看、必练的一本书。</p> <p><br></p> <p>这两本书读过之后,可以先来看一下这本书,《x86 汇编语言:从实模式到保护模式》</p> <p><br></p> <p>推荐指数: ⭐️⭐️⭐️⭐️</p> <p><span class="ql-font-monospace"><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/roz5oeck.jpeg"></span></p> <p>这本书可以在看完王爽老师汇编语言之后看,也可以一起看,也可以不看,只看王爽老师的那本书。当然视你自己的时间来定,我还是推荐看一下的。</p> <p><br></p> <p>下面来推荐一个比较王炸的书籍,《Linux 0.11 内核完全注释》</p> <p><br></p> <p>推荐指数: ⭐️⭐️⭐️⭐️</p> <p><span class="ql-font-monospace"><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/s92acfkj.jpeg"></span></p> <p>这是一本基于 Linux 0.11 内核源码写的,能让你对 Linux 0.11 内核有全面的认知。不过这本书是翻译过来的国外著作,所以有些地方比较晦涩,比如在讲第五张 Linux 内核体系结构的时候,我就有很多地方产生过歧义,不知道是我太菜还是怎样。虽然是神书,但是一页一页看下来困难也非常大,可以当做一本工具书来用,源码分析的解释非常好,重点推荐。</p> <p><br></p> <p>这部书可能你一时半会无法读完,而且这本书也没有指望你能一下子读完,这是一本能让你常读常新的书籍。随时翻看都能有所体会和感悟。</p> <p><br></p> <p>凝聚自身法则,碎丹凝婴,元婴可与法则共鸣,以己心代天心,一念之间,方圆千里云动,万里雪飘。可操控天象,举手投足,都具备毁天灭地之力,可用自身之力掌控空间,自身万寿无疆。</p> <p><br></p> <p>元婴这一步练成,就说明你有很深的造诣了,你具备手撸一个操作系统的基础和框架,下一步就直接实现一个吧!</p> <p><br></p> <h2><strong style="background-color: rgb(255, 255, 255); color: rgb(52, 73, 94);">第四步 --- 化神</strong></h2> <p><br></p> <p>写到这里我一直在思考一个问题,是把所有理论都掌握了然后再实践,还是学了一部分理论就直接上手实践,我觉得这个孰对孰错,都是选择的问题。</p> <p><br></p> <p>如果你只学了一部分理论知识就直接上手,有可能你会更加在意实验结果而忽略了过程,甚至很多细节点你注意不到,不会让实践加深你的理论认知。</p> <p><br></p> <p>如果你学了所有的理论知识再上手实践,这个过程非常痛苦,因为你会长时间浮在云上,无法落地,有可能坚持不到实践就放弃了。</p> <p><br></p> <p>所以我觉得最好的方式就是学了一部分理论之后就直接去做对应的实验,所以我推荐大家把炼气和金丹阶段修炼完,《Linux 0.11 内核完全注释》可以和我下面推荐的书籍一起看,一起练。</p> <p><br></p> <p>《操作系统真象还原》</p> <p><br></p> <p>推荐指数: ⭐️⭐️⭐️⭐️⭐️</p> <p><span class="ql-font-monospace"><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/ekijsf7y.jpeg"></span></p> <p>这本书讲解了开发一个操作系统需要的技术和知识,主要内容有:操作系统基础、部署工作环境、编写 MBR 主引导记录、完善 MBR 错误、保护模式入门、保护模式进阶和向内核迈进、中断、内存管理系统、线程、输入输出系统、用户进程、完善内核、编写硬盘驱动程序、文件系统、系统交互等核心技术。</p> <p><br></p> <p>你可以根据这本书一步一步编写和调试,加深印象,渐渐会让你对操作系统有个全面的认知和理解。</p> <p><br></p> <p>《Orange'S:一个操作系统的实现》</p> <p><br></p> <p>推荐指数: ⭐️⭐️⭐️⭐️</p> <p><span class="ql-font-monospace"><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/3azh3c19.jpeg"></span></p> <p>于渊老师的著作,这本书代码非常精炼,适合大家自己动手实现一下。</p> <p><br></p> <p>《30 天自制操作系统》</p> <p><br></p> <p>推荐指数: ⭐️⭐️⭐️</p> <p><span class="ql-font-monospace"><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/z67liciv.jpeg"></span></p> <p><br></p> <p>元神寄托虚空,号称不灭,化身万千、滴血重生,抛弃灵石,吸收更高层次的能量,能够开辟生命世界,可以横渡宇宙星空,得到天地位格的加持,彻底掌控一片地域,把一方区域化作自己的神域神国。</p> <p><br></p> <p>修炼到这个境界就能够修改操作系统源码了,你甚至可以参与 Linux 内核代码的开发。</p> <p><br></p> <h2><strong style="background-color: rgb(255, 255, 255); color: rgb(52, 73, 94);">第五步 --- 渡劫</strong></h2> <p><br></p> <p>事实上如果你能跟着上面书中的内容一步一步撸一个极简版的操作系统,那么操作系统的框架和结构就在你的脑海里 "立" 起来了,那么你需要做的是不断的装填你所需要的材料和弹药。</p> <p><br></p> <p>《深入理解 Linux 内核》</p> <p><br></p> <p>推荐指数: ⭐️⭐️⭐️⭐️⭐️</p> <p><span class="ql-font-monospace"><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/qc9r0dns.jpeg"></span></p> <p>读这本书需要对 Linux 内核有一定了解才可以,小白当然直接劝退了!如果有条件支持的话,还是要看英文版的。而且这本书不要指望看一遍就看懂,复杂系统的知识网络往往是网状的,而非线性的,读这本书要综合起来看才会有意义和收货。</p> <p><br></p> <p>《Linux 0.11 内核完全注释》</p> <p><br></p> <p>再次推荐 Linux 0.11 内核完全注释,常读常新。</p> <p><br></p> <p>《深入 Linux 内核架构》</p> <p><br></p> <p>推荐指数: ⭐️⭐️⭐️⭐️⭐️</p> <p><span class="ql-font-monospace"><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/avvjzoib.jpeg"></span></p> <p>如果你要从事 Linux 内核开发或者对 Linux 有极度的兴趣,可以看下这本书。这本书结合内核版本 2.6.24 源代码中最关键的部分,深入讨论了 Linux 内核的概念、结构和实现。</p> <p><br></p> <p>当然欢迎各位评论区提出针对此路线的改善意见和建议。</p> </div> </body> </html>
后端内功修炼,浅谈进程线程和协程
<html> <head></head> <body> <div class="content ql-editor"> <p>大家好,我是柠檬🍋。</p> <p>继续来更新我们的「后端内功修炼」系列,之前已经更新了 3 篇相关内容,感兴趣的同学可以点下面传送门回顾:</p> <p><a href="https://articles.zsxq.com/id_ghlcjqvmfude.html" target="_blank">深入物理内存管理和虚存分配</a></p> <p><a href="https://articles.zsxq.com/id_b8pregnpaw1k.html" target="_blank">浅谈 Linux 内存管理</a></p> <p><a href="https://articles.zsxq.com/id_9ze8g212eism.html" target="_blank">6种常用进程分析系统工具</a></p> <p>在操作系统课程的学习中,很多人对进程线程有大体的认识,但操作系统教材更偏向于理论叙述,本文会结合 Linux 系统实现分析,更加印象深刻。</p> <p>同时,大部分人都接触进程和线程比较多,对协程知之甚少,然而最近协程并发编程技术火热起来,希望读完本文你对协程也有一个基本的了解。</p> <p>话不多说,我们马上进入本文的学习。</p> <h2>进程</h2> <p>关于进程和内存管理我之前有一篇文章单独讲解过,这里再挑选一部分和本文相关的内容学习,温故而知新。</p> <p>首先还是说下「程序」的概念,程序是一些保存在磁盘上的指令的有序集合,是静态的。<strong>进程是程序执行的过程</strong>,包括了动态创建、调度和消亡的整个过程,<strong>进程是程序资源管理的最小单位</strong>。</p> <h3>进程与资源</h3> <p>那么进程都管理哪些资源呢? 通常包括内存资源、IO资源、信号处理等部分。</p> <p><img src="https://pic.code-nav.cn/planet_post_image/1655076464816590850/2iv4wi0e.jpeg" alt=""></p> <p>篇幅有限着重说一下内存管理,进程运行起来必然会涉及到对内存资源的管理。内存资源有限,<strong>操作系统采用虚拟内存技术,把进程虚拟地址空间划分成用户空间和内核空间。</strong></p> <h3>地址空间</h3> <p><code>4GB</code> 的进程虚拟地址空间被分成两部分:用户空间和内核空间</p> <p><img src="https://pic.code-nav.cn/planet_post_image/1655076464816590850/meoyvc05.jpeg" alt=""></p> <h4>用户空间</h4> <p>用户空间按照<strong>访问属性一致的地址空间存放在一起的原则</strong>,划分成 <code>5</code>个不同的内存区域。 访问属性指的是“可读、可写、可执行等 。</p> <ol> <li data-list="bullet"><span class="ql-ui"></span>代码段代码段是用来存放可执行文件的操作指令,可执行程序在内存中的镜像。代码段需要防止在运行时被非法修改,所以只准许读取操作,它是不可写的。</li> <li data-list="bullet"><span class="ql-ui"></span>数据段数据段用来存放可执行文件中已初始化全局变量,换句话说就是存放程序静态分配的变量和全局变量。</li> <li data-list="bullet"><span class="ql-ui"></span>BSS段<code>BSS</code>段包含了程序中未初始化的全局变量,在内存中 <code>bss</code> 段全部置零。</li> <li data-list="bullet"><span class="ql-ui"></span>堆 <code>heap</code>堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)</li> <li data-list="bullet"><span class="ql-ui"></span>栈 <code>stack</code>栈是用户存放程序临时创建的局部变量,也就是函数中定义的变量(但不包括 <code>static</code> 声明的变量,static意味着在数据段中存放变量)。除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的先进后出特点,所以栈特别方便用来保存/恢复调用现场。从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。</li> </ol> <p>上述几种内存区域中数据段、<code>BSS</code> 段、堆通常是被连续存储在内存中,在位置上是连续的,而代码段和栈往往会被独立存放。堆和栈两个区域在 <code>i386</code> 体系结构中栈向下扩展、堆向上扩展,相对而生。</p> <p><img src="https://pic.code-nav.cn/planet_post_image/1655076464816590850/w644xhss.jpeg" alt=""></p> <p>你也可以再 linux 下用<code>size</code> 命令查看编译后程序的各个内存区域大小:</p> <div class="ql-code-block-container"> <div class="ql-code-block"> [lemon ~]# size /usr/local/sbin/sshd text data bss dec hex filename 1924532 12412 426896 2363840 2411c0 /usr/local/sbin/sshd </div> </div> <h4>内核空间</h4> <p>在 <code>x86 32</code> 位系统里,Linux 内核地址空间是指虚拟地址从 <code>0xC0000000</code> 开始到 <code>0xFFFFFFFF</code> 为止的高端内存地址空间,总计 <code>1G</code> 的容量, 包括了内核镜像、物理页面表、驱动程序等运行在内核空间 。</p> <p><img src="https://pic.code-nav.cn/planet_post_image/1655076464816590850/azskud2j.jpeg" alt="内核空间地址映射"></p> <h2>线程</h2> <p>线程是操作操作系统能够进行运算调度的最小单位。线程被包含在进程之中,是进程中的实际运作单位,一个进程内可以包含多个线程,<strong>线程是资源调度的最小单位。</strong></p> <p><img src="https://pic.code-nav.cn/planet_post_image/1655076464816590850/2wpevh08.jpeg" alt="多线程程序模型"></p> <h3>线程资源和开销</h3> <p>同一进程中的多条线程共享该进程中的全部系统资源,如虚拟地址空间,文件描述符文件描述符和信号处理等等。但同一进程中的多个线程有各自的调用栈、寄存器环境、线程本地存储等信息。</p> <p>线程创建的开销主要是线程堆栈的建立,分配内存的开销。这些开销并不大,最大的开销发生在线程上下文切换的时候。</p> <p><img src="https://pic.code-nav.cn/planet_post_image/1655076464816590850/uwmf82o9.jpeg" alt="线程切换"></p> <h3>线程分类</h3> <p>还记得刚开始我们讲的内核空间和用户空间概念吗?线程按照实现位置和方式的不同,也分为用户级线程和内核线程,下面一起来看下这两类线程的差异和特点。</p> <h4>用户级线程</h4> <p>实现在用户空间的线程称为用户级线程。用户线程是完全建立在用户空间的线程库,用户线程的创建、调度、同步和销毁全由用户空间的库函数完成,不需要内核的参与,因此这种线程的系统资源消耗非常低,且非常的高效。</p> <h5>特点</h5> <ol> <li data-list="bullet"><span class="ql-ui"></span>用户线级线程只能参与竞争该进程的处理器资源,不能参与全局处理器资源的竞争。</li> <li data-list="bullet"><span class="ql-ui"></span>用户级线程切换都在用户空间进行,开销极低。</li> <li data-list="bullet"><span class="ql-ui"></span>用户级线程调度器在用户空间的线程库实现,内核的调度对象是进程本身,内核并不知道用户线程的存在。</li> </ol> <p><img src="https://pic.code-nav.cn/planet_post_image/1655076464816590850/0iinuk0i.jpeg" alt="用户线程图解"></p> <h5>缺点</h5> <ol> <li data-list="bullet"><span class="ql-ui"></span>如果触发了引起阻塞的系统调用的调用,会立即阻塞该线程所属的整个进程。</li> <li data-list="bullet"><span class="ql-ui"></span>系统只看到进程看不到用户线程,所以只有一个处理器内核会被分配给该进程 ,也就不能发挥多核 CPU 的优势 。</li> </ol> <h4>内核级线程</h4> <p>内核级线程是指,内核线程建立和销毁都是由操作系统负责、通过系统调用完成的,内核维护进程及线程的上下文信息以及线程切换。</p> <h5>特点</h5> <ol> <li data-list="bullet"><span class="ql-ui"></span>内核级线级能参与全局的多核处理器资源分配,充分利用多核 CPU 优势。</li> <li data-list="bullet"><span class="ql-ui"></span>每个内核线程都可被内核调度,因为线程的创建、撤销和切换都是对内核管理的。</li> <li data-list="bullet"><span class="ql-ui"></span>一个内核线程阻塞与他同属一个进程的线程仍然能继续运行。</li> </ol> <p><img src="https://pic.code-nav.cn/planet_post_image/1655076464816590850/svcp9xkr.jpeg" alt="内核线程图解"></p> <h5>缺点</h5> <ol> <li data-list="bullet"><span class="ql-ui"></span>内核级线程切换开销较大。因为每次线程切换都要从用户态切换到内核态, 代价要比用户级线程大很多。</li> <li data-list="bullet"><span class="ql-ui"></span>线程表是存放在操作系统固定的表格空间或者堆栈空间里,所以内核级线程的数量是有限的。</li> </ol> <h3>Linux 线程实现</h3> <p><code>Linux</code> 并没有为线程准备特定的数据结构,因为 Linux只有<code>task_struct</code>这一种描述进程的结构体。在内核看来只有进程而没有线程,线程调度时也是当做进程来调度的。Linux所谓的线程其实是与其他进程共享资源的<strong>轻量级进程</strong>。</p> <p>为什么说是轻量级呢?在于它只有一个最小的执行上下文和调度程序所需的统计信息,它只带有进程执行相关的信息,与父进程共享进程地址空间 。</p> <h4>轻量级进程</h4> <p>轻量级线程 <code>Light-weight Process</code>简称<code>LWP</code> ,是一种由内核支持的用户线程,每一个轻量级进程都与一个特定的内核线程关联。</p> <p>它是基于内核线程的高级抽象,系统只有先支持内核线程才能有 <code>LWP</code>。每一个进程有一个或多个 <code>LWPs</code> ,每个<code>LWP</code> 由一个内核线程支持,在这种实现的操作系统中 <code>LWP</code> 就是用户线程。</p> <p><img src="https://pic.code-nav.cn/planet_post_image/1655076464816590850/intpwmyk.jpeg" alt=""></p> <p>轻量级进程最早在<code>Linux</code> 内核 <code>2.0.x</code> 版本就已实现,应用程序通过一个统一的 <code>clone()</code> 系统调用接口,用不同的参数指定创建的进程是轻量进程还是普通进程。</p> <h4>特点和缺点</h4> <p>由于轻量轻量级进程基于内核线程实现,因此它的特点和缺点就是内核线程的缺点,这里不再赘述。</p> <h2>协程</h2> <p>协程的知名度好像不是很高,在以前我们谈论高并发,大部分人都知道利用多线程和多进程部署服务,提高服务性能,但一般不会提到协程。其实协程的概念出来的比线程还早,只不过最近才被人们更多的提起。</p> <p>协程之所以最近被大家熟知,个人觉得是 <code>Python</code> 和 <code>Go</code> 从语言层面提供了对协程更好的支持,尤其是以 <code>Goroutine</code> 为代表的 Go 协程实现,很大程度上降低了协程使用门槛,可以说是后起之秀了!</p> <p><img src="https://pic.code-nav.cn/planet_post_image/1655076464816590850/xh6nzr8b.jpeg" alt=""></p> <h3>why 协程</h3> <p>当今无数的 Web 服务和互联网服务,本质上大部分都是 IO 密集型服务,什么是 IO 密集型服务?意思是处理的任务大多是和网络连接或读写相关的高耗时任务,高耗时是相对 CPU 计算逻辑处理型任务来说,两者的处理时间差距不是一个数量级的。</p> <p><strong>IO 密集型服务的瓶颈不在 CPU 处理速度,而在于尽可能快速的完成高并发、多连接下的数据读写。</strong></p> <p><strong>以前有两种解决方案:</strong></p> <ol> <li data-list="bullet"><span class="ql-ui"></span>如果用多线程,高并发场景的大量 IO 等待会导致多线程被频繁挂起和切换,非常消耗系统资源,同时多线程访问共享资源存在竞争问题。</li> <li data-list="bullet"><span class="ql-ui"></span>如果用多进程,不仅存在频繁调度切换问题,同时还会存在每个进程资源不共享的问题,需要额外引入进程间通信机制来解决。</li> </ol> <p><strong>协程出现给高并发和 IO 密集型服务开发提供了另一种选择。</strong></p> <p>当然,世界上没有技术银弹,在这里我想把协程这把钥匙交到你手中,但是它也不是万能钥匙,最好的解决方案是贴合自身业务类型做出最优选择,不一定就选择一种模型,有时候是几种模型的组合,比如多线程搭配协程是常见的组合。</p> <h3>什么是协程</h3> <p>**那什么是协程呢?协程 <code>Coroutines</code> 是一种比线程更加轻量级的微线程。**类比一个进程可以拥有多个线程,一个线程也可以拥有多个协程,因此协程又称微线程和纤程。</p> <p><img src="https://pic.code-nav.cn/planet_post_image/1655076464816590850/8yf7dpv5.jpeg" alt=""></p> <p><strong>可以粗略的把协程理解成子程序调用,每个子程序都可以在一个单独的协程内执行。</strong></p> <p><img src="https://pic.code-nav.cn/planet_post_image/1655076464816590850/48lk0q5z.jpeg" alt=""></p> <h3>调度开销</h3> <p>线程是被内核所调度,线程被调度切换到另一个线程上下文的时候,需要保存一个用户线程的状态到内存,恢复另一个线程状态到寄存器,然后更新调度器的数据结构,这几步操作设计用户态到内核态转换,开销比较多。</p> <p><img src="https://pic.code-nav.cn/planet_post_image/1655076464816590850/rc34cdu7.jpeg" alt=""></p> <p>协程的调度完全由用户控制,协程拥有自己的寄存器上下文和栈,协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操作用户空间栈,完全没有内核切换的开销。</p> <p><img src="https://pic.code-nav.cn/planet_post_image/1655076464816590850/yqzd5snw.jpeg" alt=""></p> <h3>动态协程栈</h3> <p>协程拥有自己的寄存器上下文和栈,协程调度切换时将寄存器上下文和栈保存下来,在切回来的时候,恢复先前保存的寄存器的上下文和栈。</p> <p>Goroutine 是 Golang 的协程实现。Goroutine 的栈只有 2KB大小,而且是动态伸缩的,可以按需调整大小,最大可达 1G 相比线程来说既不浪费又灵活了很多,可以说是相当的nice了!</p> <p>线程也都有一个固定大小的内存块来做栈,一般会是 2MB 大小,线程栈会用来存储线程上下文信息。2MB 的线程栈和协程栈相比大了很多。</p> <p><img src="https://pic.code-nav.cn/planet_post_image/1655076464816590850/3mlg20m2.jpeg" alt=""></p> <h3>协程实现</h3> <h4>Python协程实现</h4> <p>正如刚才所写的代码示例,<code>python 2.5</code> 中引入 <code>yield/send</code> 表达式用于实现协程,但这种通过生成器的方式使用协程不够优雅。</p> <p><code>python 3.5</code> 之后引入<code>async/await</code> ,简化了协程的使用并且更加便于理解。</p> <h4>Go语言协程实现</h4> <p>Golang 在语言层面实现了对协程的支持,<code>Goroutine</code> 是协程在 Go 语言中的实现, 在 Go 语言中每一个并发的执行单元叫作一个 <code>Goroutine</code> ,Go 程序可以轻松创建成百上千个协程并发执行。</p> <p>Go 协程调度器有三个重要数据结构:</p> <ol> <li data-list="bullet"><span class="ql-ui"></span>G 表示 <code>Goroutine</code> ,它是一个待执行的任务;</li> <li data-list="bullet"><span class="ql-ui"></span>M 表示操作系统的线程,它由操作系统的调度器调度和管理;</li> <li data-list="bullet"><span class="ql-ui"></span>P 表示处理器 <code>Processor</code>,它可以被看做运行在线程上的本地调度器;</li> </ol> <p><img src="https://pic.code-nav.cn/planet_post_image/1655076464816590850/ioyeyr25.jpeg" alt=""></p> <p>Go 调度器最多可以创建 10000 个线程,但可以通过设置 <code>GOMAXPROCS</code> 变量指能够正常运行的运行, 这个变量的默认值 等于 CPU 个数,也就是线程数等于 CPU 核数,这样不会触发操作系统的线程调度和上下文切换,所有的调度由 Go 语言调度器触发,都是在用户态,减少了非常多的调用开销。</p> <h2>总结</h2> <p>这篇文章讲解和对比了进程、线程的概念,同时通过进程窥探到操作系统内存管理的冰山一角,另外还讲解了具体到 Linux 系统下线程的实现现状,顺势引出了轻量级进程的概念。最后着重说明了大部分同学不太了解的协程,通过对比不同的服务模型,带你了解协程的特点。</p> <p>看到这里的小伙伴都是能静下心来学习的同学,如果对你有帮助,点个免费的赞支持下呗~</p> <p>我是程序员柠檬,咱么下次再见👋🏻</p> #计算机基础# #后端# #操作系统# </div> </body> </html>
硬核操作系统网站推荐
<html> <head></head> <body> <div class="content ql-editor"> <p>一般很少有人推荐操作系统的网站吧。。。。。。这几个网站来源于我平常的学习总结,也有一些是来源于网上优秀的回答,希望这几个网站能够助力你对操作系统有更深的认识。</p> <p><br></p> <h2><strong style="background-color: rgb(255, 255, 255); color: rgb(244, 138, 0);">studytonight</strong></h2> <p><br></p> <p>studytonight 简直太棒了!!!studytonight 会包括 operationg system,但是并不是说 studytonight 就是一个单纯的 OS 学习网站,它是一个基础教程网,它的首页是这样的,不仅限于 OS ,还会包括 <strong>Java、C、CSS、OS、Computer network 等</strong>。</p> <p><br></p> <p><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/tqvtnne6.jpeg"></p> <p>这个页面一看就爱上了,和国内很多页面做的硬风格不同,这样的教程才不那么生硬和让人讨厌。在所有的素材库里面,有各种各样的教程</p> <p><br></p> <p><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/6bbsmfnh.jpeg"></p> <p><br></p> <p>我们推荐的是操作系统,所以索性就点进去操作系统主页好了,点进去的页面就是这样的</p> <p><br></p> <p>studytonight 是一个对初学者来说学习操作系统的一个很友好的网站。</p> <p><br></p> <p><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/u77xebtq.jpeg"></p> <p>课程艺术主要分为三部分,由易到难分别是基础篇、中等篇、提高篇,我们点进去基础篇的第一篇</p> <p><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/om3iabeo.jpeg"></p> <p>这一篇主要是对操作系统的介绍,操作系统的功能、操作系统任务等</p> <p><br></p> <p>通过简单的描述和图片来说明,让人感觉清晰易懂,很有目的性的学习,而且这些主题也可以作为面试题来考</p> <p><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/5r3i6hpf.jpeg"></p> <p>你还真说对了,studytonight 还真的就有面试题</p> <p><br></p> <p>我们在 Test 页签下面会发现有很多面试题</p> <p><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/7bi1d91s.jpeg"></p> <p><br></p> <p>我们选择 <strong>Operating System</strong> 进去之后会发现有很多的测试</p> <p><br></p> <p><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/d72nci3r.jpeg"></p> <p>是一个一体化的学习平台,适用于新手,我大致翻看了一下,里面的东西比较基础,受众广,是大家学习必备的一个网站。</p> <p><br></p> <h2><strong style="background-color: rgb(255, 255, 255); color: rgb(244, 138, 0);">udacity</strong></h2> <p><br></p> <p>udacity 是一个视频学习网站,界面看起来很清爽。</p> <p><br></p> <p><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/h4ecve6d.jpeg"></p> <p><br></p> <p>下面还有关于课程的介绍,同时你可以开始免费的课程,这个界面就是中文版了,让人眼前一亮</p> <p><br></p> <p><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/6un0tlwy.jpeg"></p> <p><br></p> <p>我的课程 就是你学过的所有课程,你可以在所有课程中搜索指定的课程,种类非常多</p> <p><br></p> <p><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/3bhcyg81.jpeg"></p> <p><br></p> <p>我们还是以操作系统为例,来看一下具体的课程</p> <p><br></p> <p><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/1ev9c1ht.jpeg"></p> <p><br></p> <p>左面是具体的课程列表,右面是讲师授课部分,视频非常清晰,而且讲师吐字很清楚,可以锻炼英语。有一些小伙伴们说英文看不懂,对英文望而退却,这不是一个好习惯。英文在编程世界中的重要性不言而喻。所以英文是你一定要学好的一门语言。</p> <p><br></p> <p><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/7zx08jgw.jpeg"></p> <p>讲师讲完课程之后还有具体的练习环节,作为学习巩固,非常不错。</p> <p><br></p> <p>udacity 的课程要比 studytonight 更深一些,操作系统这门课就分成了 22 堂课,每一堂课还有很多小节,真是一个非常好的网站。<strong>我现在在写文章,我巴不得不写字了,马上学习!</strong>。还是忍住了,那就写完了马上去看!!!</p> <p><br></p> <h2><strong style="background-color: rgb(255, 255, 255); color: rgb(244, 138, 0);">tutorialspoint</strong></h2> <p><br></p> <p>tutorialspoint 这个网站也是一个资源教程网,这个网站的搜索指数非常高,基本上搜任何问题都有 tutorialspoint 的解释。</p> <p><br></p> <p><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/ly25yv3y.jpeg"></p> <p><br></p> <p>我们点进去 Library 之后发现,这就是教程宝库啊,罗列的非常清楚</p> <p><br></p> <p><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/tg1gyy26.jpeg"></p> <p><br></p> <p>tutorialspoint 也有视频教程,不过大多都收费。</p> <p><br></p> <p><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/qlcc73yb.jpeg"></p> <p>教程非常多,不仅限于编程,也包含 Excel 、SAP 等教程。</p> <p><br></p> <p>tutorialspoint 还有电子书教程,不过大部分也是收费的,应该是 tutorialspoint 自己制作的 PDF,不知道写的怎么样,如果有兴趣的小伙伴可以付费下载,到时候记得给我发一份哦,嘿嘿。</p> <p><br></p> <p><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/rbttwyua.jpeg"></p> <p><br></p> <p>说了这么多,我们还没有看 tutorialspoint 操作系统的主页呢</p> <p><br></p> <p><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/xcm8x42a.jpeg"></p> <p>左边是导航栏,右边是具体的教程,这个样式感觉有些老,不过分类倒是很明确的,里面的内容要比 studytonight 差一些,也是一个入门非常好的教程网</p> <h2><br></h2> <h2><strong style="background-color: rgb(255, 255, 255); color: rgb(244, 138, 0);">classcentral</strong></h2> <p><br></p> <p>classcentral 这个网站有点强啊,里面汇总了各大名校的教程</p> <p><br></p> <p><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/hbpg8tqv.jpeg"></p> <p><br></p> <p>我们发现了一个中文教程,一看是 南京大学 的教程,南京大学也是非常牛逼的一所学校,小编也有南大的基友在搞影视,其实我是一个被编程耽误的导演,狗头保命。</p> <p><br></p> <p>不扯皮了,来看看南大的课程</p> <p><br></p> <p><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/jzcaqcum.jpeg"></p> <p><br></p> <p>这么多牛逼的课程发现了中文大学,也侧面说明了我国大学在国际上的地位。Overview 是 OS 的总体介绍。</p> <p>我们注册后点击开始课程,就进入讲课页面</p> <p><br></p> <p><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/pn83u97x.jpeg"></p> <p><br></p> <p>课程分为 6 周,以视频的形式展开,我们开始 计算机系统概览。</p> <p><br></p> <p><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/kw5dwd59.jpeg"></p> <p><br></p> <p>终于能看到国人讲的操作系统了!!!</p> <p><br></p> <p>右边还可以随时做笔记进行查看,课程还支持 下载 功能,非常不错!</p> <p><br></p> <p><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/pfmsb8st.jpeg"></p> <p>好了我们该退出来了,一会儿又忍不住听课了!</p> <p><br></p> <h2><strong style="background-color: rgb(255, 255, 255); color: rgb(244, 138, 0);">nptel</strong></h2> <p><br></p> <p>仿佛见到了一个不得了的网站,这个网站的名字就隐隐的感觉有点牛逼。我们先看牛逼在哪,然后再看为什么牛逼</p> <p><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/5ql7njxj.jpeg"></p> <p><strong>你能感觉出来牛逼了吗</strong>?</p> <p><br></p> <p>这每一个目录都 TM 是一本书啊,虽然页数不多,但这确确实实是宝贝啊。</p> <p><br></p> <p>从操作系统概述到文件系统、进程管理、文件管理、I/O 管理等等等等。这还不是最牛逼的,最牛逼的是右边能免费 下载,你说气人不气人</p> <p><br></p> <p><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/3sugcfk0.jpeg"></p> <p><br></p> <p>每一章节都支持下载 PDF 版本。</p> <p><br></p> <p>我们带着好奇心,点开了 About Us。</p> <p><br></p> <p>然后就看到了下面这段话</p> <p><br></p> <p><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/m0p84agf.jpeg"></p> <p>也就是说,这是一个 印度的国家增强型学习计划,也就是说,印度的各大名校联合推出的免费学习计划,这也能理解为什么印度人在电气、编程、通信方面能够越来越牛逼了。</p> <p><br></p> <p>这个网站你一定要看,我认为可以和黑皮书系列有一拼了。</p> <p><br></p> <h2><strong style="background-color: rgb(255, 255, 255); color: rgb(244, 138, 0);">codescracker</strong></h2> <p><br></p> <p>codescracker 又是一个牛逼的网站,看完这个网站,我才觉得低调才是最牛逼的炫耀。。。</p> <p><br></p> <p><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/scewso77.jpeg"></p> <p><br></p> <p>分类都非常全,解释的也很到位,但是 codescracker 并不只是一个 os 网站,它是一门编程语言的学习一站式平台,只不过网站比较简洁</p> <p><br></p> <p><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/zt8h2yo7.jpeg"></p> <p>可以看到有各种各样的教程,下面还是有测试类的,基本上企业用的语言都涵盖到了。</p> <p><br></p> <p>你必须要珍藏的一个网站。</p> <p><br></p> <h2><strong style="background-color: rgb(255, 255, 255); color: rgb(244, 138, 0);">sciencedirect</strong></h2> <p><br></p> <p>sciencedirect 这个网站真是太牛逼了。百度对 sciencedirect 的解释</p> <p><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/1qmanf9c.jpeg"></p> <p><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/vn70i654.jpeg"></p> <p>不过 sciencedirect 大部分的 PDF 下载是需要收费的,感兴趣的小伙伴们可以购买</p> <p><br></p> <h2><strong style="background-color: rgb(255, 255, 255); color: rgb(244, 138, 0);">homepage</strong></h2> <p><br></p> <p>Homepage 是做什么的,一看主页就明白了</p> <p><br></p> <p>这是一个计算机科学和统计学的网站,然后我们点击 search 搜索 os 直接跳转到 os 的首页</p> <p><br></p> <p><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/fss7qe7i.jpeg"></p> <p><br></p> <p>然后就呵呵呵呵了,这个网站比较奇葩,它没有后退和前进的按钮,那怎么访问?</p> <p><br></p> <p><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/4fhpk57l.jpeg"></p> <p><br></p> <p>我是直接通过 url 访问的,主页就是 <a href="https://homepage.cs.uri.edu/faculty/wolfe/book/Readings/Reading01.htm" target="_blank">https://homepage.cs.uri.edu/faculty/wolfe/book/Readings/Reading01.htm</a></p> <p>但是网站太硬核了,很好的一个学习资料哦。</p> <p><br></p> <p><br></p> <h2><strong style="color: rgb(244, 138, 0);"><a href="http://computer.howstuffworks.com" target="_blank">computer.howstuffworks.com</a></strong></h2> <p><br></p> <p><a href="http://computer.howstuffworks.com" target="_blank">computer.howstuffworks.com</a> 就是一个计算机网站,它涵盖软件和硬件的方方面面。</p> <p><br></p> <p><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/d5bvpduh.jpeg"></p> <p><br></p> <p>Computer 知识包括 <strong>计算机硬件、网络、计算机软件、计算机秘密等等</strong></p> <p><strong><br></strong></p> <p>都是一些讲的非常好的文章,可以说是计算机的百科全书了。</p> <p><br></p> <p>老样子我们点开 COMPUTER OPERATING SYSTEMS 专题,可以看到都是一些非常好的文章</p> <p><br></p> <p><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/lb07nt5r.jpeg"></p> <p>加入收藏夹!</p> <p><br></p> <h2><strong style="color: rgb(244, 138, 0);"><a href="http://tldp.org" target="_blank">tldp.org</a></strong></h2> <p><br></p> <p>这个网站又是一个学习操作系统非常牛逼的网站,我都不知道今晚上说了多少次了,哈哈哈哈。</p> <p><br></p> <p>来看看主页是啥样的</p> <p><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/yrv4l241.jpeg"></p> <p><br></p> <p>这一看就是一个牛逼的网站,不要问我为什么,OS 的页面是这样的</p> <p><br></p> <p><img src="https://pic.code-nav.cn/planet_post_image/1796381395438190593/8v73tv8v.jpeg"></p> <p>没有任何点缀和装饰,<strong>成年人的生活就这么朴实无华</strong>。</p> <p><br></p> </div> </body> </html>
后端内功修炼,浅谈linux内存管理
<html> <head></head> <body> <div class="content ql-editor"> <p>大家好,我是柠檬哥。</p> <p>周末啦,卷王们又到了弯道的时候!今天带大家学习 <code>Linux</code>内存管理。</p> <p>对于精通 <code>CURD</code> 的业务同学,内存管理好像离我们很远,知识点虽然冷门(估计很多人学完根本就没机会用上),但绝对是基础中的基础,这就像武侠中的内功修炼,学完之后看不到立竿见影的效果,但对你日后的开发工作是大有裨益的,因为你站的更高了。</p> <p>功利点的说,面试的时候不经意间透露你懂这方面知识,并且能说出个一二三来,也许能让面试官对你更有兴趣,走上人生巅峰又近了一步。</p> <p><img src="https://pic.code-nav.cn/planet_post_image/1655076464816590850/1hm2v5vc.jpeg" alt="image"></p> <p>前提约定:本文讨论技术内容前提,操作系统环境都是 <code>x86</code>架构的 32 位 <code>Linux</code>系统。</p> <h2>虚拟地址</h2> <p>即使是现代操作系统中,内存依然是计算机中很宝贵的资源,看看你电脑几个T固态硬盘,再看看内存大小就知道了。为了充分利用和管理系统内存资源,Linux采用虚拟内存管理技术,利用虚拟内存技术让每个进程都有<code>4GB</code> 互不干涉的虚拟地址空间。</p> <p>进程初始化分配和操作的都是基于这个「虚拟地址」,只有当进程需要实际访问内存资源的时候才会建立虚拟地址和物理地址的映射,调入物理内存页。</p> <p>打个不是很恰当的比方。这个原理其实和现在的某某网盘一样,假如你的网盘空间是<code>1TB</code>,真以为就一口气给了你这么大空间吗?还是太年轻,都是在你往里面放东西的时候才给你分配空间,你放多少就分多少实际空间给你,但你和你朋友看起来就像大家都拥有<code>1TB</code>空间一样。</p> <p><img src="https://pic.code-nav.cn/planet_post_image/1655076464816590850/z3k3exzf.jpeg" alt=""></p> <h3>虚拟地址的好处</h3> <ol> <li data-list="bullet"><span class="ql-ui"></span>避免用户直接访问物理内存地址,防止一些破坏性操作,保护操作系统</li> <li data-list="bullet"><span class="ql-ui"></span>每个进程都被分配了4GB的虚拟内存,用户程序可使用比实际物理内存更大的地址空间</li> </ol> <p><code>4GB</code> 的进程虚拟地址空间被分成两部分:「用户空间」和「内核空间」</p> <p><img src="https://pic.code-nav.cn/planet_post_image/1655076464816590850/q7h928js.jpeg" alt="用户空间内核空间"></p> <h2>物理地址</h2> <p>上面章节我们已经知道不管是用户空间还是内核空间,使用的地址都是虚拟地址,当需进程要实际访问内存的时候,会由内核的「请求分页机制」产生「缺页异常」调入物理内存页。</p> <p>把虚拟地址转换成内存的物理地址,这中间涉及利用<code>MMU</code> 内存管理单元(Memory Management Unit ) 对虚拟地址分段和分页(段页式)地址转换,关于分段和分页的具体流程,这里不再赘述,可以参考任何一本计算机组成原理教材描述。</p> <p><img src="https://pic.code-nav.cn/planet_post_image/1655076464816590850/9psfs72j.jpeg" alt="段页式内存管理地址转换"></p> <p><code>Linux</code> 内核会将物理内存分为3个管理区,分别是:</p> <h3>ZONE_DMA</h3> <p><code>DMA</code>内存区域。包含0MB~16MB之间的内存页框,可以由老式基于<code>ISA</code>的设备通过<code>DMA</code>使用,直接映射到内核的地址空间。</p> <h3>ZONE_NORMAL</h3> <p>普通内存区域。包含16MB~896MB之间的内存页框,常规页框,直接映射到内核的地址空间。</p> <h3>ZONE_HIGHMEM</h3> <p>高端内存区域。包含896MB以上的内存页框,不进行直接映射,可以通过永久映射和临时映射进行这部分内存页框的访问。</p> <p><img src="https://pic.code-nav.cn/planet_post_image/1655076464816590850/ae0adec7.jpeg" alt="物理内存区划分"></p> <h2>用户空间</h2> <p>用户进程能访问的是「用户空间」,每个进程都有自己独立的用户空间,虚拟地址范围从从 <code>0x00000000</code> 至 <code>0xBFFFFFFF</code> 总容量3G 。</p> <p>用户进程通常只能访问用户空间的虚拟地址,只有在执行内陷操作或系统调用时才能访问内核空间。</p> <h3>进程与内存</h3> <p>进程(执行的程序)占用的用户空间按照「 访问属性一致的地址空间存放在一起 」的原则,划分成 <code>5</code>个不同的内存区域。 访问属性指的是“可读、可写、可执行等 。</p> <ol> <li data-list="bullet"><span class="ql-ui"></span>代码段代码段是用来存放可执行文件的操作指令,可执行程序在内存中的镜像。代码段需要防止在运行时被非法修改,所以只准许读取操作,它是不可写的。</li> <li data-list="bullet"><span class="ql-ui"></span>数据段数据段用来存放可执行文件中已初始化全局变量,换句话说就是存放程序静态分配的变量和全局变量。</li> <li data-list="bullet"><span class="ql-ui"></span>BSS段<code>BSS</code>段包含了程序中未初始化的全局变量,在内存中 <code>bss</code> 段全部置零。</li> <li data-list="bullet"><span class="ql-ui"></span>堆 <code>heap</code>堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)</li> <li data-list="bullet"><span class="ql-ui"></span>栈 <code>stack</code>栈是用户存放程序临时创建的局部变量,也就是函数中定义的变量(但不包括 <code>static</code> 声明的变量,static意味着在数据段中存放变量)。除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场。从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。</li> </ol> <p>上述几种内存区域中数据段、<code>BSS</code> 段、堆通常是被连续存储在内存中,在位置上是连续的,而代码段和栈往往会被独立存放。堆和栈两个区域在 <code>i386</code> 体系结构中栈向下扩展、堆向上扩展,相对而生。</p> <p>也可以再linux下用<code>size</code> 命令查看编译后程序的各个内存区域大小:</p> <div class="ql-code-block-container"> <div class="ql-code-block"> [lemon ~]# size /usr/local/sbin/sshd text data bss dec hex filename 1924532 12412 426896 2363840 2411c0 /usr/local/sbin/sshd </div> </div> <h2>内核空间</h2> <p>在 <code>x86 32</code> 位系统里,Linux 内核地址空间是指虚拟地址从 <code>0xC0000000</code> 开始到 <code>0xFFFFFFFF</code> 为止的高端内存地址空间,总计 <code>1G</code> 的容量, 包括了内核镜像、物理页面表、驱动程序等运行在内核空间 。</p> <p><img src="https://pic.code-nav.cn/planet_post_image/1655076464816590850/v4duq3jj.jpeg" alt="内核空间细分区域."></p> <h4>直接映射区</h4> <p>直接映射区 <code>Direct Memory Region</code>:从内核空间起始地址开始,最大<code>896M</code>的内核空间地址区间,为直接内存映射区。</p> <p>直接映射区的896MB的「线性地址」直接与「物理地址」的前<code>896MB</code>进行映射,也就是说线性地址和分配的物理地址都是连续的。内核地址空间的线性地址<code>0xC0000001</code>所对应的物理地址为<code>0x00000001</code>,它们之间相差一个偏移量<code>PAGE_OFFSET = 0xC0000000</code></p> <p>该区域的线性地址和物理地址存在线性转换关系「线性地址 = <code>PAGE_OFFSET</code> + 物理地址」也可以用 <code>virt_to_phys()</code>函数将内核虚拟空间中的线性地址转化为物理地址。</p> <h4>高端内存线性地址空间</h4> <p>内核空间线性地址从 896M 到 1G 的区间,容量 128MB 的地址区间是高端内存线性地址空间,为什么叫高端内存线性地址空间?下面给你解释一下:</p> <p>前面已经说过,内核空间的总大小 1GB,从内核空间起始地址开始的 896MB 的线性地址可以直接映射到物理地址大小为 896MB 的地址区间。退一万步,即使内核空间的1GB线性地址都映射到物理地址,那也最多只能寻址 1GB 大小的物理内存地址范围。</p> <p>所以,内核空间拿出了最后的 128M 地址区间,划分成下面三个高端内存映射区,以达到对整个物理地址范围的寻址。而 在 64 位的系统上就不存在这样的问题了,因为可用的线性地址空间远大于可安装的内存。</p> <h5>动态内存映射区</h5> <p><code>vmalloc Region</code> 该区域由内核函数<code>vmalloc</code>来分配,特点是:线性空间连续,但是对应的物理地址空间不一定连续。 <code>vmalloc</code> 分配的线性地址所对应的物理页可能处于低端内存,也可能处于高端内存。</p> <h5>永久内存映射区</h5> <p><code>Persistent Kernel Mapping Region</code> 该区域可访问高端内存。访问方法是使用 <code>alloc_page (_GFP_HIGHMEM)</code> 分配高端内存页或者使用<code>kmap</code>函数将分配到的高端内存映射到该区域。</p> <h5>固定映射区</h5> <p><code>Fixing kernel Mapping Region</code> 该区域和 4G 的顶端只有 4k 的隔离带,其每个地址项都服务于特定的用途,如 <code>ACPI_BASE</code> 等。</p> <p><img src="https://pic.code-nav.cn/planet_post_image/1655076464816590850/oull3pi9.jpeg" alt="内核空间物理内存映射"></p> <h2>回顾一下</h2> <p>上面讲的有点多,先别着急进入下一节,在这之前我们再来回顾一下上面所讲的内容。如果认真看完上面的章节,我这里再画了一张图,现在你的脑海中应该有这样一个内存管理的全局图。</p> <p><img src="https://pic.code-nav.cn/planet_post_image/1655076464816590850/6m2sn07e.jpeg" alt="内核空间用户空间全图"></p> <h2>内存数据结构</h2> <p>要让内核管理系统中的虚拟内存,必然要从中抽象出内存管理数据结构,内存管理操作如「分配、释放等」都基于这些数据结构操作,这里列举两个管理虚拟内存区域的数据结构。</p> <h3>用户空间内存数据结构</h3> <p>在前面「进程与内存」章节我们提到,Linux进程可以划分为 5 个不同的内存区域,分别是:代码段、数据段、<code>BSS</code>、堆、栈,内核管理这些区域的方式是,将这些内存区域抽象成<code>vm_area_struct</code>的内存管理对象。</p> <p><code>vm_area_struct</code>是描述进程地址空间的基本管理单元,一个进程往往需要多个<code>vm_area_struct</code>来描述它的用户空间虚拟地址,需要使用「链表」和「红黑树」来组织各个<code>vm_area_struct</code>。</p> <p>链表用于需要遍历全部节点的时候用,而红黑树适用于在地址空间中定位特定内存区域。内核为了内存区域上的各种不同操作都能获得高性能,所以同时使用了这两种数据结构。</p> <p>用户空间进程的地址管理模型:</p> <p><img src="https://pic.code-nav.cn/planet_post_image/1655076464816590850/sd24mvci.jpeg" alt="wm_arem_struct"></p> <h3>内核空间动态分配内存数据结构</h3> <p>在内核空间章节我们提到过「动态内存映射区」,该区域由内核函数<code>vmalloc</code>来分配,特点是:线性空间连续,但是对应的物理地址空间不一定连续。 <code>vmalloc</code> 分配的线性地址所对应的物理页可能处于低端内存,也可能处于高端内存。</p> <p><code>vmalloc</code> 分配的地址则限于<code>vmalloc_start</code>与<code>vmalloc_end</code>之间。每一块<code>vmalloc</code>分配的内核虚拟内存都对应一个<code>vm_struct</code>结构体,不同的内核空间虚拟地址之间有<code>4k</code>大小的防越界空闲区间隔区。与用户空间的虚拟地址特性一样,这些虚拟地址与物理内存没有简单的映射关系,必须通过内核页表才可转换为物理地址或物理页,它们有可能尚未被映射,当发生缺页时才真正分配物理页面。</p> <p><img src="https://pic.code-nav.cn/planet_post_image/1655076464816590850/uov0jrld.jpeg" alt="动态内存映射"></p> <h2>END</h2> <p><code>Linux</code>内存管理是一个非常复杂的系统,本文所述只是冰山一角,从宏观角度给你展现内存管理的全貌,但一般来说,这些知识在你和面试官聊天的时候还是够用的,当然我也希望大家能够通过读书了解更深层次的原理。</p> <p>以上就是今天的分享啦,希望这篇文章可以作为一个索引一样的学习指南,当你想深入某一点学习的时候可以在这些章节里找到切入点,以及这个知识点在内存管理宏观上的位置!</p> <p><strong>如果有帮助,记得点个免费赞支持下~</strong></p> #后端# #操作系统# </div> </body> </html>
操作系统导论(虚拟CPU篇)
<html> <head></head> <body> <div class="content ql-editor"> <h1>前言</h1> <p><br></p> <p><a href="https://gitee.com/liwenhao12/note/blob/main/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%B3%BB%E5%88%97/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E5%AF%BC%E8%AE%BA.md" target="_blank">https://gitee.com/liwenhao12/note/blob/main/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%B3%BB%E5%88%97/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E5%AF%BC%E8%AE%BA.md</a></p> <p>PS: 强烈建议看网页版,星球的格式一言难尽,网址就是那个本文开源那个</p> <p>本文的主要内容:《操作系统导论》的大部分知识 + 我对书中内容的理解记录。我强烈推荐你也去看看这本书,也许你也会和我一样忍不住想写一些东西来记录自己的思考。</p> <p><br></p> <blockquote> <div class="blockquote-item"> 我针对整本书进行了一个梳理,如果你不确定你是否对下面的内容感兴趣可以看看大纲 😁 </div> <div class="blockquote-item"> 大纲链接:https://www.mubu.com/doc/L_9qNbJoK6 </div> <div class="blockquote-item"> 本文开源:https://gitee.com/liwenhao12/note/blob/main/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%B3%BB%E5%88%97/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E5%AF%BC%E8%AE%BA.md </div> <div class="blockquote-item"> 如果文章有什么错误或者有不妥的地方可以提Issue </div> </blockquote> <p><br></p> <h1>操作系统的发展</h1> <p><br></p> <ol> <li data-list="bullet"><span class="ql-ui"></span>第一阶段:操作系统还只是一些简单的底层API</li> <li data-list="bullet" class="ql-indent-2"><span class="ql-ui"></span>那时候操作系统只是一些控制设备的API,比如关于IO的API</li> <li data-list="bullet"><span class="ql-ui"></span>第二阶段:操作系统的第一个功能</li> <li data-list="bullet" class="ql-indent-2"><span class="ql-ui"></span>人们逐渐意识到控制设备的这部分代码,不能被随意访问。系统调用的概念就是这个时期出来的。</li> <li data-list="bullet"><span class="ql-ui"></span>第三阶段:多道程序时代</li> <li data-list="bullet" class="ql-indent-2"><span class="ql-ui"></span>随着硬件的成本下降,拥有计算机的成本降低,人们希望充分利用CPU资源,一次指定多个程序。为了满足这个要求,现代化的操作系统就此诞生了,比如内存保护,进程隔离等等。</li> </ol> <p><br></p> <p>通过操作系统的演化过程不难发现,从只是提供功能复用的'OS'变成了一个管理硬件资源的大管家。</p> <p><br></p> <h1>虚拟化</h1> <p><br></p> <blockquote> <div class="blockquote-item"> 接下来的内容,如果没有特别说明,讨论的是单核CPU的情况 </div> </blockquote> <p><br></p> <p>虚拟化硬件,是为了更好的管理硬件,更好的为应用程序分配资源,比如Linux将硬件虚拟化为文件,从而实现更好的管理和控制。</p> <p><br></p> <h2>虚拟CPU</h2> <p><br></p> <p>将CPU虚拟化,目的就是让应用程序看到这样一个假象:<strong>应用程序独占一个CPU</strong>。</p> <p><br></p> <blockquote> <div class="blockquote-item"> 举个租房的例子,我有一间房子,有两个租客,他们都想要租这个房子,而作为房东的我,很贪心,想要收他们两个人的房租。但是我只有一个房间,正当我放弃的时候,我突然发现他们的租房时间很有趣,租客甲他说我只会在上午使用房子,其他时间在公司工作,而租客乙恰恰相反,他除了晚上使用房子,其他时候也在公司工作。于是我起来贪心,收了这两位租客的房租,然后他们两个成功入住了。但是为了不让他们起疑心,我必须保证甲回来时,房子中的环境和以往一样,乙回来时,也得和他上次看到的一样。于是我不得不在甲离开房子,乙回来之前,将房子还原成乙的环境。虽然很辛苦,但是我收了两份房租,而且在他们看来,这个房子就只有他们一个人租。 </div> </blockquote> <p><br></p> <p>上面的例子解释了虚拟CPU的具体实现,即如何让应用程序认为他们独占一个CPU。在这个例子当中,房东就是操作系统,租客甲/乙就是普通的应用程序。</p> <p><br></p> <p>在程序甲要使用CPU之前,需要恢复程序甲之前的运行环境(比如寄存器中的值,以及CPU中的缓存数据)。通过这种保存环境,恢复环境的方式,让应用程序以为他自己独占一个CPU核心。而这里的保存环境以及恢复环境的过程就是我们<strong>通常说的上下文切换。</strong></p> <p><br></p> <p>既然就了解到这里了,不如我们继续深入下去,看看虚拟化的CPU到底是怎么做的?简单来说:<strong>CPU的时分共享 + 调度策略。时分共享</strong>:不同时间段,有不同的进程占用CPU,在进程的视角上看,他们独占CPU,但是从上帝视角上看,CPU是被许多进程共享的。之所以能保证在进程的视角上是独占视角的,这得多亏上下文切换,能够保留环境和恢复环境。<strong>调度策略</strong>:主要是决定运行哪个进程,是否需要进行上下文切换。</p> <p><br></p> <blockquote> <div class="blockquote-item"> 设计思想 </div> <div class="blockquote-item"> 时分共享更多的是一种底层的运行机制,而调度策略是上层的一种解决方案。 </div> <div class="blockquote-item"> 时分共享更多的是提供一种解决思路,而调度策略更多的是提供一种具体实现。类似于接口与实现类的关系。 </div> </blockquote> <p><br></p> <h3>进程</h3> <p><br></p> <p>通俗的讲,进程 = 正在运行的程序,这句话描述的够准确,但不够细节,进程是对正在运行的程序的抽象,那一个进程究竟包括什么呢?首先我们先想想运行一个程序需要什么?对于运行的程序,我们首先需要代码,它承载了我们的逻辑,会产生数据,这些承载了我们的结果,代码和数据得有地方存,这个时候有硬盘和内存可选,但是为了高效,快速,选择了内存,代码只是逻辑的体现,只是一套执行方案,还需要执行者,那就是我们的CPU。所以我们知道进程至少需要包含的硬件资源:<strong>内存 + CPU</strong>,硬件资源也不尽相同,比如内存的规格和性能,为了更好的管理硬件资源以及更好的分配资源给进程,我们需要虚拟化硬件,实现统一的管理。</p> <p><br></p> <p>进程需要的硬件资源</p> <p><br></p> <ol> <li data-list="bullet"><span class="ql-ui"></span>内存</li> <li data-list="bullet"><span class="ql-ui"></span>CPU</li> <li data-list="bullet"><span class="ql-ui"></span>硬盘</li> <li data-list="bullet"><span class="ql-ui"></span>IO</li> </ol> <p><br></p> <p>关于进程的介绍,大致就这样,后面我们慢慢补充。</p> <p><br></p> <h3>调度策略</h3> <p><br></p> <p>调度策略是发展的,是一个演进的过程,于是在理解调度策略的时候,我们也应该用发展的眼光看它,所以这部分内容,我打算从最简单的FIFO策略 → 最短任务优先策略 → 最短完成时间优先策略 → 轮换策略 → 多级反馈队列。</p> <p><br></p> <p>首先要比较不同调度策略,我们需要有一个评价的指标,最直观的指标就是速度,为了衡量不同方面的速度,我们提出了周转时间和响应时间这两套指标。</p> <p><br></p> <ol> <li data-list="bullet"><span class="ql-ui"></span>周转时间 $T_{任务完成时刻}</li> </ol> <p><br></p> <ol> <li data-list="bullet"><span class="ql-ui"></span>响应时间 $T_{首次运行时刻}</li> </ol> <p><br></p> <p><br></p> <p>这里的任务可以理解为进程,根据他们的含义可以看到,周转时间是程序总的运行时间长度,而响应时间是用户提交程序(比如双击图标)到程序真正被执行(获取到CPU资源)的时间差,主要是用来衡量交互性的好坏。</p> <p><br></p> <p>为了更好的展示,调度策略是怎么演化的,我们需要给我们的进程进行一些假设。</p> <p><br></p> <ol> <li data-list="ordered"><span class="ql-ui"></span>每一个工作运行相同的时间</li> <li data-list="ordered"><span class="ql-ui"></span>所有的工作同时到达(提交)</li> <li data-list="ordered"><span class="ql-ui"></span>一旦开始,每个工作保持运行直到完成</li> <li data-list="ordered"><span class="ql-ui"></span>所有的工作只使用CPU,而不使用I/O</li> <li data-list="ordered"><span class="ql-ui"></span>每个工作的运行时间已知</li> </ol> <p><br></p> <ol> <li data-list="ordered"><span class="ql-ui"></span>FIFO调度策略</li> </ol> <p><br></p> <p>FIFO,即先进先出,也就是先到先执行,假设我们有三个任务A B C,他们都运行10s,我们这里来计算一下他们的平均周转时间,根据假设,因为他们同时达到,假设A比B早一点点,B比C早一点点。</p> <p><img src="https://pic.code-nav.cn/planet_post_image/1628897468148121602/m79r21hb.jpeg"></p> <p><br></p> <p>$周转时间为:[(10 - 0) + (20 - 0) + (30 - 0)] \div 3 = 20s$</p> <p><br></p> <p>FIFO的策略有其优点那就是很容易实现,那缺点是什么呢?我们先把假设1(每一个工作运行相同的时间)放宽,每个任务的运行时间不一定相同,还是上面的例子,A B C三个任务运行时间分别为 100s,10s,10s,那么平均周转时间是多少呢?</p> <p><img src="https://pic.code-nav.cn/planet_post_image/1628897468148121602/826f6ffz.jpeg"></p> <p>周转时间为: $[(100 - 0) + (110 - 0) + (120 - 0)] \div 3 = 110s$ 可以看到,周转时间增加了很多,这被叫为护航响应:一些潜在的消耗较少的消费者排在了重量级的消耗大的资源消费者后面。 FIFO的策略的性能严重依赖进入任务的耗时以及任务被执行的顺序。上个例子,如果B C 先运行,平均周转时间 (10 + 20 + 120) / 3 = 50s,可以看见平均周转时间减少了一半。于是下一个调度策略就解决了这个问题</p> <p><br></p> <ol> <li data-list="ordered"><span class="ql-ui"></span>最短任务优先策略(SJF/Shortest Job First)</li> </ol> <p><br></p> <p>先去回顾一下我们的假设,现在为止,我们已经放开了假设1,或者说我们放弃了假设1后,产生了问题,于是这个调度策略就是来解决产生的问题的。</p> <p><br></p> <p>我们知道了FIFO策略的性能严重依赖任务的耗时以及任务执行的顺序,而SJF就是来解决这个问题的。还是任务A B C同时到达,这时候就会根据任务的耗时判断,谁先被调度(执行)。还是上面那个例子 A B C三个任务运行时间分别为 100s,10s,10s。那么平均周转时间是确定的,50s</p> <p><br></p> <p><img src="https://pic.code-nav.cn/planet_post_image/1628897468148121602/5cel5j4y.jpeg"></p> <p>在开始的时候,对任务耗时的比较,让任务的执行顺序<strong>确定而且最优,</strong>解决了FIFO策略的性能依赖任务执行顺序的问题,但是之所有能最优是建立在任务同时到达的假设下,也就是我们的假设2(所有的工作同时到达(提交)),可是如果我们放开假设2,就会产生这样的问题?</p> <p><img src="https://pic.code-nav.cn/planet_post_image/1628897468148121602/n4swqn88.jpeg"></p> <p>当任务不是同时达到时,就会产生上面这种情况:长时间任务先到达,然后执行A任务到完成(假设3),即使B C任务比A时间短。这样的话就让周转时间又下降了。造成这种情况的原因是我们假设任务一旦执行,就必须执行完成(假设3),如果我们放宽这个假设3,利用上下文切换技术就可以解决这个问题,这个也是我们的下一个策略的原理。</p> <p><br></p> <ol> <li data-list="ordered"><span class="ql-ui"></span>STCF策略(最短完成时间优先策略/Shortest Time to Completion First)</li> </ol> <p><br></p> <p>为了解决SJF在不是同时达到任务长度比较问题,STCF给出的解决方案是在每次添加新任务进队列的时候,会比较当前执行任务的剩余时间和新进入的任务的剩余时间进行比较,选择其中短的任务执行,如果发生要切换到新的任务,就会进行上下文环境的保存即上下文切换。</p> <p><img src="https://pic.code-nav.cn/planet_post_image/1628897468148121602/e57v18ej.jpeg"></p> <p></p> <p><br></p> <p>通过这种抢占式的调度方式,可以很好的保证短任务一定先于长任务执行。在假设4(只使用CPU不使用IO)和假设5(知道任务的完成时间)成立的条件下,STCF是比较符合直觉的最优的解决方案。</p> <p><br></p> <blockquote> <div class="blockquote-item"> 在讲解下一个调度方式的时候,不知道你注意到没,我们现在还没有使用响应时间这个指标,为什么呢?因为我们的任务没有使用IO,没有IO就没有输入/输出,那么就没有交互,没有交互谈响应时间的意义就不是很大。不过我们也可以利用响应时间公式来算算上面那个STCF中的例子,因为A到达后,就立马执行,所以A的响应时间为0s,B也一样,到达了就执行了,只有C,在达到后,需要等待B执行完后,才能执行,所以C的响应时间=10s。从这个例子可以看出来,无论B中有无IO操作,都会等待B完全执行完毕后,才开始执行C,如果我们执行的这个C任务是一个与用户交互的程序,那么用户端将会明显的感觉到卡顿。为了解决这个问题,优化响应时间,提升交互程序的易用性,于是诞生了下面这种调度方式 -- 轮换 </div> </blockquote> <p><br></p> <ol> <li data-list="ordered"><span class="ql-ui"></span>轮转(RR)</li> </ol> <p><br></p> <p>为了极致的优化响应时间,这种调度策略以一个很小的时间片段为单位,一个进程只运行这么一个时间片,然后就会进行上下文切换,执行另一个进程。</p> <p><br></p> <p><img src="https://pic.code-nav.cn/planet_post_image/1628897468148121602/lueu62j9.jpeg"></p> <p>在图中每个时间片的大小为1s,那么C的响应时间就为(4-3) = 1s,可以看到响应时间被大大的优化了,但是这个优化是有代价的,代价就是上下文切换。上下文切换最少就是要做的保存寄存器的值到内存,然后将寄存器的值从内存恢复到寄存器中。虽然这种切换很快,但是如果频繁操作依然影响性能,不过上下文切换的代价是稳定的,可以利用均摊的思想,来降低上下文切换带来的性能影响。上面的调度方式其实是基于假设4(只使用CPU而不使用IO)但是程序不可能不使用IO,于是我们放开假设4,程序都可以使用IO和CPU。</p> <p><img src="https://pic.code-nav.cn/planet_post_image/1628897468148121602/c3tfrvso.jpeg"></p> <p>时间片内发出IO操作,会自动放弃CPU资源,这个时候就会调度其他任务,当IO完成后,就又会将A任务设置为就绪状态,等待被调度,充分利用了上一个任务在时间片内等待IO的时间。"疯狂压榨CPU"(提升了CPU的利用率)</p> <p><br></p> <ol> <li data-list="ordered"><span class="ql-ui"></span>多级反馈队列</li> </ol> <p><br></p> <p>目前为止,我们的假设1,2,3,4都已经被我们放宽了,就只剩下假设5(每个工作的运行时间已知),这是这5个假设中最离谱,最不切实际的假设,因为根本无法知道程序到底需要运行多久。那么如果我们放宽这个假设,就会产生很多问题,比如基于时间的SJF和STCF策略都没法用了。于是就出现了现代化操作系统在用的调度方式 -- 多级反馈队列(MLFQ)</p> <p><br></p> <h5>基本规则</h5> <p><br></p> <ol> <li data-list="ordered"><span class="ql-ui"></span>存在多个队列,每个队列有不同的优先级</li> <li data-list="ordered"><span class="ql-ui"></span>每个队列中可以存在多个任务</li> <li data-list="ordered"><span class="ql-ui"></span>一个任务只能属于一个队列</li> </ol> <p><br></p> <h5>工作方式</h5> <p><br></p> <p>初始阶段,每个任务的优先级都是最高的,然后在同一个队列中的任务采用轮转的策略进行调度执行,在执行期间(一个时间片)如果主动放弃CPU会被视为交互程序,优先级保持不变,如果执行期间没有放弃CPU,那么被视为计算密集的任务,降低优先级。这种在运行过程中动态调整优先级的方式被称为用<strong>历史预测未来</strong>,只有高优先级的队列任务执行完之后,才会执行低优先级的队列中的任务。</p> <p><br></p> <p>但是这种方式并不完美,存在一个很大的问题,那就是饥饿问题,比如AB是交互性程序,C是计算型程序</p> <p><img src="https://pic.code-nav.cn/planet_post_image/1628897468148121602/i8lzlozl.jpeg"></p> <p>如果A B任务没有停止,那么C任务在后面就不可能被执行。于是就产生了饥饿问题,解决饥饿问题的方式就是经过一个时间段,将其他优先级的任务又重新添加到最高优先级的队列中,于是关键的问题在于<strong>如何确定时间段的大小</strong>,因为如果设置的过短,交互性程序得不到合适的CPU比例,过长,长时间的任务又会饥饿。于是这个时间段也被称为<strong>巫毒常量</strong>,其实除了这个问题以外,还有一个小问题,出现在确定优先级的策略上,目前我们的确定优先级的策略是:如果在一个轮转时间片中主动放弃CPU,那么就会保持优先级不变,如果没有放弃CPU,那么就会降低到下一个优先级队列中。有一些聪明的程序可以利用这个策略,在执行到时间片99.99%的时候主动放弃CPU,即便他是计算型任务也不会降低优先级。于是我们需要升级这个策略:每个任务在每个队列中存在总时间限制。确定优先级的策略变成了这样:<strong>在执行期间,如果一个任务在该队列中执行的总时间超过了配额,就会降低到下一个优先级队列中。</strong>这样就规避了上面这种投机取巧的方法。目前我们的多级反馈队列的调度方式已经很完美了,但是还是存在一个小小的优化点。那就是每个队列中,轮转执行的时间片是一致的,我们知道优先级越低的队列中,更多的是计算密集的任务,而轮转的调度方式需要进行上下文切换,有一定的性能开销,所以为了优化性能,我们可以将优先级低的队列的时间片设置的长一些,减少不必要的上下文切换。</p> <p><br></p> <h4>小结</h4> <p><br></p> <p>到此,主流的调度策略的演化过程就结束了。这里面有一种学习方法:在一个条件非常特殊的情况下讨论问题,给出解决方案,然后一步一步的放宽条件,放宽条件的同时一定会出现新问题,我们可以根据出现的新问题,提出新的解决方案,最后形成了我们最终的解决方案。有一种分而治之的味道在里面。</p> <p><br></p> <p><br></p> <p><br></p> <p><br></p> <p><br></p> <p><br></p> </div> </body> </html>
游戏研发 校招面经解读(一)
如何定义纯虚函数: C++:在一个类里面定义纯虚函数: 在函数定义后面加上= 0; 并且这个类就变成了虚基类,无法实例化,就是不能创建对象,只能被继承,并且继承之后,子类必须实现纯虚函数。 抽象类是实现多态的一种途径。可以提高代码的**可扩展性**和**灵活性**。 可扩展性:对**同一个接口**想实现**有区别的功能**的时候,只需要继承抽象类实现一个新的接口就行了。 灵活性:灵活地编程。**面向接口编程**,只需要改接口的部分,不需要改其他地方,而且**可以用抽象类的指针去指向其子类的对象**,这样就实现了以统一的方式处理不同的子类对象 C#中没有像C++那样的纯虚函数的概念,但是**依旧有抽象类和抽象方法** (abstract),不能实例化,方法不用实现public abstract void area(); C++ 和 C#的抽象类中都可以定义虚函数(非抽象方法),不用 =0 和 abstract,可以被继承,也可以被重写override C#的抽象方法只能定义在抽象类里面吗? 是的,因为不同的类不允许有没有实现的方法。 宏定义有哪些作用? 定义常量 定义函数 调试信息 #ifdef DEBUG #define LOG(x) std::cout<<x<<std::endl; #else #define LOG(x) //空展开 #endif 条件编译:#ifdef #ifndef #elif #if #elif #endif 用宏define出来的常量和函数,在使用到它的时候会进行宏展开,其实就是文本 替换,但是,就是因为宏是文本替换,所以他是类型不安全的。比如,用一个宏 实现比较大小的功能,如果是int,double这样的数据类型,他就可以正常工 作,但是如果传进去了两个字符串(sring),那就不能正常工作了 不会被编译器检查出来的错误有哪些? 要解决这种问题,可以用函数重载来实现,或者用模板来实现,对于 string,可以用模板特化来实现,自定义的数据类型的话,可以使用操作符 重载 条件编译和visual studio的debug模式, release模式有点像,比如说,我们可以**预定义好一种LOG宏函数**, #ifdef DEBUG #define LOG(X) std::cout<<X<<std::endl; #endif 并且它只有DEBUG这个宏被定义的时候才会被编译。 并且在代码段里面,也是用条件编译,只有DEBUG这个宏被定义的时候,相关代码才会被执行 #ifdef DEBUG Log(x); #endif C++是**类型安全**的编程语言:**绝大部分类型相关的错误能够在编译期间被检查出来** C++编译器找不出来的错误: **数组越界**:不管是[]还是vector,都无法在编译的时候找出越界问题 **访问空指针**:解引用空指针(nullptr)的时候 一个模板类有什么作用: 减少重复代码。模板类是编译时多态的一种体现,他把数据类型作为参数,在编译时对不同的数据类型生成特定的代码实现,能够减少重复代码的书写。像C++的STL容器就都是模板类 提高代码的灵活性和可扩展性:对某些特殊类型的实例化模板,我们可以进行模板特化,为它实现和模板类不同的功能。 增加类型安全。使用模板类,会在编译期间生成代码进行编译,同时会检查类型的正确性 提高性能,虽然会增加编译时间,但是比运行时再进行类型转换或者运行时多态快 C#的委托实际上是怎样的类型。 是一个特殊的类,是方法的容器,可以将任意个同类型的方法当作参数传递,存储和调用 C#的编译流程是怎样的 和C++很不一样。 先编译生成**中间语言(IL)**,存储在.exe或者dll中, 运行的时候,需要使用.NET框架,再经过一次JIT编译,.NET框架会根据不同的平台生成对应的机器码,这期间还会进行链接,优化等操作,并将程序载入内存 静态库和动态库有什么不一样呢 静态库会被拷贝至应用程序中,成为应用程序的一部分,因此调用它会更快,不过,当很多个程序都用到这个库的时候,内存中会出现很多个这个库的代码,浪费空间 动态库只有在**用到它的时候才会被加载进内存**,且内存中只会存在一个,允许多个程序共用这个库 C++ 动态库的代码是怎么被主程序执行的: 比如说,我现在要printf了,那么我就要用到**CRT(C RunTime)这个动态链接库**,它会被载入内存,但是我要怎么知道printf在哪里,我又要怎么读到CPU里面去并执行它呢? 当你的程序调用 CRT 中的 printf 函数时,**操作系统**会负责将 CRT 动态链接库加载到内存中。 在编译和链接过程中,链接器会将你的程序中对 printf 函数的调用**解析**为对 CRT 中 printf 函数在**内存中地址的引用**(这里是逻辑地址)。这样,在运行时,当你的程序调用 printf 函数时,它实际上是通过引用 CRT 中 printf 函数在内存中的地址来调用它的。 当你的程序运行时,操作系统会为它分配一个**虚拟地址空间**。虚拟地址空间中的**每个虚拟地址**都会通过内存管理单元(MMU)映射到物理内存中的一个物理地址。这个映射过程是由操作系统管理的,并且对你的程序是透明的。 因此,当你的程序调用 printf 函数时,它实际上是通过引用一个虚拟地址来调用它的。这个虚拟地址会被 MMU 映射到物理内存中“**CRT 动态链接库**”所在位置的一个物理地址。 这样,你的程序就能够通过引用这个虚拟地址来调用 CRT 中 printf 函数在内存中的实际位置。 操作系统会为每个进程创建页表,当进程被载入内存的时候,就会更新页表的内容 在用到了动态链接库的指令的时候,CPU会根据操作系统的MMU,访问到动态链接库所在的物理内存,取出相关的指令,便可以执行动态链接库的代码了(例如printf) 更多内容: 编程导航:https://www.codefather.cn/user/1646369469980790786/post 知乎:https://www.zhihu.com/people/xiao-xun-mo-yu/posts bilibili:https://space.bilibili.com/689579105
