《人有人的用途》(The Human Use of Human Beings — Cybernetics and Society)这本书是控制论鼻祖维纳(Norbert Wiener)的一本“科普书”,虽然只有100多页,还是32开纸,但是我觉得却是一本有深度的好书。首先,这本书并没有任何公式和严谨的控制理论,还有很多恰当的小例子,因此特别易读;但是虽易读,并非无营养,相反,每一段、每个观点都可以细读,引发思考。 与“科普书”的定位相比,更应当注意的是这本书的副标题:“控制论和社会”,作者不仅让人信服的解释了熵的概念、(机器)学习的概念、语言信息传递的原理;也对法律、社会政策等方面的思考和讨论;最后时甚至对未来发展进行预测……行文间,作者的例子不仅涉及自己的控制论,还包括信息论、生物学、热力学、社会学等多方面的思考。更令人叹服的是,虽1954年成书时人工智能之一概念才刚刚起步,作者在这本当时的“科普”书中,就已经能够看出各种现在很火的统计机器学习、仿生神经网络等让机器从历史经验进行未来预测的思想! 我读这本书并不快,但第一次也只是匆匆略过,现在想抽时间再读一遍,准备记下好的观点和自己对应的思考。总之,这是一本连相关专业学生都无法当科普书来读的科普书。 第一章 历史上的控制论 其实控制论是属于信息论的。 在控制与通信中,我们要与组织性降低和含义受损的自然趋势( 熵增 理论)做斗争。 一个复杂的动作可以有如下定义:为了影响外部( 输出 )而引入了可以有大量组合的数据( 输入 ),这些数据可能是当下刚放入的数据,也可能来自过去 存储 的数据(记忆)。(我感觉这种观点其实类似计算机系统的输入输出I/O和存储区memory/storage) 机器对自己的动作的后果作为下一步动作的所需信息,即是 反馈 。 作者认为生命个体和机器都是利用反馈来控制熵的,控制中枢用 自己打算做的(目的信息) 和 外界运演过的(反馈信息) 进行动作。 第二章 进步和熵 这一章作者进一步通过热力学第二定律的角度解释 熵增 的概念。 机器不一定可以称作“生命”,但和生命类似的地方是都在 整体的熵增 中,实现了 局部的熵减 。 消息传递的产生,一定伴随着能量的损失。 第三章 定型和学习–通讯行为的两种模式 (关于反馈) (定型应该指的是人的构造决定了人的多样和创造力,学习比较类似反馈思想或者现在的机器学习思想,从发生过的事总结经验,或者发生过的对未发生的动作产生影响) (摘录)学习,和比较简单的反馈形式一样,也是一种从未来看过去和从过去看未来的有所不同的过程。 (摘录)能学习的生物是从已知的过去走向未知的未来,而未来是不能和过去互换的。 作者认为,双向通信在控制中很重要,(其实就是反馈)。作者还进一步讲了“ 社会反馈 ”的概念,比如阶层之间、君臣之间的通信有着特殊的限制,不同于一般人与人间的通信。 (人类社会与昆虫社会的区别源自机械定型) […]

大部分截图来自原书,贴出书的官方主页: 《Operating Systems: Three Easy Pieces》 (作者Remzi H. Arpaci-Dusseau and Andrea C. Arpaci-Dusseau)。感谢原作者这么好的书。 本篇笔记是书的第三部分(Persistence),讲述了操作系统和外存系统相关的内容。 第一节 I/O Device 1.1 IO 总线 一般情况下, IO设备的性能较差(慢),所以用Peripheral IO Bus,为什么不用像显卡一样用的PCI呢?因为1)越快的总线越短,这样空间不够插;2)越快的总线制作成本越高,如果存储设备照总线的性能差的远,没必要用高性能总线。 这张图为总线的层次结构,memory bus是最快的也是最近的,IO Bus比较远,也是最慢的,中间有用于显卡的PCI等总线。 1.2 典型设备的组成部分 一个典型的外围设备如图所示,包括两部分: 接口 和 内部结构 。 接口: 类似软件接口的功能,硬件接口是留给OS和设备交互的。 内部结构: 比如㓟CPU、MEM等基本组件,还有称为固件(firmware)的软件来实现内部功能。 1.3 两种IO模式(Polling和Interrupt) Polling的形式,而interrupt。 一种典型的协议是 Polling (轮询),称为programmed IO,步骤有4: 循环等待STATUS寄存器直到设备状态为不busy 写数据到DATA寄存器 写命令到COMMAND寄存器 循环等待STATUS直到设备为不busy Polling显著的缺点就是太浪费CPU时间,这是因为IO相对于CPU是很慢的,大量的CPU时间被用在了等待上。 Interrupt (中断)方法(也称为interrupt-handling IO)可以解决这个问题,用Interrupt方法进行IO时,当设备完成操作时,会raise一个硬件interrupt。但是这样的话,如果设备很快(比如现在的NVMe SSD设备),Interrupt由于需要进程上下文的切换、以及中断的控制等原因,会拖慢IO的速度。所以两种方法各有利弊: Polling […]

大部分截图来自原书,贴出书的官方主页: 《Operating Systems: Three Easy Pieces》 (作者Remzi H. Arpaci-Dusseau and Andrea C. Arpaci-Dusseau)。感谢原作者这么好的书。 本篇笔记是书的第一部分(Virtualization)的下半部分,讲述了操作系统是怎么通过地址空间的抽象,将内存资源进行虚拟化的。 第一节 地址空间 1.1 内存虚拟化 多进程OS的资源共享策略 本书上半部分讲了CPU的共享策略:通过进程(process)这个抽象,OS将时间片分给进程。 对于内存资源的共享:为了让昂贵的计算机能够支持多个程序同时运行,如果在切换某个进程时将内存数据从磁盘换入(进程共享磁盘,内存和寄存器都不共享),由于磁盘IO太慢,不现实。所以现在的系统,都是将相对较快的寄存器换入换出 ,所有进程数据共享内存资源( 寄存器不共享,内存共享 )。为了实现这种想法,并更好地管理内存, 地址空间(Address Space) 的抽象被引入(如下图),相对为每个程序固定分配一定大小的内存空间更灵活,用地址空间进行管理更加灵活。 地址空间在 结构 上主要分为Code、Heap和Stack,Code部分用来存程序运行的代码,Heap是用户程序动态分配内存(malloc/free)所使用空间,Stack是变量使用的空间。除非程序递归很多,一般Stack都是够用的;如果程序视图访问非法地址,可能出现Segmentation fault的错误。 每个进程都会有一个自己地址空间,且每个进程都认为自己的地址空间是从0开始的,并且地址空间的地址也不必和物理地址相等,甚至地址空间的总大小可以大于物理内存大小,这就体现了一种 内存虚拟化 的概念,OS的内存管理系统也可以称为 虚拟内存系统(virtual memory system, VM) 。因此,我们编写的程序中,所有我们可以得到的地址也都是虚拟地址,并非物理地址。 VM系统设计的三个目标:透明(transparency)、高效(efficency) 和 保护(protection) 。其中保护即隔离(isolation),进程间的地址空间需要隔离,进程和OS间也需要隔离,(甚至在有些微内核操作系统中,OS的一部分和OS的另一部分也进行了隔离),这样可以保证安全性。 1.2. memory API 对于用户程序,Stack中的变量是自动管理的,比如用int声明一个整数变量,而Heap中的内存是由程序(程序员)负责的,什么时候malloc/free都要程序员进行考虑,所以要格外小心一些常见的malloc错误,比如忘记分配内存、分配的不够导致buffer overflow、忘记初始化所分配内存内容、忘记free等。 purify 和 valgrind 这两个工具可以协助检测内存分配的问题。 1.3. malloc、free和mmap的关系** 要注意 […]

截图来自原书,贴出书的官方主页: 《Operating Systems: Three Easy Pieces》 (作者Remzi H. Arpaci-Dusseau and Andrea C. Arpaci-Dusseau)。感谢原作者这么好的书。 本篇笔记是书的第一部分(Virtualization)的上半部分,讲述了操作系统是怎么通过进程的抽象,将CPU计算资源进行虚拟化的。 第一节 进程的抽象 1.1. 策略和机制 Policy在mechanism(策略和机制)在操作系统中通常是分开设计的。比如如何切换上下文是一个low-level的mechanism,指底层的方法或者协议。当前时刻应该让哪个进程运行更好是一个high-level的policy的问题,指一些“智能”的调度。 1.2. 虚拟化和OS OS本身就可以看做是“虚拟机”(virtual machine)。系统通过在可以被接受的合理开销(时间、空间)范围内,将计算机CPU、内存、存储等资源进行虚拟化(抽象),目的是为了用户的方便使用。 CPU虚拟化 主要体现在将任务抽象为 进程(process) ,将资源按进程隔离,然后多个进程轮转使用计算资源; 内存虚拟化 主要体现在 虚拟地址空间(virtual address space 或 adress space) ;而对于持久化的 存储 ,OS让文件共享,没有那么多私有隔离,OS假定用户会用文件来共享数据。 (????) 第二节 进程API 2.1. fork和exec exec()函数组和fork()的区别是:fork()复制当前进程为一个子进程执行,exec()会执行一个新的程序;exec()执行以后就再也不会返回。 2.2. shell和stdout redirect 例如shell就是一个普通的用户程序,利用了fork和exec的组合。给出一个提示符,你输入可执行程序时,会先fork(),然后在fork出的子进程中exec()这个命令,然后调用wait()来结束。这种fork和exec的组合使用,可以在让shell在fork后运行一些其他代码:fork后的子进程可以redirect操作再exec;fork后的父进程可以执行wait操作在exec结束后再显示提示符prompt。 stdout redirect的原理很简单,stdout一般的fd都是0,在fork后的子进程中close掉stdout,然后打开要redirect到的文件,这个文件就会获得为0的fd,这时执行新命令的exec,则会把这个为0的文件看做stdout进行输出,程序清单如下图: 2.3. 其他 kill()可以向进程发送信号,让程序sleep, die。 第三节 […]

谁来定义虚拟化? 一个比较抽象的词,很难给出一个比较明确的定义,而且我也一直认为没有人可以对一个抽象的概念给出绝对正确的定义。如果一个公司想争夺一种技术的定义权,我会毫不吝啬的给它扣上“技术独裁者”的帽子。 但是理解一个词在当前这个时代、这个世界的用法还是很有必要的,比如“虚拟化”这个词,对虚拟化开始重点关注以来,对“虚拟化”这个词的理解的确是在逐渐变化的,今天就来说一说我目前为止的理解。 从虚拟机说起 关注虚拟化方向之前,我对虚拟化这个词的理解是经历了几个阶段的。最开始可能“虚拟机”啊,有了虚拟机,大家就能方便地在Windows下用Linux系统啦。后来云计算火起来了,云服务器的底层技术是什么啊,是虚拟机和虚拟化啊,所以感觉虚拟化真是很牛逼。后来Docker火了,Docker是什么,人家都说是“轻量级的虚拟化”,哇,虚拟化这么牛逼,虚拟机、云服务器、Docker都用了虚拟化啊。 虚拟机就像下面的图中,如果把一个计算机软硬件系统比作一个从地基垒起的金字塔(用户和应用在金字塔顶),那么虚拟机就像一个倒立的金字塔,虚拟机的用户就像是倒立的金字塔上的金字塔。要让一个虚拟机正常运转,就要在软件层面上模拟各种计算机硬件,涉及到计算,存储,网络等各种设备。 以QEMU为例,虚拟机的CPU是以QEMU创建的vCPU线程进行模拟的,这些线程仍然由Host操作系统进行调度;虚拟机的网络和存储IO是通过virtio这种半虚拟化机制达成的,Guest的IO通过内存的循环队列传递数据和消息;虚拟机的存储设备通过Host中的一个文件来进行模拟……但是虚拟机(Virtual Machine)所用的技术就是虚拟化技术(Virtualization)吗?我认为不一样。 虚拟机之外的虚拟化 以存储虚拟化(Storage Virtualization)为例,Linux逻辑卷管理技术(LVM),有了这种技术,我们可以将多个分区虚拟成一个大的逻辑分区,或者将一个分区虚拟成多个小的逻辑分区。LVM之外,Linux中的loop回环设备(将一个文件虚拟成一个块设备)、tmpfs(将一段内存虚拟成一个文件系统分区)、RAM DISK(将一段内存虚拟成一个块设备)、UnionFS(将多个文件系统虚拟成一个文件系统)在我理解都应该属于虚拟化之列。而QEMU虚拟机中,我们多是把一个文件虚拟成一个磁盘,其灵活性无法代表整个存储虚拟化技术,或者说仅关注QEMU,我们不能关注到所有的存储虚拟化技术。 QEMU VM的vCPU是Host操作系统中的线程,可以看做是计算的虚拟化。其实按照广义的虚拟化,Intel的超线程(Hyper-threading)技术岂不更加“虚拟”?比如它可以将一个核抽象成操作系统看来的两个核。 虚拟化,无处不在 更广义(准确)的,其实操作系统技术本身就是虚拟化技术,没有操作系统的进程调度时间片切换,也许CPU是1核的就只能同时跑1个程序,但有了操作系统,你不仅能同时照着网页抄作业、还能看着paper听着歌。这一切都是系统将计算资源虚拟化的结果啊。 再说编程语言,程序员之所以不用编写二进制代码,便是因为有工具可以将高级语言翻译成机器码,如果不去研究编译器,这种翻译也是透明的;编程语言,形形色色,不管你用哪种,其实背后都是0,1在执行(电位在变化)。我可以在这篇博客里写一串二进制码011110100110101001100011,你看到的0和1并不是底层的0和1,但还是0和1,不也是类似虚拟机软件反向搭建金字塔的过程吗?同样,人类语言也可以看成是思想的“虚拟化”。 所以,什么是虚拟化?虚拟化,道也,什么是道?老子说,“道可道,非常道”。

0. 环境 iOS 10 + MacOS 10.12 + Python 2.7 1. 思路 APP界面中弹出的题的位置和答案的位置都是固定的,因此我们可以将手机屏幕想办法投到电脑屏幕上,通过OCR识别指定区域,实时打开搜索引擎界面搜索问题,甚至匹配答案。 2. 关键步骤 2.1 投屏 我是iPhone 5s + Mac电脑,可以用Mac的Quicktime Player播放器的屏幕录制功能(安卓据说可以用ADB)。 具体的,打开Quicktime Player后,点击“文件–新建屏幕录制–(红色录制按钮旁的下拉菜单)选择从手机录制”,这时,手机屏幕就实时投到屏幕上了。 2.2 截屏和OCR 截屏 截屏要将你的手机投屏窗口固定在一个位置,找准屏幕上的左上角和右下角两个坐标,利用PIL中的ImageGrab进行抓屏,以截取题干为例,代码如下: from PIL import ImageGrab image = ImageGrab.grab((50, 170, 540, 330)) OCR 利用tesseract库和对应的pytesseract接口进行OCR,具体配置可以参考[1]。 import pytesseract ocr_str = pytesseract.image_to_string(image, lang=’chi_sim’) 2.3 搜索 分两种思路,我们可以直接打开一个浏览器页面用百度搜索,把答案筛选工作交给人: import webbrowser url = “http://www.baidu.com/s?rn=50&wd=” + […]

0. GCC的attribute关键字 这是GCC的一个特性,gcc可以使用attribute关键字,格式如下: __attribute__((attribute_name)) 其中attribute_name中有两类constructor和destructor类似C++中类的构造和析构的概念,只不过是相对main()函数来说的。简单说,__attribute__((constructor))定义的函数在main前执行,__attribute__((destructor))定义的函数在main后执行。 1. 以qcow2为例 QEMU中有很多”module”的初始化使用了__attribute__((constructor))这个特性,来在main前完成init函数的注册过程。使用方法举例具体如下: // QEMU_2.10_SRC/include/qemu/module.h中: #define module_init(function, type) \ static void __attribute__((constructor)) do_qemu_init_ ## function(void) \ { \ register_module_init(function, type); \ } #endif typedef enum { MODULE_INIT_BLOCK, MODULE_INIT_OPTS, MODULE_INIT_QOM, MODULE_INIT_TRACE, MODULE_INIT_MAX } module_init_type; // 比如这里block_init函数被用在QEMU_SRC/block/*的qcow2等Format Driver中广泛应用, // 其实就是间接调用了被__attribute__((constructor))调用的register_module_init() #define block_init(function) module_init(function, MODULE_INIT_BLOCK) #define opts_init(function) module_init(function, MODULE_INIT_OPTS) #define type_init(function) module_init(function, MODULE_INIT_QOM) […]

欢迎评论。。以后还可能写个版本2。。。 冗余的人类语言 研表究明,汉字序顺并不定一影阅响读!事证实明了当你看这完句话之后才发字现都乱是的。 以上这句话很多人都看到过,知乎上也有很多人讨论问题的原因[2],对于这段中文,有人从贝叶斯决策的角度分析,指出这是由于人借助了上下文的相关信息+日常的经验。对于英文,如果把一段话的每个单词的字母顺序打乱,也会出现不影响阅读的情况,有人指出这可能是人在阅读一个单词时只看第一个字母和最后一个字母的原因。我感觉都是有道理的。 但现在我们要从另一个角度考虑这个问题: 假设在另一个平行宇宙中,汉语“研表究明”和“研究表明”存在截然不同表示的是两种截然不同的意思,那么就算那个宇宙中的人们可能就觉得这两个词是有区别的。 再假设一个更极端的平行宇宙,他们每个单词都长为6个字母,且只能由ABCDEF 6种字母组成(我算了下有4万多种组合,够多了),那么,他们对词序的判别应该就特别严格吧。 可见,我们所在的平行宇宙中,语言中是存在“冗余”的。这样,不管依据什么经验,语言的冗余,让我们辨识出调换词序的句子的原本意思成为可能。 其实不光调换词序体现了这种冗余。类似的,当我们在一个噪音大的环境中讲话的时候,或者在FM收音机中调出一个信号不好的电台时,我们一般情况下照样可以听明白对方所讲,靠着也是这种“冗余”,我们可以根据已知的信息,猜出完整的信息。 0和1:抗干扰的冗余 接着说收音机。如前边所说,我们的语言中存在”冗余”,所以接收的电台中音调偶尔的变化或者一些字的不清晰依然不影响我们接受信息。那么为什么现在的网络电台没有这些失真、底噪呢,人们靠什么高科技来消除这些噪声干扰? 我们常见的收音机,不管是调幅的还是调频的,都是以模拟信号进行传输的,这种信号直接将要传输的信息以幅度或者频率的形式均匀地映射(调制)到负责传输信号的电磁波(载波)上,由于传输的过程(信道)中信号必然是被各种干扰(噪声)的,于是我们的收音机接收到的电磁波转换到声音的形式(解调)时,干扰信号(噪声)也就被一一映射到了声音(噪音)传到我们耳朵中。 但是现在的网络传输,多数基于数字信号。信号都不再是一一映射到频率值或幅度值了,而是仅映射为一个由0或1(两种频率或幅度)组成的编码。我们假定一个最简单的串行通信,在一个时刻,只能有0或1两种可能,假设信道中存在干扰(比如0被干扰到0.2还会被认为是0信号,1被干扰为0.9还会被认为是1信号),接收后的结果也大概率没有出错。其实这也是一种冗余,一种防止出错的冗余。 0, 1, 2, 3:高效的冗余? 我们为了信息的稳定传输,将无限种状态映射到两种状态(0和1)的编码。但是,我们为什么一定要2种状态呢?为什么不能是0, 1, 2三种状态呢?如果这种可能容易实现(电路上),而且人们最开始没有走上普及二进制计算机这条不归路,那么可能我们现在用的都是基于三机制的电脑了[4]。 技术上的难度或者转换的巨大成本,让人类点了”二进制”这条科技树。不过人们虽然没有用3种状态,但是用4种状态或者8种状态的情况倒是有很多,因为这能保证了和系统其他部分的二进制组件兼容。 比如在信息存储中,固态硬盘(SSD)的MLC/TLC技术,就是在每个存储单元中把以前SLC的两种状态(电压)记录信息,转为用4种/8种电压来记录信息,这样做便增加了SSD的存储密度。 (0, 1, 2, 3) + X: 不可避免的冗余 但是,这种4种或8种状态的SSD,虽然提高了存储密度,但它们的存储单元的寿命会缩短,所以制作这种SSD的时候,就一定要在设备内部预留更多的备用存储单元,这也是一种冗余。看来冗余从抗干扰的冗余被迫转为空间的冗余。 当然,我们也可以采用校验/纠错码技术,用更小的空间冗余来保证信息的可靠。但是编码或数据恢复都需要话费额外的计算时间。如果我们比起冗余空间的开销,更不看重数据恢复的时间,那么看起来空间的冗余又转为了时间的冗余。 看来,冗余无法避免,0/1到(0, 1, 2, 3),虽然它们减少了信号抗干扰的冗余,但是最终也无法避免的使用了其他的冗余。X可能是空间,可能是时间,但到今天这个世界中,都会是money,无法预测的money。 扩展阅读 [1] 熵:宇宙的终极规则, http://www.ruanyifeng.com/blog/2017/04/entropy.html [2] 知乎:为什么汉字顺序有时候不影响阅读? https://www.zhihu.com/question/20428571 [3] 知乎:如何从心理学上解释『打乱英语单词首尾字母之外的字母顺序仍然不影响阅读』的现象?https://www.zhihu.com/question/20804531/answer/16237704 [4] 知乎:苏联三进制计算机Сетунь到底是怎样一个计算机?https://www.zhihu.com/question/35937929

“新司机”虽然上路了,但并不知道走了多少弯路,因为还知道有没有走上正路。但上路也快一年了,当然有一些体会,就算是错的,也该想过些什么。如果我什么体会都不写出来,那么这些想法总会在我的脑子中绕啊绕啊的。所以我希望写些出来,也许这样就可以不用刻意提醒自己不要忘记它们,也好专心”开车”。而且我想,车技总是不断积累联系和回看总结的过程,也许我将来看现在自己的体会,不是嘲笑自己的车技太差就是羡慕自己的没有迷路运气。当然还有一种情况,就是我能因这些感想能将其他”新司机”带上(歪)路,我也是很欣慰的。。。 这系列文章,不去反省自己的缺陷,不去叙述自己的经历,只写下当前所总结的体会。本篇博客,我将写一下对存储栈的理解。后边,我还可能从存储组织(文件系统/存储结构)、存储缓存和虚拟化存储等几方面写下体会。 1. 层次化封装 就像OSI网络参考模型一样,存储也是有层次的,如果在网络中我们将这些层次称为网络协议栈(TCP/IP协议栈),那么在存储中我们经常用存储栈(storage stack)或I/O栈(I/O stack)与之对应。 顾名思义,栈这一种直上直下一层叠一层的结构。在网络的层次中,数据链路层关心的是MAC地址,网络层关心的是IP地址,栈中的所有层次分工协作,大家像流水线一样将数据层层传递如下图。 在存储层次中,也有类似的分工。比如以Linux存储栈为例,文件系统主要关心的是文件的组织结构,向上将接口暴露给用户;而文件系统下一层的块存储设备层则关心实际数据的去向,主要和存储设备打交道。下图是一个单机上比较复杂的情况,以一个运行在KVM虚拟机中的MySQL为例。当然如果考虑远程网络分布式存储,应该更复杂。 2. 为什么层次是必要的 除了网络和存储,其实编程语言中封装的这种概念,在我看来就类似这种层次化的形式。比如在很多编程语言中常用的SHA256、MD5等安全Hash算法或者链表、各种常用数据结构的库等。这节的问题就以编程中的封装和层次开发为例进行说明。 对编程语言的库来说,问题在于,既然哈希算法的计算方法都是开源的,数据结构都是固定的形式,为什么不自己写呢?首先想到的可能是自己写费时费力,其次一个被很多人使用的库一般都是由各路大神优化而来,应该比自己实现的效果要好,但最重要的,库是可以复用的。 比如那么当我们在这些其他人实现的库的基础上构建自己的应用的时候,就是在库的封装之上进行的开发,这就形成了库–>我的应用的这样的层次结构。进一步说,如果我们是在其他人的库的基础上开发了更高层的库,比如我在其他人写的二叉树库的基础上开发了用于排序的库,那么我们的封装层次就又涨了一层:二叉树库–>排序库–>其他人的应用。再展开说,我们甚至可以冲破一种编程语言的界限,表示出更完整的封装层次:数字逻辑–>指令集–>汇编语言–>系统调用–>编程语言标准库–>二叉树库–>排序库–>其他应用。 如果只是从左到右或者从上到下画出这种层次图,我们还是无法理解层次的必要性,但是如果我们想横向扩充,这种层次就是很必要的。极端的情况:如果我们所有的层次都重叠在一起,那么也许我想开发一个gui小应用,就要从汇编开始,一直沿着操作系统改到库和应用逻辑,简直不现实,这也是软件工程中耦合和内聚的概念。换句话说,不论我们是靠近硬件还是靠近应用的程序员,我们都可以从自己出发,只要向上层和下层提供不变的接口,那么不论我们在自己的范围怎么折腾,都不会破坏其他层次的工作。 回到存储,我们只有将管理文件的file system和下层的设备驱动通过块设备层和虚拟文件系统(VFS)层解耦,才能在单独编写多中设备驱动不用再去修改文件系统代码,也才能在添加新的文件系统功能的同时不用担心对老的设备是否可以工作。 3. 为什么层次可能影响性能 还是以编程语言为例,很多都认可C语言相对其他语言是高效的,但学汇编的人可能觉得汇编才是最高效的,这都没有错,汇编比C高效,但并不属于高级程序语言,C比Python高效,但是指针这种东西没有谁可以一时半会搞定。实际上,汇编–>C–>Python就可以认为是这样封装起来的。某种程度上来说,我们开发C语言应用可以看成是和开发Python是在一个层次上的。。。对于存储也是一样的,层次总是一层一层网上堆的。堆到越上层,越具有其简单易用的特性,而这种层次化页必然会带来性能上的降低。 现在在我看来,存储层次升高带来的性能损失的根本原因是因为在层次间信息的不对称的同时还有些层次要越层”搞事情”。具体来说,层次之间的沟通通过接口,由于层次间较松的耦合,某一层中无法获知其他层中的具体细节。比如,应用程序可能要告诉文件系统具体要读的文件名,但并不知道文件具体存在什么地址;文件系统可能告诉块设备驱动它具体要读内容的地址,但是块设备层就不知道这内容属于什么文件了。 但是,存储的管理不光“你告诉我你要什么数据,我把数据传给你”那么简单:首先,由于数据的重要性,各个层次都要用自己的机制保证数据的完整性和一致性;其次,也要利用数据的局部性,用dram作为cache来弥合内存和二级存储设备间的性能差异。那么大家都要保证数据可靠,大家也都在加把劲降低IO读写延迟,真的是齐心协力力量大吗? 当然大家都想整个系统变得更好,但是既然层级之间信息不对称,一定会因为缺少合作,而导致自己所做的工作不如预期,甚至起到副作用。我们是需要加强各层间的耦合交互?还是提升各层的“智能”让其揣测其它层的想法?还是应该聘请一个“存储栈独裁程序”来统一发出号令?这块儿学问就大了,还是新司机的我理解并不够深入,车技提升后还要展开多写写。。。 4. 在适当的层次做适当的事 Python认为程序员要指针没啥用,于是没有设计出指针的概念。而可能在一些C语言程序员眼中,Python因此就是一种有缺陷的语言。但是我们可能忽略了一点,就是没有谁禁止过Python程序员学习C语言,也没有人禁止过C程序员学Python。对于一个项目来说,没有最好的语言,只有最合适的。 对于存储层次同样如此,比如同样是数据加密,我们可以在应用程序中加密数据,可以在文件系统中加密数据,可以在数据网络传输之前进行,极端的情况,甚至也可以在硬盘硬件中进行加密。对于cache,我们可以在应用层开辟内存作为cache、或者利用文件系统缓存,或者磁盘的硬件缓存等。选择很多,不同的功能,适合的位置也是不同的,同样和上节一样,这块儿学问就大了,还是新司机的我理解并不够深入,车技提升后还要展开多写写。。。

手动搜集资料,不敢保证无误,如有错误,恳请指正。 1. 设备 最新的3D XPoint存储器比DRAM慢10倍,便宜2倍;比NAND FLASH快1000倍,贵5倍左右,性能比其他PCIe和NVMe的SSD快10倍左右。并且它是一种NVM。 下表摘自[2] Type Volatile? Writeable? Erase Size Max Erase Cycles Cost (per Byte) Speed SRAM Yes Yes Byte Unlimited Expensive Fast DRAM Yes Yes Byte Unlimited Moderate Moderate Masked ROM No No n/a n/a Inexpensive Fast PROM No Once, with a device programmer n/a n/a Moderate Fast EPROM No Yes, […]