自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(36)
  • 收藏
  • 关注

原创 leveldb(二):Arena

Arena是Leveldb的简单的内存池,它所作的工作十分简单,申请内存时,将申请到的内存块放入std::vector blocks_中,在Arena的生命周期结束后,统一释放掉所有申请到的内存,内部结构如图所示。 class Arena { public: Arena(); ~Arena();//析构函数统一释放所有申请的内存 char* Allocate(size_t bytes)

2017-06-28 15:49:18 332

转载 C++11开发中的Atomic原子操作

原子操作在多线程开发中经常用到,比如在计数器,序列产生器等地方,这类情况下数据有并发的危险,但是用锁去保护又显得有些浪费,所以原子类型操作十分的方便。原子操作虽然用起来简单,但是其背景远比我们想象的要复杂。其主要在于现代计算系统过于的复杂:多处理器、多核处理器、处理器又有核心独有以及核心共享的多级缓存,在这种情况下,一个核心修改了某个变量,其他核心什么时候可见是一个十分严肃的问题。同时在极致最求性...

2017-06-28 15:11:28 1520

转载 memory barrier(内存屏障)

一、前言我记得以前上学的时候大家经常说的一个词汇叫做所见即所得,有些编程工具是所见即所得的,给程序员带来极大的方便。对于一个c程序员,我们的编写的代码能所见即所得吗?我们看到的c程序的逻辑是否就是最后CPU运行的结果呢?很遗憾,不是,我们的“所见”和最后的执行结果隔着:1、编译器2、CPU取指执行编译器将符合人类思考的逻辑(c代码)翻译成了符合CPU运算规则的汇编指

2017-06-28 15:02:00 871

原创 leveldb(一):AtomicPointer

AtomicPointer 简介AtomicPointer 是 leveldb 提供的一个原子指针操作类,使用了基于内存屏障的同步访问机制,这比用锁和信号量的效率要高。源文件位置:leveldb/port/atomic_pointer.h 它的实现主要分为两种:(一)利用std::atomic实现AtomicPointer  std::atomic对int, char, bool等数据结构进行原子

2017-06-28 14:58:26 1414 1

转载 SSD 之WA写入放大

WA是闪存及SSD相关的一个极为重要的属性。由于闪存必须先擦除才能再写入的特性,在执行这些操作时,数据都会被移动超过1次。这些重复的操作不单会增加写入的数据量,还会减少闪存的寿命,更吃光闪存的可用带宽而间接影响随机写入性能。WA这个术语在2008年被Intel公司和SiliconSystems公司(于2009 年被西部数据收购)第一次提出并在公开稿件里使用。       举个最简单的例子:当要

2017-06-28 10:23:38 704

转载 SSD 之OP预留空间

SSD上的OP指的是用户不可操作的容量,大小为实际容量减去用户可用容量,OP区域一般被用于优化操作如:WL,GC和坏块映射等。       OP一般分三层(见下图)。第一层容量固定为SSD标称容量的7.37%,这是因为标称容量采用千进制为单位,而NAND颗粒容量单位为1024进制,两者正好相差约7.37%。这部分空间被默认用于作OP。第二层OP是否存在及容量大小取决于厂商设置。第三层OP是用户

2017-06-28 10:22:51 1259

转载 SSD卡驱动中trim命令的实现原理

有关trim命令的简介 可以看下http://blog.csdn.net/yuzhihui_no1/article/details/46519701这里就大概的说下驱动中对trim命令的实现吧,由于对公司代码的保密性,这里就不沾贴代码了,就大概的说下实现原理;条理会有点乱,也借此机会复习整理下一些相关知识点;首先是块设备的基本框架:队列 queue和

2017-06-28 10:21:05 565

转载 SSD 之Trim指令

Trim,其实是一个ATA指令,并无正式中文名称,操作系统发送此指令给SSD主控,以通知它哪些数据占用的地址是‘无效’的。       在讲解Trim的重要性前,先说一点文件系统的相关知识。当我们在操作系统中删除一个文件时,系统并没有真正删掉这个文件的数据,它只是把这些数据占用的地址标记为‘空’,即可以覆盖使用。但这只是在文件系统层面的操作,硬盘本身并不知道那些地址的数据已经‘无效’,除非系统

2017-06-28 10:19:03 968

转载 SSD 之GC垃圾回收机制

在前面向大家讲解FTL时,我们提到了GC的操作,所谓GC就是把一个闪存块里的‘有效’页数据复制到一个‘空白’块里,然后把这个块完全擦除。GC是SSD里的一个非常关键的操作,其效率对性能有决定性影响。闪存块里‘有效’页的数量对GC效率有决定性的影响,因数量越少,需要复制的页就越少, 花费的时间也越少,效率就高了。(GC操作参考下图)请看下图,把X块和Y块里的“有效”页复制到N块里,然后擦

2017-06-28 10:15:06 668

转载 SSD 之wl(wear leveling)算法分析

Wear-Leveling算法  众所周知,SSD的寿命局限于它的读写次数。对相同的存储单元不断地进行编写和擦除将更容易导致该存储单元受到永久性的损害。为了避免该情况的发生,有一种叫“Wear-Leveling”的特殊的算法被配置到SSD中。该算法的中文译名为均衡磨损。顾名思义,Wear-Leveling就是将擦除/写入循环平均地分配到SSD的所有存储单元中。这样就避免了对同一个存储单元持

2017-06-28 10:06:17 3164

转载 SSD 之WL磨损平衡

闪存寿命是以P/E次数来计算的,而WL就是确保闪存内每个块被写入的次数相等的一种机制。若没有这个机制,SSD内的闪存颗粒就无法在同一时间内挂掉,那对用户来说就是灾难。       会出现这种情况的原因在于,用户在LBA空间里的数据更新速度是不同的,有部分是经常需要更新,而有些却长期不需要变更,因此若没有WL,很显然那些经常被更新的数据所在的闪存寿命会首先被消耗完毕,而不怎么需要变更的数据所在的

2017-06-28 09:57:18 997

原创 NVM(非易失性内存)科普篇

NVM特性NonVolatile Memory,非易失存储器,具有非易失、按字节存取、存储密度高、低能耗、读写性能接近DRAM,但读写速度不对称,读远快于写,寿命有限(需要像ssd一样考虑磨损均衡)。当电流关掉后,所存储的数据不会消失的计算机存储器。没有数据寻道,这点和ssd比较像。常见NVM: 相变存储器(PCM,phase change memory)  磁阻式存储器(MRAM,M

2017-06-27 14:13:03 26150

转载 ssd与基于ssd的文件系统

固态驱动器当前非常流行,但是嵌入式系统很久以前就开始使用固态驱动器进行存储。您可以看到 flash 系统被用于个人数字助理(PDA)、手机、MP3 播放器、数码相机、USB flash 驱动(UFD),甚至笔记本电脑。很多情况下,商业设备的文件系统可以进行定制并且是专有的,但是它们会遇到以下挑战。基于 Flash 的文件系统形式多种多样。本文将探讨几种只读文件系统,并回顾目前可用的各种

2017-06-27 13:27:42 1305

转载 如何高效的访问内存

影响内存访问速度的因素主要有: 1.内存带宽:每秒读写内存的数据量,由硬件配置决定。 2.CACHE高速缓冲:CPU与内存之间的缓冲器,当命中率比较高时能大大提供内存平均访问速度。 3.TLB转换旁视缓冲:系统虚拟地址向物理地址转换的高速查表机制,转换速度比普通转换机制要快。我们能够优化的只有第2点和第3点。由于CACHE的小容量与SMP的同步竞争,如何最大限度的利用高速缓冲就是我们的明确优化

2017-06-27 09:54:40 945

转载 SSD 之FTL转换层

闪存的读写单位为页,而页的大小一般为4KB或8KB,但我们的操作系统读写数据是按HDD的扇区尺寸进行的(512Byte(字节)),更麻烦的是闪存擦除以块作单位,而且未擦除就无法写入,这导致操作系统现在使用的文件系统根本无法管理SSD,需要更换更先进、复杂的文件去解决这个问题,但这样就会加重操作系统的负担。       而为了不加重操作系统的负担,SSD采用软件的方式把闪存的操作虚拟成磁盘的独立

2017-06-26 18:00:34 755

转载 Paxos协议

Paxos是什么Paxos 算法解决的问题是一个分布式系统如何就某个值(决议)达成一致。一个典型的场景是,在一个分布式数据库系统中,如果各节点的初始状态一致,每个节点都执行相同的操作序列,那么他们最后能得到一个一致的状态。为保证每个节点执行相同的命令序列,需要在每一条指令上执行一个“一致性算法”以保证每个节点看到的指令一致,是分布式计算中的重要问题。Paxos的两个原则安全原则—保证不能做错的事只

2017-06-26 16:02:34 353

转载 TLB工作原理

TLB - translation lookaside buffer快表,直译为旁路快表缓冲,也可以理解为页表缓冲,地址变换高速缓存。由于页表存放在主存中,因此程序每次访存至少需要两次:一次访存获取物理地址,第二次访存才获得数据。提高访存性能的关键在于依靠页表的访问局部性。当一个转换的虚拟页号被使用时,它可能在不久的将来再次被使用到,。 TLB是一种高速缓存,内存管理硬件使用它来改善虚拟地址到物理

2017-06-24 10:55:22 2059

转载 cache的write through和write back

程序的局部性原理:是指程序在执行时呈现出局部性规律,即在一段时间内,整个程序的执行仅限于程序中的某一部分。相应地,执行所访问的存储空间也局限于某个内存区域。局部性原理又表现为:时间局部性和空间局部性。时间局部性是指如果程序中的某条指令一旦执行,则不久之后该指令可能再次被执行;如果某数据被访问,则不久之后该数据可能再次被访问。空间局部性是指一旦程序访问了某个存储单元,则不久之后。其附近的存储单元也将被

2017-06-23 13:56:30 362

原创 vfs的数据结构

每个VFS对象都存放在一个恰当的数据结构中,其中包括对象的属性和指向对象方法表的指针。内核可以动态地修改对象的方法,因此可以为对象建立专用的行为。超级块对象struct super_block { struct list_head s_list; /* 所有的super_block都通过s_list链接在一起 */ dev_t s_dev;

2017-06-22 18:44:24 396

原创 什么是vfs以及vfs的作用

vfs(虚拟文件系统)是什么?我们知道文件系统的种类有很多。除了Linux标准的文件系统Ext2/Ext3/Ext4外,还有很多种文件系统 。linux通过叫做VFS的中间层对这些文件系统提供了完美的支持。在大部分情况下,用户通过libc和kernel的VFS交互,不需要关心底层文件系统的具体实现。我的理解,vfs就是对各种文件系统的一个抽象,它为各种文件系统提供了一个通用的接口,类似于c++中虚基

2017-06-22 16:34:49 17793

原创 node与zone

node内核使用结构体pglist_data ,管理node中的内存资源所有node的pglist_data结构地址都放在数组node_datastruct pglist_data *node_data[MAX_NUMNODES];//64#define MAX_NUMNODES (1 << CONFIG_NODES_SHIFT)node中的内存资源,被划分成若干zone ZONE_DMA

2017-06-22 15:15:19 351

原创 判断某个页框pfn是否有效(section和root)

前言在一些系统中,物理地址空间存在许多的空洞——无效区域 内核需要管理有效区域,只为或尽量只为有效区域中的页框建立page结构,避免物理内存的浪费如何管理有效区域?以页框为粒度?如位向量、………… 空间复杂度同页框(无效+有效)个数线性相关,扩展性差以若干长度不等的有效或空洞区域为粒度?如线段树、………… 时间复杂度差,和有效区域个数成log关系Linux内核以section为粒度时间和

2017-06-13 22:03:01 912

原创 页框page

物理内存被划分成固定大小的块,称为页框内核以页框为基本单位管理物理内存。内核为每个页框都建立了一个page结构,使用struct page结构体描述一个页框。page采用了元数据与数据分离的方案page结构并不存放在其所描述的页框内专门从内存中分配了若干空间,存储所有页框的page结构从线性地址空间角度,所有page结构都依页框号依次存放在vmemmap开始的地方在2.6的内核版本中,

2017-06-13 20:00:36 4275

原创 内存探测

要进行物理内存管理,必须要弄清当前系统的内存容量、地址范围、内存类型等信息。进入保护模式后,内核对内存信息进行了若干加工处理。 结构体memblock的全局实例memblock保存了内存region信息struct memblock { phys_addr_t current_limit;//内存最大容量 struct memblock_type memory; struc

2017-06-13 17:42:35 308

原创 存储器的几种体系结构

SMP:共享存储型多处理机(Shared Memory MulptiProcessors)共享存储型多处理机有三种模型:均匀存储器存取(Uniform-Memory-Access,UMA)模型 非均匀存储器存取(Non uniform-Memory-Access,NUMA)模型 只用高速缓存的存储器结构(Cache-Only MemoryArchitecture,COMA)模型UMA:物

2017-06-13 17:28:50 1820

原创 请求队列request_queue

请求队列request_queue请求队列是由一个大的数据结构request_queue表示的。struct request_queue { struct list_head queue_head; //待处理请求的链表,请求队列中的请求用链表组织在一起 struct request *last_merge; //指向队列中首先可能合并的请求描述符 struc

2017-06-08 22:58:13 6675 2

原创 bio与request(io合并与request)

由“通用块层与bio”我们知道,一次io操作就是一个bio结构,虽然我们的块设备驱动程序完全可以一次处理一个bio请求来执行一次io操作,但这会导致磁盘性能的下降,因为确定bio在磁盘上的起始扇区是很费时的,取而代之的是只要可能,内核就试图把几个相邻扇区的bio合并在一起,这样只用一次寻址。因此引入了一个新的结构request,我们将在后面对该结构进行分析。当我们要读写一些磁盘数据时,实际上创建一个

2017-06-08 21:16:25 2213

原创 通用块层与bio

通用块层与bio通用块层什么是通用块层?通用块层是一个内核组件,它的作用就是处理来自上层对所有块设备发出的io操作。例如,上层文件系统对磁盘上某个文件的读写操作都会转换成相应的io操作然后交给我们的通用块层进行处理。bio结构上面我们提到了很多次io操作的概念,,内核用一个叫做bio的结构体来描述一次块io操作。下面我们来分析一下bio的重要结构。struct bio { sector_t

2017-06-08 18:06:48 2989 1

原创 "分散-聚集DMA"以及"scatterlist"

“分散-聚集DMA”以及”scatterlist”我们知道对磁盘的每个IO操作就是在磁盘与一些内存单元之间相互传送一些相邻扇区的内容。块设备驱动程序只要向磁盘控制器发送一些适当的命令(如前面我们所讲的scsi命令)就可以触发一次数据传送;一旦完成数据的传送,控制器就会发出一个中断通知块设备驱动程序。大多数情况,磁盘控制器直接采用DMA方式进行数据传送。DMADMA全称就是直接内存访问,是一种硬件机制

2017-06-07 15:34:51 3635

原创 为request的每一个bio创建DMA映射

为request的每一个bio创建DMA映射先了解下几个相关的数据结构struct scsi_data_buffer { struct sg_table table; unsigned length; int resid;};struct sg_table { struct scatterlist *sgl; /* the list */ unsign

2017-06-07 11:22:16 1931

原创 scsi磁盘驱动中将request请求转化为scsi命令的过程(sd_prep_fn)

scsi磁盘驱动中将request请求转化为scsi命令的过程该过程主要发生在sd_prep_fn函数中,下面分析该函数static int sd_prep_fn(struct request_queue *q, struct request *rq){ struct scsi_cmnd *SCpnt; struct scsi_device *sdp = q->queuedata

2017-06-07 09:16:16 2087

原创 scsi设备的请求处理函数(request_fn)

每个块设备驱动程序的核心就是它的请求处理函数,即请求队列中对应的request_fn函数struct request_queue { ... request_fn_proc *request_fn; make_request_fn *make_request_fn; prep_rq_fn *prep_rq_fn; ...}下面分析s

2017-06-06 14:59:56 2216

转载 块设备层request plug/unplug机制

分类: LINUX一、基本原理Linux块设备层使用了plug/unplug(蓄流/泄流)的机制来提升IO吞吐量。基本原理为:当IO请求提交时,不知直接提交给底层驱动,而是先将其放入一个队列中(相当于水池),待一定时机或周期后再将该队列中的请求统一下发。将请求放入队列的过程即plug(蓄流)过程,统一下发请求的过程即为unplug(泄流)过程。每个请求在队列中等待的时间不会

2017-06-05 16:26:56 914

原创 IO调度层

void blk_queue_bio(struct request_queue *q, struct bio *bio){ const bool sync = !!(bio->bi_rw & REQ_SYNC); struct blk_plug *plug; int el_ret, rw_flags, where = ELEVATOR_INSERT_SORT; st

2017-06-04 21:25:19 789

原创 向通用块层提交一个bio请求

通用块层对bio请求的处理过程void submit_bio(int rw, struct bio *bio){ bio->bi_rw |= rw; ... generic_make_request(bio);}void generic_make_request(struct bio *bio){ struct bio_list bio_list_on_stac

2017-06-04 20:32:09 649

原创 如何调用内核未导出的函数

如何获取内核未导出的函数地址从Linux内核的2.6某个版本开始,内核引入了导出符号的机制。只有在内核中使用EXPORT_SYMBOL或EXPORT_SYMBOL_GPL导出的符号才能在内核模块中直接使用。然而,内核并没有导出所有的符号。当我们写驱动时,如果想调用一个并未导出的函数时,我们可以使用如下办法:以get_request函数为例,该函数原型为:static struct request *

2017-06-04 17:12:31 2314

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除