curl 是常用的命令行工具，用来请求 Web 服务器。它的名字就是客户端（client）的 URL 工具的意思。如果操作熟练， 完全可以取代部分图形浏览器的功能。不带有任何参数时，curl 就是发出 GET 请求：curl https://www.typeboom.com/ 上面命令向www.typeboom.com发出 GET 请求，服务器返回的内容会在命令行输出。-A参数-A参数指定客户端的用户代理标头，即User-Agent。curl 的默认用户代理字符串是curl/[version]。curl -A 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36' https://www.typeboom.com/ 上方的命令以Chrome浏览器为User-Agent向www.typeboom.com发送了GET请求。curl -A '' https://www.typeboom.com/ 上方的命令以无User-Agent的方式向www.typeboom.com发送了GET请求。（大多数网站所使用的CDN的内置WAF会屏蔽）curl -H 'User-Agent: php/1.0' https://www.typeboom.com/ 上方的命令使用了-H参数直接指定标头，更改了User-Agent并向www.typeboom.com发送了GET请求。-b参数使用-b参数向服务器发送 Cookie。curl -b 'foo=bar' https://www.typeboom.com/ 上方的命令会生成一个标头Cookie: foo=bar，向服务器发送一个名为foo、值为bar的 Cookie。curl -b 'foo1=bar;foo2=bar2' https://www.typeboom.com/ 上方的命令向服务器发送了Cookie: foo=bar和Cookie: foo2=bar2两个Cookie。curl -b cookies.txt https://www.typeboom.com/ 上方的命令读取并向服务器发送了Cookie.txt中的Cookie。-c参数使用-c参数将服务器返回的Cookie保存至某个文件。curl -c cookies.txt https://www.typeboom.com/ 上方的命令将服务器返回的Cookie保存至了Cookie.txt文件中。-d参数使用-d参数向服务器发送POST请求的数据体。curl -d'login=admin＆password=123'-X POST https://www.typeboom.com/admin/ # 或者 curl -d 'login=admin' -d 'password=123' -X POST https://www.typeboom.com/admin/ 上方的命令向服务器发送（POST）了login=admin＆password=123。但是使用-d参数以后，HTTP 请求会自动加上标头Content-Type : application/x-www-form-urlencoded。并且会自动将请求转为 POST 方法，因此可以省略-X POST。和发送Cookie类似，-d参数同样可以读取本地文本文件的数据，向服务器发送。curl -d '@data.txt' https://www.typeboom.com/ 上方的命令向服务器发送（POST）了data.txt文件中的数据。--data-urlencode参数--data-urlencode参数相当于-d参数，但是会自动对发送的内容进行URL（统一资源定位器）编码。curl --data-urlencode 'comment=Cross the Great Wall and go to the world' https://www.typeboom.com/ 上方的命令中，要向服务器发送的命令存在无法直接读取的空格，需要被URL编码。-e参数-e参数用来设置 HTTP 的标头Referer，表示请求的来源。curl -e 'https://ArtemisNet.net/' https://www.typeboom.com/ 上方的命令设置 HTTP 的标头为https://ArtemisNet.net/，向服务器发送了GET请求。这在某些启用了防盗链（HotLink保护）且禁止以空Referer的方式的服务器上很管用。-H参数-H参数可以通过直接添加标头Referer，达到同样效果。curl -H 'Referer: https://ArtemisNet.net/' https://www.typeboom.com/ 上方的命令使用-H参数设置Referer为https://ArtemisNet.net/向服务器发送了GET请求。-F参数-F参数用于向服务器发送二进制文件。curl -F 'file=@photo.webp' https://www.typeboom.com/ 上方的命令会给HTTP请求加上标头Content-Type: multipart/form-data并将文件photo.webp作为file字段发送（POST）至了服务器。-F参数同样也可以指定MINE类型：curl -F 'file=@photo.webp;type=image/png' https://www.typeboom.com/ 上方的命令指定 MIME 类型为image/png，否则 curl 会把 MIME 类型设为application/octet-stream。-F参数同样也可以指定文件名。curl -F 'file=@photo.webp;filename=cat.webp' https://www.typeboom.com/ 上方的命令将文件photo.webp发送（POST）至了服务器，但是服务器收到的文件的名称为cat.webp。-G参数-G参数用于构造URL（统一资源定位器）的查询字符串。curl -G -d 'Workers' https://www.typeboom.com 上方的命令向服务器发送了一个GET请求，请求的URL为：https://www.typeboom.com?=Workers如有数据需要URL编码，可以结合--data--urlencode参数。-H参数可以添加HTTP请求标头。curl -H 'Accept-Language: zh-CN' https://www.typeboom.com/ 上方的命令添加了HTTP请求标头：Accept-Language: zh-CN并向服务器发送了GET请求。curl -H 'Accept-Language: zh-CN' -H 'Secret-Message: FUNCDN-sucks' https://www.typeboom.com/ 上方的命令添加了两个HTTP请求标头：Accept-Language: zh-CN和Secret-Message: FUNCDN-sucks并向服务器发送了GET请求。curl -d '{"login": "admin", "pass": "123"}' -H 'Content-Type: application/json' https://www.typeboom.com/admin 上方的命令添加了HTTP请求标头：Content-Type:application/json并使用-d参数向服务器发送（POST）了json数据。-i参数-i参数将打印出服务器回应的HTTP标头。curl -i https://www.typeboom.com/ 上方的命令将会在终端打印出服务器回应的HTTP标头后，换行再打印出服务器返回的网页源码。-I参数-I参数将向服务器发送HEAD请求并打印出服务器回应的HTTP标头。curl -I https://www.typeboom.com/ 上方的命令将会在终端打印出服务器对HEAD请求的回应。--head参数--head参数等同于-I参数。curl --head https://www.typeboom.com/ 上方的命令同样将会在终端打印出服务器对HEAD请求的回应。-k参数-k参数将会禁用SSL证书校验。curl -k https://www.typeboom.com/ 上方的命令向服务器发送了GET请求，但不检查SSL证书的有效性。-L参数-L参数将允许所发出的HTTP请求跟随服务器的重定向，如果不设置此参数，CURL将默认不跟随重定向。curl -L https://www.typeboom.com/ 上方的命令向服务器发送了GET请求，但允许跟随服务器的重定向。--limit-rate参数--limit-rate参数将限制HTTP请求和回应的带宽。curl --limit-rate 500k https://www.typeboom.com/ 上方的命令向服务器发送了GET请求且限制其所使用的带宽速度为每秒500千字节（KiB）。-o参数-o参数将服务器的回应保存为文件，约等于wget命令。curl -o speedtest-12.7m.png https://img.typeboom.com/pic/speedtest-12.7m.png 上方的命令向服务器发送了GET请求，并将服务器的回应保存为speedtest-12.7m.png。-O参数-O参数将服务器的回应保存为文件，并将URL（统一资源定位器）中的最后一部分作为文件名。curl -O https://img.typeboom.com/pic/speedtest-12.7m.png 上方的命令向服务器发送了GET请求，并将服务器的回应保存为speedtest-12.7m.png。-s参数-s参数将不输出错误和进度信息。curl -s https://www.typeboom.com/ 上方的命令向服务器发送了GET请求，如果不发生错误，将仅输出正常的运行结果。结合-o /dev/null参数，可使CURL不输出任何信息，此参数的意思为：“将文件写入/dev/null”，/dev/null在类Unix系统中是一个特殊的设备文件，它丢弃一切写入其中的数据（但报告写入操作成功）。curl -s -o /dev/null https://www.typeboom.com/ 上方的命令向服务器发送了GET请求，但不会输出任何信息。-u参数-u参数可以设置服务器认证的用户名以及密码。curl -u "bob:12345" https://www.typeboom.com/admin 上方的命令设置用户名为bob，密码为12345，然后将其转为HTTP标头Authorization: Basic Ym9iOjEyMzQ1。-v参数-v参数将会输出CURL与服务器通信的全过程。--trace参数--trace参数将会输出CURL与服务器通信的全过程，并且输出原始的二进制数据。-x参数-x参数可以指定HTTP请求使用的代理。curl -x socks5://admin:123@127.0.0.1:2081 https://www.typeboom.com/ 上方的命令通过位于127.0.0.1:2081的Socks5代理其用户名为admin密码为123，向服务器发出了GET请求。如果不指定代理类型，CURL将默认采用HTTP代理协议。curl -x admin:123@127.0.0.1:2082 https://www.typeboom.com/ 上方的命令通过位于127.0.0.1:2081的HTTP代理其用户名为admin密码为123，向服务器发出了GET请求。-X参数-X参数可以指定HTTP请求方法。curl -X POST https://www.typeboom.com/ 上方的命令向服务器发送了POST请求。
概述CRT显示器学名为“阴极射线显像管”，是一种使用阴极射线管的显示器。主要有五部分组成：电子枪、偏转线圈、荫罩、高压石墨电极和荧光粉涂层及玻璃外壳。显示原理CRT显示器是靠电子束激发屏幕内表面的荧光粉来显示图像的，由于荧光粉被点亮后很快会熄灭，所以电子枪必须循环地不断激发这些点。首先，在荧光屏上涂满了按一定方式紧密排列的红、绿、蓝三种颜色的荧光粉点或荧光粉条，称为荧光粉单元，相邻的红、绿、蓝荧光粉单元各一个为一组，学名称之为像素。每个像素中都拥有红、绿、蓝(R、G、B)三基色。CRT显示器用电子束来进行控制和表现三原色原理。电子枪工作原理是由灯丝加热阴极，阴极发射电子，然后在加速极电场的作用下，经聚焦极聚成很细的电子束，在阳极高压作用下，获得巨大的能量，以极高的速度去轰击荧光粉层。这些电子束轰击的目标就是荧光屏上的三基色。为此，电子枪发射的电子束不是一束，而是三束，它们分别受电脑显卡R、 G、 B三个基色视频信号电压的控制，去轰击各自的荧光粉单元。受到高速电子束的激发，这些荧光粉单元分别发出强弱不同的红、绿、蓝三种光。根据空间混色法(将三个基色光同时照射同一表面相邻很近的三个点上进行混色的方法)产生丰富的色彩，这种方法利用人们眼睛在超过一定距离后分辨力不高的特性，产生与直接混色法相同的效果。用这种方法可以产生不同色彩的像素，而大量的不同色彩的像素可以组成一张漂亮的画面，而不断变换的画面就成为可动的图像。通常实现扫描的方式很多，如直线式扫描，圆形扫描，螺旋扫描等等。其中，直线式扫描又可分为逐行扫描和隔行扫描两种。事实上，在CRT显示系统中两种都有采用。逐行扫描是电子束在屏幕上一行紧接一行从左到右的扫描方式，是比较先进的一种方式。而隔行扫描中，一张图像的扫描不是在一个场周期中完成的，而是由两个场周期完成的。无论是逐行扫描还是隔行扫描，为了完成对整个屏幕的扫描，扫描线并不是完全水平的，而是稍微倾斜的。为此电子束既要作水平方向的运动，又要作垂直方向的运动。前者形成一行的扫描，称为行扫描，后者形成一幅画面的扫描，称为场扫描。然而在扫描的过程中，要保证三支电子束准确击中每一个像素，就要借助于荫罩(Shadow mask)，它的位置大概在荧光屏后面(从荧光屏正面看)约10mm处，厚度约为0.15mm的薄金属障板，它上面有很多小孔或细槽，它们和同一组的荧光粉单元即像素相对应。三支电子束经过小孔或细槽后只能击中同一像素中的对应荧光粉单元，因此能够保证彩色的纯正和正确的会聚偏转线圈可以协助完成非常高速的扫描动作，它可以使显像管内的电子束以一定的顺序，周期性地轰击每个像素，使每个像素都发光，而且只要这个周期足够短，也就是说对某个像素而言电子束的轰击频率足够高，就会呈现一幅完整的图像。至于画面的连续感，则是由场扫描的速度来决定的，场扫描越快，形成的单一图像越多，画面就越流畅。而每秒钟可以进行多少次场扫描通常是衡量画面质量的标准，通常用帧频或场频(单位为Hz，赫兹)来表示，帧频越大，图像越有连续感。24Hz场频是保证对图像活动内容的连续感觉，48Hz场频是保证图像显示没有闪烁的感觉，这两个条件同时满足，才能显示效果良好的图像。LCD 原理液晶液晶起源于1888年，是奥地利植物学家莱尼兹发现的一种特殊的混合物质，此物质在常态下处于固态和液态之间，不仅如此，其还兼具固态物质和液态物质的双重特性，因此就称之为Liquid Crystal（液态的晶体）。1963年时，美国RCA公司的威廉发现液晶受到电场的影响会产生偏转的现象，也发现光线射入到液晶中会产生折射现象。在1968年，也就是威廉发现光会因液晶产生折射后的5年，RCA的Heil震荡器开发部门发表了全球首台利用液晶特性来显示画面的屏幕。在莱尼兹发现液晶物质整整80年后，“液晶”和“显示器”两个专有名词才连结在一起，“液晶显示器（LCD）”才成为行业的专业名词。液晶特性通电时导通，排列变得有秩序，使光线容易通过；不通电时排列混乱，阻止光线通过。让液晶如闸门般地阻隔或让光线穿透。从技术上简单地说，液晶面板包含了两片相当精致的无钠玻璃素材，称为Substrates，中间夹着一层液晶。当光束通过这层液晶时，液晶本身会排排站立或扭转呈不规则状，因而阻隔或使光束顺利通过。大多数液晶都属于有机复合物，由长棒状的分子构成。在自然状态下，这些棒状分子的长轴大致平行。将液晶倒入一个经精良加工的开槽平面，液晶分子会顺着槽排列，所以假如那些槽非常平行，则各分子也是完全平行的。液晶是一种介于晶体状态和液态状态之间的中间物质。它兼有液体和晶体的某些特点，表现出一些独特的性质。工作原理液晶显示器(LCD/Liquid Crystal Display)的显像原理，是将液晶置于两片导电玻璃之间，靠两个电极间电场的驱动，引起液晶分子扭曲向列的电场效应，以控制光源透射或遮蔽功能，在电源关开之间产生明暗变化，从而将影像显示出来。举例TFT LCD显示原理偏光片与偏振光偏光片（Polarizer）全称为偏振光片，可控制特定光束的偏振方向。由美国人Edwin Herbert Land发明。主要作用是可以将不具偏极性的自然光转化为偏振光，透过液晶的转向，来控制光线的穿透与否，进而产生面板明暗之显示效果，利用液晶分子的扭转特性,达到控制光线的通过程度。偏光片的工作原理自然光在通过偏光片时，振动方向与偏光片透过轴垂直的光将被吸收，透过光只剩下振动方向与偏光片透过轴平行的偏振光液晶屏的下偏光片用于将背光源产生的光束转换为偏振光，上偏光片用于解析经液晶电调制后的偏振光，产生明暗对比，从而产生显示画面。液晶显示模组的成像必须依靠偏振光，少了任何一张偏光片，液晶显示模组都不能显示图像。显示原理液晶显示器就是利用偏光板的特性来完成的，利用上下两片栅栏之间互垂直的偏光板之间充满了液晶，在利用电场控制液晶分支的旋转，来改变光的行进方向，如此一来，不同的电场大小，就会形成不同颜色度了。当在不加上电极的时候，当入射的光线经过下面的偏光板(起偏器)时, 会剩下单方向的光波,通过液晶分子时, 由于液晶分子总共旋转了90度, 所以当光波到达上层偏光板时, 光波的极化方向恰好转了90度。下层的偏光板与上层偏光板, 角度也是恰好差异90度。 所以光线便可以顺利的通过，如果光打在红色的滤光片上就显示为红色。效果如图中前两个图所示。（这里的下偏振片是让振动方向平行的光投过，而上偏振片是让振动方向垂直的光透过，在没液晶的情况下，光源透过下偏振片光振动方向都是水平的，当透过上偏振片的时候都被过滤掉了，因为只允许垂直的光透过）当在加上电极后(最大电极)，液晶分子在受到电场的影响下，都站立着，光路没有改变，光就无法通过上偏光板，也就无法显示，如图蓝色滤光片下面的液晶。转自简书
一、SD miniSD microSD SDHC的区分SDSD卡（Secure Digital Memory Card）是一种基于半导体闪存工艺的存储卡。为了满足数码产品不断缩小存储卡体积的要求，SD卡逐渐演变出了Mini SD，Micro SD两种规格。 SD卡背面共有9个引脚，包含4根数据线，支持1bit/4bit两种数据传输宽度，时钟最高频率为25MHZ，故理论最高数据传输速率为12.5MB/S，工作电压2.7~3.6VMiniSD顾名思义，Mini SD卡相比标准SD卡，外形上更加小巧，仅有标准SD卡40％左右的大小。尽管Mini SD卡的外形大小及接口形状与原来的SD卡有所不同，但接口规范保持不变，确保了兼容性。若将Mini SD插入特定的转接卡中，可当作标准SD卡来使用。TransFlash（Micro SD） （主角）Transflash卡，也称T-Flash卡，TF或T卡，最早由SanDisk推出。T卡仅有11mmx15mmx1mm大小，仅相当于标准SD卡的1/4，比Mini SD卡还要小巧。 同样，T卡是与标准SD卡功能也是兼容的，将T卡插入特定的转接卡中，可以当作标准SD卡或Mini SD卡来使用。 2005年7月，SDA协会正式发布了Micro SD标准，该标准与TransFlash卡完全兼容，市场上的TransFlash卡和Micro SD卡可以不加区分的使用。这好比TransFlash是卡的小名，等长大了就取了个Micro SD的学名，不过大家还是叫其TransFlash的多！Mini SD、Micro SD这种小体积SD卡的出现，大大拓展了SD卡的应用范围，这使得SD卡应用在一些小型手机中成为可能。另一方面，Mini SD、Micro SD功能与SD卡功能兼容，只要将其插入特定转接卡中，即可当作标准SD卡来使用，这样，Mini SD、Micro SD便可用于那些使用标准SD卡的数码设备，这加速了Mini SD、Micro SD的市场普及。 miniSD相对于标准SD，增加了2个NC引脚 microSD相对于标准SD，减少了1个VSS引脚 SDHC目前市场上的SD、Mini SD、Micro SD卡遵循的是SD Spec Ver1.0或1.1规范，最大可能容量仅为2GB。2006年，SDA协会发布了SD Spec Ver2.0规范，符合此新规范的SD卡容量可达4GB或更高。 符合2.0规范的SD卡，称为SDHC（SD high capacity）卡。SDHC卡外形维持与SD卡一致，但是文件系统从FAT12、FAT16改为FAT32型；SDHC卡的最大容量可达32GB。除了SDHC卡外,还有Mini SDHC，Micro SDHC类型的卡。 SDHC卡与标准SD卡不再兼容，必须符合SD Spec Ver2.0的设备才能支持SDHC卡，这样的设备都会带有SDHC logo。而支持SDHC卡的设备可以向下兼容标准SD卡。 为了充分发挥SDHC卡的性能，保证兼容性，SDA协会为SDHC卡定义了3个速度等级：2，4，6；其含义是各等级分别可以忍受的写速率至少是2MB/S，4MB/S，6MB/S.速度等级定义中使用的是数据写速率，数据读速率要比数据写速率快。 容量大于2GB的SDHC卡必须带有SDHC符号和速度等级标记符号二、microSD(TF)介绍SD卡和Micro SD卡其实也就大小和引脚不一样，它们的操作其实是一样的，所以网上的SD卡读写代码其实可以直接拿来用。关于SD卡和Micro SD卡的引脚定义和不同可见下两表：我们可以发现Micro SD卡只有8个引脚是因为比SD卡少了一个Vss。当然你也可以买个卡套套在Micro SD卡上，这样一来大小就和SD卡一样大，这时候卡套上的9个引脚就和SD卡一样了，你可以完全当做SD卡来操作。三、micorSD(TF)的驱动上面Micro SD卡的硬件电路就好了，下面我们讲讲Micro SD卡的软件驱动和指令集。SD卡的命令格式如下，6字节共48位，传输时最高位(MSB)先传输：SD卡的command（命令）占6 bit，一般叫CMDx或ACMDx，比如CMD1就是1，CMD13就是13，ACMD41就是41，依此类推。Command Argument（命令参数）占4 byte，并不是所有命令都有参数，没有参数的话该位一般就用置0。最后一个字节由7 bit CRC校验位和1 bit停止位组成。在SPI模式下，CRC是被忽略的，可以都置1或置0.但是发送CMD0时要记得加上CRC，即最后1字节为0x95（因为发送CMD0时还未进入SPI模式，PS：CMD8也要，但一般大家都把发送CMD8省略了）。每次发送完一次命令后，SD卡都会有回应。SD卡的回应有多种格式，1字节的R1，2字节的R2等，不过一般在SPI模式中我们只用到R1，下面介绍R1的格式：关于SD卡SPI和command的发送要注意以下几点：列表项目SD卡的SPI总线，在读入数据时SD卡的SPI是CLK的上升沿输入锁存，输出数据也是在上升沿。向SD卡写入一个CMD或者ACMD指令的过程是这样的： 首先使CS为低电平，SD卡使能；其次在SD卡的Din写入指令；写入指令后还要附加8个填充时钟，是SD卡完成内部操作；之后在SD卡的Dout上接受回应；回应接受完毕使CS为低电平，再附加8个填充时钟。在SD卡的Din没有数据写入时，应使Din保持高电平。关于这一点我可吃透了苦头，本来也记得要保持高电平的，结果不知怎的鬼使神差的置0拉低了。结果程序出现了各种奇怪的貌似偶然的错误，比如连续两次复位会有一次失败，单步调试成功全速运行又会失败。总之在这个过程中我对时序进行各种改变，每次解决一个问题后又会有新的问题出现，多少次动摇了我对MicroSD卡和SD卡的操作是一样的这个看法。因为这个低级的错误耽误了我三四天，看来细心很重要啊！我已经不止一次因为不细心浪费大量时间了，希望大家也引以为戒。好了，现在SD卡的命令和回应清楚了，我们下面讲讲SD卡的复位，初始化和读写方法。复位方法：1.拉高CS，发送至少74个clk周期来使SD卡达到正常工作电压和进行同步2.选低CS，发送CMD0，需要收到回应0x01表示成功进入idle状态3.拉高CS，发送8个时钟复位时序图：初始化：复位成功后，SD卡就进入了SPI模式，接着应该进行初始化。初始化说白了有两种方法：（1）发送CMD1，（2）发送CMD55+ACMD41。我从网上查的资料可以看到这种说法：如果是MMC卡就发CMD1，SD卡则发CMD55+ACMD41。但是关于Micro SD卡要发哪种却讲的不太清楚，网上用这两种方法都有人成功过，但有的都成功不了。我自己也碰到了这种问题，刚开始拿了自己手机上的写着Nokia的2GB的Micro SD卡（应该是杂牌的）初始化了两天也没成功，快要放弃的时候想起来为什么不换张试试呢，于是就找室友借了他的手机内存卡，是2GB的Apacer的Micro SD卡（当然也可能是杂牌的，室友买那卡的地方一般都是卖各种廉价电子产品的，大家都知道是杂牌的），结果一试就成功了。后来我用了令一种方法发现也可以初始化，也就是说两种方法都可以初始化成功。但我的那种怎么就不行呢？难道不是所有Micro SD卡都支持SPI模式。我在网上百度了半天也不能确定是不是所有Micro SD卡都支持SPI模式。但我想，现在Micro SD卡的生产公司很多，而且你也并不能保证你的Micro SD卡不是杂牌的。你并不知道生产厂家进行了那些改变，因为确实有些厂家生产的SD卡精简了一些命令。所以初始化的时候建议两种都试一下，不过我记得SD卡的说明书上推荐使用第二种方法。下面是初始化方法：（1）使用CMD1发送CMD1，收到0x00表示成功时序图如下：（2）使用CMD55+ACMD411.发送CMD55（表示使用ACMDx类命令），收到0x012.发送ACMD41，收到0x00表示成功记住SD卡的初始化速度不能大于400kHz，所以一开始复位和初始化时spi的速率要设置低一点。读单块和多块：SD卡读单块和多块的命令分别为CMD17和CMD18，他们的参数即要读的区域的开始地址。因为考虑到一般SD卡的读写要求地址对齐，所以一般我们都将地址转为块，并以扇区（块）（512Byte）为单位进行读写，比如读扇区0参数就为0，读扇区1参数就为1<<9(即地址512），读扇区2参数就为2<<9(即地址1024），依此类推。 读单块方法：1.发送CMD17，收到0x00表示成功 2.连续读直到读到开始字节0xFE 3.读512个字节 4.读两个CRC字节 读单块时序图：读多块方法：1.发送CMD18读，收到0x00表示成功 2.连续读直到读到开始字节0xFE 3.读512字节 4.读两个CRC字节 5.如果还想读下一扇区，重复2-4 6.发送CMD12来停止读多块操作 写单块和多块：SD卡用CMD24和CMD25来写单块和多块，参数的定义和读操作是一样的。 写单块方法：1.发送CMD24，收到0x00表示成功 2.发送若干时钟 3.发送写单块开始字节0xFE 4.发送512个字节数据 5.发送2字节CRC（可以均为0xff） 6.连续读直到读到XXX00101表示数据写入成功 7.继续读进行忙检测（读到0x00表示SD卡正忙），当读到0xff表示写操作完成 写单块时序图：写多块方法：1.发送CMD25，收到0x00表示成功 2.发送若干时钟 3.发送写多块开始字节0xFC 4.发送512字节数据 5.发送两个CRC（可以均为0xff） 6.连续读直到读到XXX00101表示数据写入成功 7.继续读进行忙检测，直到读到0xFF表示写操作完成 8.如果想读下一扇区重复2-7步骤 9.发送写多块停止字节0xFD来停止写操作 10.进行忙检测直到读到0xFF 转自https://is.gd/csdn_
随着IBM PC机的发展，键盘也分为XT, AT, PS/2键盘以至于后来的USB键盘. PC系列机使用的键盘有83键、84键、101键、102键和104键等多种。XT和AT机的标准键盘分别为83键和84键，而286机以上微机的键盘则 普遍使用101键、102键或104键。83键键盘是最早使用的一种PC机键盘，其键号与扫描码是一致的。这个扫描码被直接发送到主机箱并转换为 ASCII码；随着高档PC机的出现，键盘功能和按键数目得到了扩充，键盘排列也发生了变化，产生的扫描码与83键键盘的扫描码不同。为了保持PC系列微 机的向上兼容性，需将84/101/102/104键键盘的扫描码转换为83键键盘的扫描码，一般将前者叫作行列位置扫描码，而将后者称为系统扫描码。显 然，对于83键键盘，这两种扫描码是相同的。键盘是由一组排列成矩阵方式的按键开关组成，通常有编码键盘和非编码键盘两种类型，IBM系列个人微型计算机的键盘属于非编码类型。微机键盘主要由单片 机、译码器和键开关矩阵三大部分组成。其中单片机采用了INTEL8048单片微处理器控制，这是一个40引脚的芯片，内部集成了8位 CPU、1024×8位的ROM、64×8位的RAM、8位的定时器／计数器等器件。由于键盘排列成矩阵格式，被按键的识别和行列位置扫描码的产生，是由 键盘内部的单片机通过译码器来实现的。单片机在周期性扫描行、列的同时，读回扫描信号线结果，判断是否有键按下，并计算按键的位置以获得扫描码。当有键按 下时，键盘分两次将位置扫描码发送到键盘接口；按下一次，叫接通扫描码；释放时再发一次，叫断开扫描码。因此可以用硬件或软件的方法对键盘的行、列分别进 行扫视，去查找按下的键，输出扫描位置码，通过查表转换为ASCII码返回。键盘是与主机箱分开的一个独立装置，通过一根5芯电缆与主机箱连接，系统主板上的键盘接口按照键盘代码串行传送的应答约定，接受键盘发送来的扫描码；键盘 在扫描过程中，7位计数器循环计数。当高5位(D6一D2)状态为全“0”时，经译码器在O列线上输出一个“0”,其余均为“1”；而计数器的低二位 (D1D0)通过4选1多路选择器控制0—3行的扫描。计数器计一个数则扫描一行，计4个数全部行线扫描一遍，同时由计数器内部向D2进位，使另一列线1 变低，行线再扫描一遍。只要没有键按下，多路选择器就一直输出高电平，则时钟一直使计数器循环计数，对键盘轮番扫描。当有一个键被按下时，若扫描到该键所 在的行和列时，多路选择器就会输出一个低电平，去封锁时钟门，使计数器停止计数。这时计数器输出的数据就是被按键的位置码(即扫描码)。8048利用程序 读取这个键码后，在最高位添上一个“O”，组成一个字节的数据，然后从P22引脚以串行方式输出。在8048检测到键按下后，还要继续对键盘扫描检测，以 发现该键是否释放。当检测到释放时，8048在刚才读出的7位位置码的前面(最高位)加上一个“1”，作为“释放扫描码”，也从 P22引脚串行送出去，以便和“按下扫描码”相区别。送出“释放扫描码”的目的是为识别组合键和上、下档键提供条件。同时，主机还向键盘发送控制信号，主机CPU响应键盘中断请求时，通过外围接口芯片8255A一5的PA口读取键盘扫描码并进行相应转换处理和暂存；通过PB口的PB6和PB7来控制键盘接口工作。从用途上看，键盘可分为台式机键盘、笔记本电脑键盘和工控机键盘三大类；其中台式机键盘从按键结构上又可分为两类，即机械键盘和电容键盘（又称有触点键盘 和无触点键盘）。机械键盘存在着开关容易损坏、易污染、易老化的缺点，现已基本淘汰。电容键盘在可靠性上比前者有质的飞跃，使用寿命较长，目前大多为电容 键盘。早期的键盘是由美国IBM公司推出的，当时采用的计算机键盘为83键键盘。不久IBM又推出了84键的键盘设计标准，将键盘分为三个区，即功能区、打字键 区及负责光标控制和编辑的副键盘区，这种键盘主要区域的划分标准一直沿用至今。随着微软Windows视窗操作系统的广泛应用，IBM公司于1986年首 次推出了101键的标准键盘，除添加了F11、F12两个功能键之外，还在键盘的中部多加了一组专用的光标控制和编辑的键，使键盘功能得到了进一步扩充， 成为当时业界的标准键盘。后来，为与微软的Win95操作系统相配合，IBM又推出了104键键盘，新增了3个功能键（亦称Windows快捷键或热键 ），使以前需要打开好几个窗口才能完成的某些功能，通过快捷键的设定直接启动菜单完成，而不必再点击鼠标，这样就使计算机的 操作更加便易。目前，这种104键的键盘（亦称Win95键盘）的设计已成为业界和市场上最为普遍、最为流行的一种标准，业界通称为标准键盘。实际上，所 谓的标准键盘并没有标准，只因其应用较为广泛而被业界通称为标准键盘。由于软件的不断升级更新，为配合软件的需要，所谓的标准键盘的键数也在随之扩增，并 因其又被业界所通常采纳而又被业界通称为标准键盘。但是，无论是机械键盘或者电容键盘，还是从早期的83键键盘发展到目前通称的标准键盘104键键盘，其应用都是主要依赖于硬件CPU和软件操作系统。以下就键盘的构造及工作原理等问题进行介绍。(一)键盘构造及工作原理PS/2设备履行一种双向同步串行协议。换句话说，每次数据线上发送一位数据并且每在时钟线上发一个脉冲就被读入。设备可以发送数据到主机，而主机也可以发送数据到设备，但主机总是在总线上有优先权，它可以在任何时候抑制来自设备的通信，只需把时钟线电平拉低即可。 键盘的内部结构主要包括控制电路板、按键、底板和面板等。电路板是整个键盘的控制核心，位于键盘的内部，主要担任按键扫描识别、编码和传输接口工作；它将各个键所表示的数字或字母转换成计算机可以识别的信号，是用户和计算机之间主要的沟通者之一。键盘主要由键开关矩阵、单片机和译码器三大部分组成。键开关矩阵即键盘按键由一组排列成矩阵方式的按键开关组成，所输入的信号由按键所在的位置决定。单片 机即键盘内部采用的Intel 8048单片机微处理器，这是一个40引脚的芯片，内部集成了8位CPU、1024×8位的ROM、64×8位的RAM以 及8位的定时器／计数器等。译码器即信号编码转译装置，把键盘的字符信号通过编码翻译转换成相应的二进制码。由于键盘排列成矩阵格式，被按键的识别和行列 位置扫描码的产生，是由键盘内部的单片机通过译码器来实现的。根据键盘向主机送入的二进制代码类型，可把键盘分为编码键盘和非编码键盘两种。IBM PC机的键盘属于非编码键盘，其特点是不直接提供所按键的编码信息，而是用较为简单的硬件和一套专用程序来识别所按键的位置，并提供与所按键相对应的中间 代码，然后再把中间代码转换成要对应的编码。这样，非编码键盘就为系统软件在定义键盘的某些操作功能上提供了更大的灵活性。计算机键盘通常采用行列扫描法来确定按下键所在的行列位置。所谓行列扫描法是指，把键盘按键排列成n行×m列的n*m行列点阵，把行、列线分别连接到两个 并行接口双向传送的连接线上，点阵上的键一旦被按动，该键所在的行列点阵信号就被认为已接通。按键所排列成的矩阵，需要用硬件或软件的方法轮转顺序地对其 行、列分别进行扫描，以查询和确认是否有键按动。如有键按动，键盘就会向主机发送被按键所在的行列点阵的位置编码，称为键扫描码。单片机通过周期性扫描 行、列线，读回扫描信号结果，判断是否有键按下，并计算按键的位置以获得扫描码。键被按下时，单片机分两次将位置扫描码发送到键盘接口：按下一次，叫接通 扫描码；按完释放一次，叫断开扫描码。这样，通过硬件或软件的方法对键盘分别进行行、列扫视，就可以确定按下键所在位置，获得并输出扫描位置码，然后转换 为ASCII码，经过键盘I/O电路送入主机，并由显示器显示出来。键盘要增加键数是很容易的，任何矩阵键盘通过增加键盘的行或列便可实现增加按键数。如64 键的键盘排列成8行×8列的行列点阵，128键的键盘排列成8行×16列的行列点阵，256键的键盘排列成16行×16列的行列点阵，这在1992年7月 出版的《微处理机为基础之设计》出版物上已作介绍(此对比文献在2001年12月13日已递交)。因此，键盘结构采用矩阵式早已是公有技术。(二)键盘的按键增加及功能改进随着计算机CPU（硬件）和Windows操作系统（软件）的不断升级换代，计算机的发展进入到了包括多媒体在内的高速多功能时代。与此相适应，计算机键 盘也出现了一些新的变化，主要表现在键盘键数的增加及功能的整合。美国苹果(Apple)公司早在1992年就曾推出过设有调整音量按键的键盘。时下流行 的多媒体键盘，也叫多功能键盘，其特征是增加了一些快捷键（或功能键），通过设定主板BIOS或软件设定，使这些新增的键可以实现开关电脑、休眠启动、 CD播放、音量调整、一键上网等特殊功能。此外还出现了一些多功能集成的键盘，如将扫描仪、录音设备或手写板、鼠标等整合为一体的键盘，以及带有文字编辑 或指纹识别功能的智能键盘等。如前所述，IBM定义的101键键盘与微软(Microsoft)所定义的三键共同形成的104 键Win95键盘一般被称作标准键盘，那么标准键盘的104键之外如何增加按键扩充功能呢？从目前键盘发展情况看，可以有多种方法。单就增加键盘按键的设 定技术看，一般来讲，按键的增加取决于三个方面的因素：一是CPU能识别，二是操作系统能响应，三是键盘内部电路结构能安排。从前面的介绍可知，CPU和 操作系统这两个因素是计算机必备的现成技术，不成问题。这样，增加键盘按键的关键就在于键盘的内部结构。以下两种方法可以直接简便地增加键盘按键。目前PC机键盘按键一直沿用IBM的行列矩阵方式布局排列，称为扫描矩阵，其内部电路结构的核心是8048（包括其后续升级系列）单片机微处理器。根据单 片机微处理器特定的I/O（即Input/Output输入/输出）电路，IBM将键盘按键的行列矩阵定义为8行×16列＝128键，而现行的标准键盘只 使用了其中的104键，故尚有128-104＝24键的阵点闲余，尚未定义。因此，增加按键的方法之一是，直接在这尚未定义的24个闲余按键阵点中继续定 义新键以扩增新的功能键。方法之二是，通过改变单片机微处理器I/O电路的配线方式，可以把IBM的原8行×16列扫描矩阵变为（8+n）行×16列，如 （8+1）行×16列＝144键等，这样就会在128键之外获得新增加的一行16个键位，再根据需要为其定义功能。以上两种方法都可以达到增加104键的 标准键盘的按键数的目的。简而言之，第一种方法是在原扫描矩阵8行×16列的行列点阵中尚未利用的24个点上,根据需要可任意增加1至24个新键；第二种 方法是在单片机微处理器原扫描矩阵8行×16列基础上再增加一行，变为9行×16列扫描矩阵，再根据需要任意增加新键，并不会带来单片机微处理器本身原有 功能的更新。如IBM 的83键盘发展到原来的标准键盘101键，其要增加的键数只要通过增加键盘的行或列，并在增加的行列阵点上进行定义便可实现；而原来的101键的标准键盘 后发展到目前的104键的标准键盘，其增加的3个键数可以不增加键盘的行和列，只要在原扫描矩阵中尚未定义的点上直接定义就可以。无论是第一种方法还是第 二种方法，都已经属于公有技术领域的技术。什么是键盘的键位冲突？简单的说，也就是当你同时按下键盘上的几个键的时候，这几个键不能同时反映出来，这就叫做键盘的键位冲突。例如说，你能想象当你按下Ctrl－Alt－Del时，系统只能接收到前两个键，而死活不承认你按了Del键吗？当然，现实中是不会有这样的键盘的，按不下Ctrl－Alt－Del的键盘根本就没法出厂，但其他一些常见的键位冲突就不稀奇了。例如，经常有一些键盘不能同时对例如A-S-空格这样的按键组合作出反应，这样在FPS游戏中，使用者就会大为吃亏。对于键位冲突问题，电脑用户中有两种完全不同的态度，绝大多数人根本意识不到键位冲突问题的存在，直到遇到冲突的时候才叫苦不迭，并且大呼“为什么他就能 做这个动作？”；而另一部分人，特别是一些游戏高手，又在孜孜不倦的寻找“没有键位冲突的键盘”。这两种人都是对键位冲突的原因认识不清楚的。键位冲突的直接起因，是键盘的非编码结构。在2月号的专题中，我们提到过现在的键盘几乎都是非编码的薄膜接触式键盘，那么什么是非编码键盘呢？在专题里我们没有详细的解释，下面我们就来详细说明一下非编码键盘的原理与结构。传统的键盘，是编码式键盘，它的每个键按下时都会产生唯一的按键编码，并且通过专有的一组导线传输到键盘接口电路，由于其线路和编码的唯一性，这种键盘是不存在键位冲突的问题的，但是编码键盘结构复杂，现在已经很少使用了。而现代的薄膜接触式键盘，任何一个按键都有上下两层薄膜的触点，我们将它拆开来仔细看一看（如图），就会发现在任何一层薄膜上，导线数都远少于按键数，而 且每一条导线都同时连通多个按键的触点，而且，上层和下层的任何两条导线都最多只在一个按键上重合。也就是说，上层的1号导线可能会同时经过1、2、3、 4、5……等按键，而下层的1号导线可能同时经过1、Q、A、Z……等按键，且两条导线只在1键上重合。什么是键盘的键位冲突？简单的说，也就是当你同时按下键盘上的几个键的时候，这几个键不能同时反映出来，这就叫做键盘的键位冲突。例如说，你能想象当你按下Ctrl－Alt－Del时，系统只能接收到前两个键，而死活不承认你按了Del键吗？当然，现实中是不会有这样的键盘的，按不下Ctrl－Alt－Del的键盘根本就没法出厂，但其他一些常见的键位冲突就不稀奇了。例如，经常有一些键盘不能同时对例如A-S-空格这样的按键组合作出反应，这样在FPS游戏中，使用者就会大为吃亏。对于键位冲突问题，电脑用户中有两种完全不同的态度，绝大多数人根本意识不到键位冲突问题的存在，直到遇到冲突的时候才叫苦不迭，并且大呼“为什么他就能 做这个动作？”；而另一部分人，特别是一些游戏高手，又在孜孜不倦的寻找“没有键位冲突的键盘”。这两种人都是对键位冲突的原因认识不清楚的。键位冲突的直接起因，是键盘的非编码结构。在2月号的专题中，我们提到过现在的键盘几乎都是非编码的薄膜接触式键盘，那么什么是非编码键盘呢？在专题里我们没有详细的解释，下面我们就来详细说明一下非编码键盘的原理与结构。传统的键盘，是编码式键盘，它的每个键按下时都会产生唯一的按键编码，并且通过专有的一组导线传输到键盘接口电路，由于其线路和编码的唯一性，这种键盘是不存在键位冲突的问题的，但是编码键盘结构复杂，现在已经很少使用了。而现代的薄膜接触式键盘，任何一个按键都有上下两层薄膜的触点，我们将它拆开来仔细看一看（如图），就会发现在任何一层薄膜上，导线数都远少于按键数，而 且每一条导线都同时连通多个按键的触点，而且，上层和下层的任何两条导线都最多只在一个按键上重合。也就是说，上层的1号导线可能会同时经过1、2、3、 4、5……等按键，而下层的1号导线可能同时经过1、Q、A、Z……等按键，且两条导线只在1键上重合。这样，根据上层薄膜和下层薄膜所经过的按键，就可以排出一个类似下面的表格：在非编码键盘的接口控制电路中，就存储着这样一张表格，当按下某个按键，例如“Q”时，那么在这一点上，上下两个触点就会连通，反映到接口电路中，就会检 测到上层导线1与下层导线2被连通了。相对应在表中一查，就会知道，被按下的是字母“Q”，然后通过接口输出其ASCII码。与老式的编码式键盘相比，非编码键盘的结构要简单许多，省略了复杂的编码电路和蜘蛛网似的走线，而且更重要的是，由于非编码式键盘将按键结构和输出键码分 离，所以当需要制造不同键位排列的键盘时，不需要重新设计键盘线路，而只要将控制电路中的键位排列表格重新刷新就可以了。例如在德文键盘上，子母“Y”和 “Z”的位置是互调的，那么如果要把一条英文键盘生产线改造成德文键盘生产线，什么都不用改变，只须在控制芯片中刷进一个新的排列表，将“上层导线1－下 层导线4”的位置写作“Y”，“Z”字也作同样处理就行了，显然比重新布线要简单了很多。这也就是为什么非编码式键盘大行其道的原因。但是非编码式键盘带来的就是“键位冲突”的问题。以上面的按键排列表为例，当按下一个按键时，键盘肯定会正常识别的；当按下两个按键时，例如同时按下 “Q”与“D”，此时上层导线1与下层导线2连通，而上层导线3与下层导线3连通，系统完全可以正常识别；或者同时按下“Q”与“E”，此时，上层导线 1、下层导线2、上层导线3同时连通，系统同样可以正常识别出是按下了这三个按键。但在同时按下3个或3个以上按键时，情况就复杂了。在一种情况下，例如同时按下“Q”、“D”、“B”时，此时，从表中我们可以看出，上层导线1－下层导线2、上层导线3－下层导线3、上层导线5－下层导线4都分别连通，此时系统完全可以正常识别出按下了这三个按键。但当按下的第三个按键不是“B”，而是“E”呢？此时，我们可以发现，由于第三组连通的导线变成了上层导线3－下层导线2，所以，此时反映到接口控制芯片的信号是：上层导线1－下层导线2－上层导线3－下层导线3统统被连通到了一起。但是，问题就在于，除了按下的第三个按键是“E”以外，如果按下的第三个键是用来连通上层导线1和下层导线3的“A”，也会有同样的信号组合？事实上， “Q”、“E”、“A”、“B”四个按键中按下任何三个都会有同样的信号组合，那么此时接口电路怎么判断呢？究竟是按下了哪三个按键或者是同时把四个按键 都按下了呢？这个时候，大多数键盘选择的方式，就是按照一个固定的规则输出固定的按键组合代码，对于其他可能的组合方式统统予以忽略，换句话说，在上面的键盘中，可能 无论你怎么按这四个按键，它可能永远只会输出“Q”－“E”－“D”的组合，尽管可能你按下的实际是“Q”－“A”－“D”（这里只是一个假设，实际上为 了避免误码，大多数键盘根本只输出两个按键而已）。于是，“键位冲突”就出现了。由于非编码键盘的固有结构，“键位冲突”是不可避免的。于是就需要键盘的设计者绞尽脑汁修改键盘的线路排列和待查表格，尽量使可能会有的常用组合按键避开 冲突键位——尽管要做到所有的按键都不发生冲突是不可能的，但你总不能让Ctrl－Alt－Del相互冲突吧？那这样的键盘还怎么用？还有如果四个方向键 相互冲突，那赛车类的游戏还怎么玩？不过，由于市场上的游戏实在太多，每个游戏都可能会有自己常用的按键组合，甚至每个人都有自己的习惯按键，键盘的设计者当然不可能面面俱到，有经验的设计 师可能会考虑得多一些，至少对最常见的游戏和最常见的按键设置能够保证不出现问题，但要考虑到所有情况当然是不可能的。所以，当你购买键盘的时候，绝对不要忽略“键位冲突”的问题，一定要把键盘装到电脑上，试一试自己常玩的游戏是否能够正常使用（只有实际试用才能试出键位 冲突问题，由于它与键位表相关，所以看外表是看不出来的）。同时，一些游戏高手朋友也不要白费心机去寻找什么“没有键位冲突的键盘”了，只要它依然是非编 码键盘，那么键位冲突就是不可避免的，只要它的键位冲突不对你所玩的游戏构成影响，这就足够了。PS/2协议分析The PS/2 mouse and keyboard implement a bidirectional synchronous serial protocol.PS/2鼠标和键盘执行一个双向同步串行协议。The bus is "idle" when both lines are high (open-collector).总线空闲时，两条线都是高电平(集电极开路)。This is the only state where the keyboard/mouse is allowed begin transmitting data.在这种状态下，键盘/鼠标才允许开始传输数据。The host has ultimate control over the bus and may inhibit communication at any time by pulling the Clock line low.主机对总线有最高的控制权，在任何时候通过将时钟线拉低就可以禁止通信。The device always generates the clock signal.时钟信号总是由设备端生成的。If the host wants to send data, it must first inhibit communication from the device by pulling Clock low.如果主机想发送数据，它必须先将时钟拉低来禁止来自设备端的通信。The host then pulls Data low and releases Clock.然后主机再拉低数据线，释放时钟。 注释:释放时钟，就是再恢复时钟为高This is the "Request-to-Send" state and signals the device to start generating clock pulses.这就是"请求发送(Request-to-Send)"状态，提示 设备端 开始生成时钟信号。Summary: Bus StatesData = high, Clock = high: Idle state.Data = high, Clock = low: Communication Inhibited.Data = low, Clock = high: Host Request-to-Send总结:总线状态 数据 0 1 0 ---------通信禁止----------- 时钟 1 主机要求发送 总线空闲 The clock and data pins are bidirectional, open-collectorsignals that are pulled to 5 V by pullup resistors in the keyboard.时钟和数据 引脚时 双向 集电极开路的信号，可以被键盘内部的上拉电阻 拉高到5VData sent from the device to the host is read on the falling edge of the clock signal; data sent from the host to the device is read on the rising edge.从设备发送给主机的数据时在时钟信号的下降沿读取的;从主机发给设备的数据是在上升沿读取的。The clock frequency must be in the range 10 - 16.7 kHz. This means clock must be high for 30 - 50 microseconds and low for 30 - 50 microseconds..时钟频率必须在10-16.7KHz之间。这意味着时钟必须是 高电平持续30～50毫秒，低电平持续30～50毫秒。If you're designing a keyboard, mouse, or host emulator, you should modify/sample the Data line in the middle of each cell. I.e. 15 - 25 microseconds after the appropriate clock transition.如果你设计一个键盘 鼠标 或者 主机模拟器，你必须 在每个单元的中间时刻 （也就是,在时钟跳变之后的15～25毫秒后） 修改/取样数据线.Again, the keyboard/mouse always generates the clock signal, but the host always has ultimate control over communication.重复一遍，键盘/鼠标 总是 生成时钟信号， 而 主机 控制着整个通信过程。Timing is absolutely crucial. Every time quantity I give in this article must be followed exactly.时序是非常重要的。在本文中给出的时间数必须严格遵循。设备发送数据到主机The Data and Clock lines are both open collector.数据和时钟线都是集电极开路的。A resistor is connected between each line and +5V, so the idle state of the bus is high.在+5V 和每根线 之间连接着一个电阻，所以 总线的空闲状态 是 高电平。When the keyboard or mouse wants to send information, it first checks the Clock line to make sure it's at a high logic level.当键盘或者鼠标想发送数据时，它首先必须检查时钟线 ，确认它处于高电平。If it's not, the host is inhibiting communication and the device must buffer any to-be-sent data until the host releases Clock.如果不是，主机禁止通信，设备必须缓冲任何要发送的数据，直到主机释放时钟。The Clock line must be continuously high for at least 50 microseconds before the device can begin to transmit its data.在设备开始传输数据之前，时钟线 必须持续为 高电平的 时间 必须 至少50msThe keyboard/mouse writes a bit on the Data line when Clock is high, and it is read by the host when Clock is low.当时钟为高电平时，键盘/鼠标写一个bit到数据线上；当时钟为低电平时，主机从数据线上读取这个bit 。The Data line changes state when Clock is high and that data is valid when Clock is low.当时钟位高时，数据线 改变状态；当时钟位低时，（数据线上的)数据是有效的。The clock frequency is 10-16.7 kHz.时钟频率是10-16.7KHzThe time from the rising edge of a clock pulse to a Data transition must be at least 5 microseconds.从时钟脉冲的上升沿到数据跳变 的时间必须至少 5msThe time from a data transition to the falling edge of a clock pulse must be at least 5 microseconds and no greater than 25 microseconds.从数据跳变 到时钟脉冲的下降沿 必须 至少5ms,且不超过25msThe host may inhibit communication at any time by pulling the Clock line low for at least 100 microseconds.主机可在任何时间禁止通信，只需要将时钟线下拉位低电平超过100ms即可If a transmission is inhibited before the 11th clock pulse, the device must abort the current transmission and prepare to retransmit the current "chunk" of data when host releases Clock.如果在第11个脉冲时禁止传输，设备必须中止当前的传输，准备重新传输当前的数据"chunk（块)"当主机释放时钟时A "chunk" of data could be a make code, break code, device ID, mouse movement packet, etc.一个数据块可能时 通码，断码，设备ID，鼠标移动包 等等。For example, if a keyboard is interrupted while sending the second byte of a two-byte break code, it will need to retransmit both bytes of that break code, not just the one that was interrupted.举个例子，如果当发送 一个两字节断码的 第2个字节时，键盘被中断，它将需要重新发送此断码的两个字节，而不仅仅时被中断掉的那个字节。If the host pulls clock low before the first high-to-low clock transition, or after the falling edge of the last clock pulse, the keyboard/mouse does not need to retransmit any data.如果在第一个 高->低 时钟跳变 时，（或者在 最后一个时钟脉冲的下降沿 之后）主机将时钟拉低，键盘/鼠标 不必重新传输任何数据。However, if new data is created that needs to be transmitted, it will have to be buffered until the host releases Clock.但是，如果新产生的数据需要传输，它必须将数据缓冲，知道主机释放时钟。Keyboards have a 16-byte buffer for this purpose. If more than 16 bytes worth of keystrokes occur, further keystrokes will be ignored until there's room in the buffer.键盘有一个16字节的缓冲区。如果有超过16个字节的击键存在，更多的击键将被忽略。直到缓冲区有空地。Mice only store the most current movement packet for transmission.鼠标只能缓冲最近的一个要传输的（移动)数据包。时间参数 最大值/最小值 T1数据跳变到时钟的下降沿 5/25 us T2时钟的上升沿 到 数据跳变 5/T4 - 5 us T3时钟inactive 30-50 us T4时钟active 30-50 us T5 >0/50 us Time to auxiliary device inhibit after clock 11 to ensure the auxiliary device does not start another transmissionThe auxiliary device checks the 'clock' line. If the line is inactive, output from the device is not allowed.辅助设备(指 键盘) 检查 时钟线 ，如果时低电平，禁止发送数据The auxiliary device checks the 'data' line. If the line is inactive, the controller receives data from the system.设备检查数据线，如果是 低电平，那么控制器从系统接收数据The auxiliary device checks the 'clock' line during the transmission at intervals not exceeding 100 microseconds. If the device finds the system holding the 'clock' line inactive, the transmission is terminated. The system can terminate transmission anytime during the first 10 clock cycles.设备在传输过程中 检查 时钟 线 间隔不超过100us。 如果设备发现 主机系统 将电平拉低，就终止传输。 在传输过程的前10个时钟周期的任何时候，主机系统可以中止传输。A final check for terminated transmission is performed at least 5 microseconds after the 10th clock.终止传输的最后一个检查 要持续至少5usThe system can hold the 'clock' signal inactive to inhibit the next transmission.系统拉低时钟线，将禁止下一次传输The system can set the 'data' line inactive if it has a byte to transmit to the device. The 'data' line is set inactive when the start bit (always 0) is placed on the 'data' line.系统如果有一个字节要传输给设备，可以拉低数据线。当开始位（总是0）放置到数据线时，数据线被拉低。The system raises the 'clock' line to allow the next transmission.系统拉高时钟将允许下一次传输Host-to-Device主机到设备的通信First of all, the PS/2 device always generates the clock signal.首先，PS/2设备总是产生时钟信号If the host wants to send data, it must first put the Clock and Data lines in a "Request-to-send" state as follows:如果主机想发送数据，它必须先将时钟线和数据线设置成"Request-to-send"状态:1) Inhibit communication by pulling Clock low for at least 100 microseconds.拉低时钟线至少100us来禁止通信2) Apply "Request-to-send" by pulling Data low, then release Clock.拉低数据线，请求 "Request-to-send", 然后释放时钟 .The device should check for this state at intervals not to exceed 10 milliseconds.设备应该在不超过10ms(注意，是毫秒)的间隔内就要检查一次这个状态。When the device detects this state, it will begin generating Clock signals and clock in eight data bits and one stop bit.当设备检测到这个状态，它将开始产生时钟信号，The host changes the Data line only when the Clock line is low, and data is read by the device when Clock is high.只有当时钟线 为低的时候，主机才可以改变数据线（也就是将数据写入到数据线）。数据将在时钟为高电平的时候 被 设备读取。After the stop bit is received, the device will acknowledge the received byte by bringing the Data line low and generating one last clock pulse.在收到停止位之后，设备将通过拉低数据线，生成最后一个时钟脉冲 来 应答收到的字节If the host does not release the Data line after the 11th clock pulse, the device will continue to generate clock pulses until the the Data line is released (the device will then generate an error.)在第11个时钟脉冲之后，如果主机并没有释放数据线，设备将继续产生时钟脉冲，直到数据线被释放（然后 设备将产生一个错误）The host may abort transmission at time before the 11th clock pulse (acknowledge bit) by holding Clock low for at least 100 microseconds.在第11个脉冲之前（回应位），主机可以随时中止传输，只要拉低时钟持续100us即可时间参数 最大值/最小值 T7 时钟低电平 30-50 us T8 时钟高电平 30-50 us T9 30-50 us T9 == Time from inactive to active CLK transition, used to time when the auxiliary device samples DATAFreeScale(Moto)提供的时序图主机到键盘的数据传输1.主机 通过拉低 时钟线 来 启动一个主机到键盘的数据传输。大约35us后，主机拉低数据线。这个事件序列 就是 通知 键盘，主机要传输一个命令了。在数据信号的下降沿大约 125us 后 时钟信号释放，就被键盘内部的上拉电阻拉为高电平 。在时钟信号的上升沿 约 1ms ，数据传输开始。这个期间，数据线保持低电平。键盘拉低时钟线，clocking in the low data line. 这个就做传输的起始位。键盘用时钟驱动 8个数据位从主机传输到自己这边。 这个时钟有50％的占空比(duty cycle).高电平和低电平的时间都在30~50us之间。主机在每个周期的低电平的时候改变数据线上的数据。在每个时钟的上升沿5～25us之后键盘 开始从数据线上取样，取出主机发来的数据。4.数据位之后是一个奇偶校验位（采用奇校验）5.最后是停止位6.如果键盘读到一个高电平的停止位，键盘就在 取样停止位的那个时钟的下降沿 之后的低电平期间 拉低数据线。这个行为叫做 键盘给主机的应答信号。键盘拉高时钟之后，也拉高数据线。7.在收到一个字节后，键盘对接收的数据执行一个奇偶校验。如果奇偶校验错误，或者接收的数据无法识别为有效的命令，那么键盘请求重新发送（发送0xFE给主机)键盘发送数据前，首先必须让时钟 和数据线都在键盘内部的上拉电阻作用下 拉成高电平。然后键盘拉低数据线，5－25us之后，键盘拉低时钟线。在时钟的下降沿，开始传输起始位The falling edge of the clock line clocks in the transfer’s startbit.键盘用时钟驱动 8个数据位到主机。 这个时钟有50％的占空比(duty cycle).高电平和低电平的时间都在30~50us之间。键盘在每个周期的高电平的时候改变数据线上的数据。这个改变出现在时钟的上升沿的5us后 和 下降沿的5us前。键盘的数据在时钟的下降沿被锁存进主机。3.数据位之后是一个奇校验位4.最后是停止位。在时钟的下降沿 0～50us之间 主机拉低时钟 来锁存停止位。这就告诉键盘主机现在忙，不能在接收 其他的键盘传输数据。在处理完接收的数据，准备好接收下一个数据之前，主机释放时钟。6.在键盘传输数据到主机的过程中，主机任何时候都可以中断这个传输，发送一个命令到键盘。主机拉低时钟和数据线 即可中止传输。所以，键盘在时钟为 低电平的时候必须取样数据线。（无论什么时候输出高数据位的时候）。在产生时钟的上升沿时，必须读取时钟。在任何时候发现这两个条件不满足，就拉高时钟和数据线，放弃这次传输，并准备从 主机接收命令。Moto 香港公司的 Derek Lau当时钟 高电平是，发送给主机的数据被主机读取。在空闲状态，时钟和数据线都被拉为高电平。主机 拉低 时钟最少100ms（？还是us）开始发送数据给键盘：1.主机等待，直到没有外部设备传输被处理2.主机 拉低时钟3.主机拉低数据作为开始位4 .主机释放时钟5.设备拉低时钟6.主机发送数据7.设备释放时钟，读取数据8.设备检查时钟线，如果时钟为低，中止传输9.重复 5－7步，发送 数据1－到数据0，以及 奇校验位设备拉低时钟主机释放数据12.设备时钟时钟13.设备读取数据线，想得到停止位，如果数据线为低（不是停止位），产生错误14.设备拉低 时钟和数据线15.设备释放 时钟和数据线从设备发送到主机的数据，在时钟的下降沿被读取。在发送数据前，设备检查通过检测时钟信号为高来得知 主机是否贮备好：1.键盘（设备）等待时钟为高（约50ms?us)2.如果数据为 低，终止3.键盘 发送数据4.键盘拉低时钟为低5.键盘释放时钟为高6.键盘 读取时钟线，如果时钟为低，中止传输7.重复 4－6步，传输数据0－数据7，奇校验位和停止位8.键盘释放时钟为高转自https://is.gd/gAEf2Emarkdown制表真麻烦，最后预览和实际不一样，只能截图伺候
内存内存主要用来存储系统和应用程序的指令、数据、缓存等。内存映射通常所说的内存容量，比如笔记本电脑的8GB内存，其实指的是物理内存。物理内存也称为主存，大多数计算机用的主存都是动态随机访问内存（DRAM）。只有内核才可以直接访问物理内存。Linux 内核给每个进程都提供了一个独立的虚拟地址空间，并且这个地址空间是连续的。这样，进程就可以很方便地访问内存，更确切地说是访问虚拟内存。虚拟地址空间的内部又被分为内核空间和用户空间两部分，不同字长（也就是单个CPU指令可以处理数据的最大长度）的处理器，地址空间的范围也不同。比如最常见的 32 位和 64 位系统，它们的虚拟地址空间，如下所示：通过这里可以看出，32位系统的内核空间占用 1G，位于最高处，剩下的3G是用户空间。而 64 位系统的内核空间和用户空间都是 128T，分别占据整个内存空间的最高和最低处，剩下的中间部分是未定义的。进程在用户态时，只能访问用户空间内存；只有进入内核态后，才可以访问内核空间内存。虽然每个进程的地址空间都包含了内核空间，但这些内核空间，其实关联的都是相同的物理内存。这样，进程切换到内核态后，就可以很方便地访问内核空间内存。既然每个进程都有一个这么大的地址空间，那么所有进程的虚拟内存加起来，自然要比实际的物理内存大得多。所以，并不是所有的虚拟内存都会分配物理内存，只有那些实际使用的虚拟内存才分配物理内存，并且分配后的物理内存，是通过内存映射来管理的。内存映射，其实就是将虚拟内存地址映射到物理内存地址。为了完成内存映射，内核为每个进程都维护了一张页表，记录虚拟地址与物理地址的映射关系，如下图所示：页表实际上存储在 CPU 的内存管理单元 MMU中，这样，正常情况下，处理器就可以直接通过硬件，找出要访问的内存。而当进程访问的虚拟地址在页表中查不到时，系统会产生一个缺页异常，进入内核空间分配物理内存、更新进程页表，最后再返回用户空间，恢复进程的运行。另外，TLB（Translation Lookaside Buffer，转译后备缓冲器）会影响 CPU 的内存访问性能，TLB 其实就是 MMU 中页表的高速缓存。由于进程的虚拟地址空间是独立的，而 TLB 的访问速度又比 MMU 快得多，所以，通过减少进程的上下文切换，减少TLB的刷新次数，就可以提高TLB 缓存的使用率，进而提高CPU的内存访问性能。不过要注意，MMU 并不以字节为单位来管理内存，而是规定了一个内存映射的最小单位，也就是页，通常是 4 KB大小。这样，每一次内存映射，都需要关联 4 KB 或者 4KB 整数倍的内存空间。页的大小只有4 KB ，导致的另一个问题就是，整个页表会变得非常大。比方说，仅 32 位系统就需要 100 多万个页表项（4GB/4KB），才可以实现整个地址空间的映射。为了解决页表项过多的问题，Linux 提供了两种机制，也就是多级页表和大页（HugePage）。多级页表就是把内存分成区块来管理，将原来的映射关系改成区块索引和区块内的偏移。由于虚拟内存空间通常只用了很少一部分，那么，多级页表就只保存这些使用中的区块，这样就可以大大地减少页表的项数。Linux用的正是四级页表来管理内存页，如下图所示，虚拟地址被分为5个部分，前4个表项用于选择页，而最后一个索引表示页内偏移。大页，就是比普通页更大的内存块，常见的大小有 2MB 和 1GB。大页通常用在使用大量内存的进程上，比如 Oracle、DPDK等。通过这些机制，在页表的映射下，进程就可以通过虚拟地址来访问物理内存了。虚拟内存空间分布最上方的内核空间不用多讲，下方的用户空间内存，其实又被分成了多个不同的段。以32 位系统为例，如下图：通过这张图可以看到，用户空间内存，从低到高分别是五种不同的内存段。只读段，包括代码和常量等。数据段，包括全局变量等。堆，包括动态分配的内存，从低地址开始向上增长。文件映射段，包括动态库、共享内存等，从高地址开始向下增长。栈，包括局部变量和函数调用的上下文等。栈的大小是固定的，一般是 8 MB。在这五个内存段中，堆和文件映射段的内存是动态分配的。比如说，使用 C 标准库的 malloc() 或者 mmap() ，就可以分别在堆和文件映射段动态分配内存。其实64位系统的内存分布也类似，只不过内存空间要大得多。内存分配与回收malloc() 是 C 标准库提供的内存分配函数，对应到系统调用上，有两种实现方式，即 brk() 和 mmap()。对小块内存（小于128K），C 标准库使用 brk()来分配，也就是通过移动堆顶的位置来分配内存。这些内存释放后并不会立刻归还系统，而是被缓存起来，这样就可以重复使用。而大块内存（大于128K），则直接使用内存映射 mmap() 来分配，也就是在文件映射段找一块空闲内存分配出去。这两种方式，自然各有优缺点。brk() 方式的缓存，可以减少缺页异常的发生，提高内存访问效率。不过，由于这些内存没有归还系统，在内存工作繁忙时，频繁的内存分配和释放会造成内存碎片。-mmap() 方式分配的内存，会在释放时直接归还系统，所以每次 mmap 都会发生缺页异常。在内存工作繁忙时，频繁的内存分配会导致大量的缺页异常，使内核的管理负担增大。这也是malloc 只对大块内存使用 mmap 的原因。了解这两种调用方式后，还需要清楚一点，那就是，当这两种调用发生后，其实并没有真正分配内存。这些内存，都只在首次访问时才分配，也就是通过缺页异常进入内核中，再由内核来分配内存。整体来说，Linux 使用伙伴系统来管理内存分配。这些内存在MMU中以页为单位进行管理，伙伴系统也一样，以页为单位来管理内存，并且会通过相邻页的合并，减少内存碎片化（比如brk方式造成的内存碎片）。在用户空间，malloc 通过 brk() 分配的内存，在释放时并不立即归还系统，而是缓存起来重复利用。在内核空间，Linux 则通过 slab 分配器来管理小内存。可以把slab 看成构建在伙伴系统上的一个缓存，主要作用就是分配并释放内核中的小对象。对内存来说，如果只分配而不释放，就会造成内存泄漏，甚至会耗尽系统内存。所以，在应用程序用完内存后，还需要调用 free() 或 unmap()，来释放这些不用的内存。当然，系统也不会任由某个进程用完所有内存。在发现内存紧张时，系统就会通过一系列机制来回收内存，比如下面这三种方式：回收缓存，比如使用 LRU（Least Recently Used）算法，回收最近使用最少的内存页面；回收不常访问的内存，把不常用的内存通过交换分区直接写到磁盘中；杀死进程，内存紧张时系统还会通过 OOM（Out of Memory），直接杀掉占用大量内存的进程。其中，第二种方式回收不常访问的内存时，会用到交换分区（以下简称 Swap）。Swap 其实就是把一块磁盘空间当成内存来用。它可以把进程暂时不用的数据存储到磁盘中（这个过程称为换出），当进程访问这些内存时，再从磁盘读取这些数据到内存中（这个过程称为换入）。所以，可以发现，Swap 把系统的可用内存变大了。不过要注意，通常只在内存不足时，才会发生 Swap 交换。并且由于磁盘读写的速度远比内存慢，Swap 会导致严重的内存性能问题。第三种方式提到的 OOM（Out of Memory），其实是内核的一种保护机制。它监控进程的内存使用情况，并且使用 oom_score 为每个进程的内存使用情况进行评分：一个进程消耗的内存越大，oom_score 就越大；一个进程运行占用的 CPU 越多，oom_score 就越小。这样，进程的 oom_score 越大，代表消耗的内存越多，也就越容易被 OOM 杀死，从而可以更好保护系统。当然，为了实际工作的需要，管理员可以通过 /proc 文件系统，手动设置进程的 oom_adj ，从而调整进程的 oom_score。oom_adj 的范围是 [-17, 15]，数值越大，表示进程越容易被 OOM 杀死；数值越小，表示进程越不容易被 OOM 杀死，其中 -17 表示禁止OOM。比如用下面的命令，就可以把 sshd 进程的 oom_adj 调小为 -16，这样， sshd 进程就不容易被 OOM 杀死。echo -16 > /proc/$(pidof sshd)/oom_adj 小结对普通进程来说，它能看到的其实是内核提供的虚拟内存，这些虚拟内存还需要通过页表，由系统映射为物理内存。当进程通过 malloc() 申请内存后，内存并不会立即分配，而是在首次访问时，才通过缺页异常陷入内核中分配内存。由于进程的虚拟地址空间比物理内存大很多，Linux 还提供了一系列的机制，应对内存不足的问题，比如缓存的回收、交换分区 Swap 以及OOM 等。当需要了解系统或者进程的内存使用情况时，可以用 free 和 top 、ps 等性能工具。它们都是分析性能问题时最常用的性能工具。转自https://is.gd/kWSsQe
SSD固态硬盘的结构和基本工作原理概述
我们都知道，早期的电脑CPU是可以直接从硬盘上面读取数据进行处理的，随着科技的进步，时代的发展，计算机硬件的发展速度也是极其迅猛。CPU主频的不断提升，从单核到双核，再到多核；CPU的处理速度越来越快，而硬盘的的读写速度已经远远跟不上CPU的读写速度，后来增加了内存这个读写速度相对较快的缓存，而内存也是蓬勃到发展，从SDRAM到DDR，从DDR到DDR2再到DDR3，但是无论怎样，内存缓存速度还是跟不上CPU的运算处理速度，后来便在CPU中增加了快速缓存机制！而硬盘这个持久化存储器呢？之前的文章，聊到了机械硬盘的结构和工作原理，今天就来聊一聊SSD固态硬盘的结构和基本工作原理，如理解有所变差，或文章有所不足，皆因水平所限！硬盘的发展在不断的科技进步中快速提升，从容量以及速度再到接口方面。从早期的PATA变成SATA，SCSI变到SAS，以及垂直记录技术在容量上的突破，但这些进步亦未能改变磁盘的记录方式。随着人们对数据需求增多，存储系统的瓶颈越来越明显。而在嵌入式领域移动设备和工业自动化控制等恶劣环境下，传统硬盘机械结构已经无法满足要求，而所有这一切随着固态存储(SSD)的到来而发生了改变。传统的机械硬盘(HDD)运行主要是靠机械驱动头，包括马达、盘片、磁头摇臂等必需的机械部件，它必须在快速旋转的磁盘上移动至访问位置，至少95%的时间都消耗在机械部件的动作上。SSD却不同机械构造，无需移动的部件，主要由主控与闪存芯片组成的SSD可以以更快速度和准确性访问驱动器到任何位置。传统机械硬盘必须得依靠主轴主机、磁头和磁头臂来找到位置，而SSD用集成的电路代替了物理旋转磁盘，访问数据的时间及延迟远远超过了机械硬盘。SSD有如此的“神速”，完全得益于内部的组成部件：主控--闪存--固件算法。主控、闪存及固件算法三者的关系：SSD最重要的三个组件就是NAND闪存，控制器及固件。NAND闪存负责重要的存储任务，控制器和固件需要协作来完成复杂且同样重要的任务，即管理数据存储、维护SSD性能和使用寿命等。主控：控制器是一种嵌入式微芯片(如电脑中CPU)，其功能就像命令中心，发出SSD的所有操作请求----从实际读取和写入数据到执行垃圾回收和耗损均衡算法等，以保证SSD的速度及整洁度，可以说主控是SSD的大脑中枢。目前主流的控制器有Marvell、SandForce、Samsung、Indilinx等。像Marvell各方面都很强劲，代表型号为Marvell 88SS9187/89/90主控，运用在浦科特、闪迪、英睿达等品牌的SSD上。SandForce的性能也不错，它的特点是支持压缩数据，比如一个10M的可压缩数据可能被他压成5M的写入硬盘，但还是占用10M的空间，可以提高点速度，最大的特点是会延长SSD的寿命，但是CPU占用会高点而且速度会随着硬盘的使用逐渐小幅度降低。代表型号为SF-2281，运用在包括Intel、金士顿、威刚等品牌的SSD上。Samsung主控一般只有自家的SSD上使用，性能上也是很强悍的，不会比Marvell差多少。目前三星主控已经发展到第五代MEX，主要运用在三星850EVO、850PRO上。固件算法：SSD的固件是确保SSD性能的最重要组件，用于驱动控制器。主控将使用SSD中固件算法中的控制程序，去执行自动信号处理，耗损平衡，错误校正码(ECC)，坏块管理、垃圾回收算法、与主机设备(如电脑)通信，以及执行数据加密等任务。由于固件冗余存储至NAND闪存中，因此当SSD制造商发布一个更新时，需要手动更新固件来改进和扩大SSD的功能。开发高品质的固件不仅需要精密的工程技术，而且需要在NAND闪存、控制器和其他SSD组件间实现完美整合。此外，还必须掌握NADN特征、半导体工艺和控制器特征等领域的最先进的技术。固件的品质越好，整个SSD就越精确，越高效，目前具备独立固件研发的SSD厂商并不多，仅有Intel/英睿达/浦科特/OCZ/三星等厂商，希望我国能早日解决。NAND闪存：SSD用户的数据全部存储于NAND闪存里，它是SSD的存储媒介。SSD最主要的成本就集中在NAND闪存上。NAND闪存不仅决定了SSD的使用寿命，而且对SSD的性能影响也非常大。NAND闪存颗粒结构及工作原理都很复杂，接下来我们会继续推出系列文章来重点介绍闪存，这里主要来了解一下大家平常选购SSD经常接触到的SLC、MLC及TLC闪存。SLC/MLC/TLC闪存：三种闪存状态这几年NAND闪存的技术发展迅猛同，从企业级标准的SLC闪存到被广泛运用在消费级SSD上的MLC闪存再到目前正在兴起的TLC闪存，短短时间里，我们看到NAND技术显著进步。对SLC、MLC及TLC闪存怎么理解呢？简单来说，NAND闪存中存储的数据是以电荷的方式存储在每个NAND存储单元内的，SLC、MLC及TLC就是存储的位数不同。单层存储与多层存储的区别在于每个NAND存储单元一次所能存储的“位元数”。SLC(Single-Level Cell)单层式存储每个存储单元仅能储存1bit数据，同样，MLC(Multi-Level Cell)可储存2bit数据，TLC(Trinary-Level)可储存3bit数据。一个存储单元上，一次存储的位数越多，该单元拥有的容量就越大，这样能节约闪存的成本，提高NAND的生产量。但随之而来的是，向每个单元存储单元中加入更多的数据会使得状态难以辨别，并且可靠性、耐用性和性能都 会降低。一颗NAND芯片是32G的容量，也就是说128G的SSD，内部是5个NAND芯片做并行读取。读写的时候都依靠主控芯片来做控制，主控芯片还要对所有的NAND闪存芯片做磨损平衡，保证这帮兄弟要挂一起挂，假如是256G的，内部是8通道，并发的读写能力比128G会有了接近50%的提升。至于再大的容量，因为存储容量过大，导致主控芯片保存的地址映射表过大，性能可能会出现持平甚至下降的情况。固态硬盘是无需移动的固态电子元件，可以直接进行数据读取。具体量化的概念就是，一台笔记本电脑在使用传统硬盘时可能需要等待36秒才能让操作系统完成启动，而现在如果使用固态硬盘，则只需等待不到9秒钟。基于这种高性能硬盘的协同工作，CPU的运行效率也会提高，其节省能耗的优点足以使电池延长15%的寿命，而且它更加抗震和轻便。而传统硬盘在读取及写入数据的时候，硬盘磁头需要花费时间转动并找到数据所在的位置。工作原理概述SSD主控通过若干个通道（channel）并行操作多块FLASH颗粒，类似RAID0，大大提高底层的带宽。举个例子，假设主控与FLASH颗粒之间有8个通道，每个通道上挂载了一个闪存颗粒，HOST与FLASH之间数据传输速率为200MB/s。该闪存颗粒Page大小为8KB，FLASH page的读取时间为Tr=50us，平均写入时间为Tp=800us，8KB数据传输时间为Tx=40us。那么底层读取最大带宽为（8KB/(50us+40us)）8 = 711MB/s，写入最大带宽为(8KB/(800us+40us))8 = 76MB/s。从上可以看出，要提高底层带宽，可以增加底层并行的颗粒数目，也可以选择速度快的FLASH颗粒（或者让速度慢的颗粒变快，比如MLC配成SLC使用）。主控通过8通道连接8个FLASH DIE，为方便解释，这里只画了每个DIE里的一个Block，其中每个小方块表示一个Page （假设大小为4KB）。 HOST写入4KB数据HOST继续写入16KB数据HOST继续写入，最后整个Block都写满当所有Channel上的Block都写满的时候，SSD主控会挑选下一个Block以同样的方式继续写入。 HOST是通过LBA（Logical Block Address，逻辑地址块）访问SSD的，每个LBA代表着一个Sector（一般为512B大小），操作系统一般以4K为单位访问SSD，我们把HOST访问SSD的基本单元叫用户页（Host Page）。而在SSD内部，SSD主控与FLASH之间是FLASH Page为基本单元访问FLASH的，我们称FLASH Page为物理页（Physical Page）。HOST每写入一个Host Page, SSD主控会找一个Physical Page把Host数据写入，SSD内部同时记录了这样一条映射（Map）。有了这样一个映射关系后，下次HOST需要读某个Host Page 时，SSD就知道从FLASH的哪个位置把数据读取上来。 SSD内部维护了一张映射表（Map Table），HOST每写入一个Host Page，就会产生一个新的映射关系，这个映射关系会加入（第一次写）或者更改（覆盖写）Map Table；当读取某个HostPage时， SSD首先查找Map Table中该Host Page对应的Physical Page，然后再访问Flash读取相应的Host数据。 一张Map Table有多大呢？这里假设我们有一个256GB的SSD，以4KB Host Page为例，那么一共有约 64M（256GB/4KB）个Host Page，也就意味着SSD需要有64M大小的Map Table。Map Table中的每个Entry存储的就是物理地址（Physical Page Address），假设其为4Byte (32bits) ，那么整个Map Table的大小为64M*4B = 256MB。 对绝大多数SSD，我们可以看到上面都有板载DRAM，其主要作用就是用来存储这张映射表。也有例外，比如基于Sandforce主控的SSD，它并不支持板载DRAM，那么它的映射表存在哪里呢？SSD工作时，它的绝大部分映射是存储在FLASH里面，还有一部分存储在片上RAM上。当HOST需要读取一些数据时，对有板载DRAM的SSD来说，只要查找DRAM当中的映射表，获取到物理地址后访问FLASH从而得到HOST数据.这期间只需要访问一次FLASH；而对Sandforce的SSD来说，它首先看看该Host Page对应的映射关系是否在RAM内，如果在，那好办，直接根据映射关系读取FLASH；如果该映射关系不在RAM内，那么它首先需要把映射关系从FLASH里面读取出来，然后再根据这个映射关系读取Host数据，这就意味着相比有DRAM的SSD，它需要读取两次FLASH才能把HOST数据读取出来，底层有效带宽减半。对HOST随机读来说，由于片上RAM有限，映射关系Cache命中(映射关系在片上RAM)的概率很小，所以对它来说，基本每次读都需要访问两次FLASH，所以我们可以看到基于Sandforce主控的SSD随机读取性能是不太理想的。 继续回到之前的SSD写操作。当整个SSD写满后，从用户角度来看，如果想写入新的数据，则必须删除一些数据，然后腾出空间再写。用户在删除和写入数据的过程中，会导致一些Block里面的数据变无效或者变老。如下图所示（绿色小方块代表有效数据，红色小方块代表无效数据）： Block中的数据变老或者无效，是指没有任何映射关系指向它们，用户不会访问到这些FLASH空间，它们被新的映射关系所取代。比如有一个Host Page A，开始它存储在FLASH空间的X,映射关系为A->X。后来，HOST重写了该Host Page，由于FLASH不能覆盖写，SSD内部必须寻找一个没有写过的位置写入新的数据，假设为Y，这个时候新的映射关系建立：A->Y，之前的映射关系解除，位置X上的数据变老失效，我们把这些数据叫垃圾数据。 随着HOST的持续写入，FLASH存储空间慢慢变小，直到耗尽。如果不及时清除这些垃圾数据，HOST就无法写入。SSD内部都有垃圾回收机制，它的基本原理是把几个Block中的有效数据（非垃圾数据，上图中的绿色小方块表示的）集中搬到一个新的Block上面去，然后再把这几个Block擦除掉，这样就产生新的可用Block了。 上图中，Block x上面有效数据为A,B,C，Block y上面有效数据为D,E,F,G，红色方块为无效数据。垃圾回收机制就是先找一个未写过的可用Block z，然后把Block x和Block y的有效数据搬移到Block z上面去，这样Block x和Block y上面就没有任何有效数据，可以擦除变成两个可用的Block。 一块刚买的SSD，你会发现写入速度很快，那是因为一开始总能找到可用的Block来进行写入。但是，随着你对SSD的使用，你会发现它会变慢。原因就在于SSD写满后，当你需要写入新的数据，往往需要做上述的垃圾回收：把若干个Block上面的有效数据搬移到某个Block，然后擦掉原先的Block，然后再把你的Host数据写入。这比最初单纯的找个可用的Block来写耗时多了，所以速度变慢也就可以理解了。 还是以上图为例。假设HOST要写入4KB数据 (H) ，由于当前可用Block过少，SSD开始做垃圾回收。从上图可以看出，对Block x来说，它需要把Page A,B,C的数据读出并写入到Block z，然后Block x擦除用于HOST数据写入。从Host角度，它只写了4KB数据，但从SSD内部来说，它实际写入了4个Page（Page A, B, C写入Block z，4KB数据H写入到Block x）。垃圾回收原理 再看一下这张图。回收Block x，上面有3个有效Page，需要读写3个Page完成整个Block的回收；而回收Block y时，则需要读写4个有效Page。两者相比，显然回收Block x比回收Block y快一些。说明一个简单的道理：一个Block上有效的数据越少（垃圾数据越多），则回收速度越快。 256GB FLASH配成256GB的SSD （OP = 7.37%）, 意味着25610^9的有效数据写到 2562^30的空间，每个Block上面的平均有效数据率可以认为是25610^9/2562^30 = 93.1%。 如果配成240GB的SSD，则意味着24010^9的有效数据写到2562^30的空间，每个Block的平均有效数据率为24010^9/2562^30 = 87.3%。 OP越大，每个Block平均有效数据率越小，因此我们可以得出的结论：OP越大，垃圾回收越快，写放大越小。这就是OP大的好处。 写放大越小，意味着写入同样多的HOST数据，写入到FLASH中的数据越少，也就意味着FLASH损耗越小。FLASH都是有一定寿命的，它是用P/E数 (Program/Erase Count)来衡量的。（关于FLASH基础知识，请参考《闪存基础》）。如果SSD集中对某几个Block进行擦写，那么这几个Block很快就寿命耗尽。比如在用户空间，有些数据是频繁需要更新的，那么这些数据所在Block就需要频繁的进行擦写，这些Block的寿命就可能很快的耗尽。相反，有些数据用户是很少更新的，比如一些只读文件，那么这些数据所在的Block擦写的次数就很少。随着用户对SSD的使用，就会形成一些Block有很高的PE数，而有些Block的PE数却很低的。这不是我们想看到的，我们希望所有Block的PE数都应该差不多，就是这些Block被均衡的使用。在SSD内部，有一种叫磨损平衡（Wear Leveling，WL）的机制来保证这点。 WL有两种算法：动态WL和静态WL。所谓动态WL，就是在使用Block进行擦写操作的时候，优先挑选PE 数低的；所谓静态WL，就是把长期没有修改的老数据（如前面提到的只读文件数据）从PE数低的Block当中搬出来，然后找个PE 数高的Block进行存放，这样，之前低PE数的Block就能拿出来使用。 下面这张图（来源网络）诠释了无WL，动态WL和静态WL下的FLASH耐久度的区别 （假设每个Block最大PE数为10,000）：转自https://is.gd/V3L9nG
硬盘内部硬件结构和工作原理详解
一般硬盘正面贴有产品标签，主要包括厂家信息和产品信息，如商标、型号、序列号、生产日期、容量、参数和主从设置方法等。这些信息是正确使用硬盘的基本依据，下面将逐步介绍它们的含义。硬盘主要由盘体、控制电路板和接口部件等组成，如图1-1所示。盘体是一个密封的腔体。硬盘的内部结构通常是指盘体的内部结构；控制电路板上主要有硬盘BIOS、硬盘缓存（即CACHE）和主控制芯片等单元，如图1-2所示；硬盘接口包括电源插座、数据接口和主、从跳线，如图1-3所示。图1-1 硬盘的外观图1-2 控制电路板图1-3 硬盘接口电源插座连接电源，为硬盘工作提供电力保证。数据接口是硬盘与主板、内存之间进行数据交换的通道，使用一根40针40线（早期）或40针80线（当前）的IDE接口电缆进行连接。新增加的40线是信号屏蔽线，用于屏蔽高速高频数据传输过程中的串扰。中间的主、从盘跳线插座，用以设置主、从硬盘，即设置硬盘驱动器的访问顺序。其设置方法一般标注在盘体外的标签上，也有一些标注在接口处，早期的硬盘还可能印在电路板上。此外，在硬盘表面有一个透气孔（见图1-1），它的作用是使硬盘内部气压与外部大气压保持一致。由于盘体是密封的，所以，这个透气孔不直接和内部相通，而是经由一个高效过滤器和盘体相通，用以保证盘体内部的洁净无尘，使用中注意不要将它盖住。1.2 硬盘的内部结构硬盘的内部结构通常专指盘体的内部结构。盘体是一个密封的腔体，里面密封着磁头、盘片（磁片、碟片）等部件，如图1-4所示。图1-4 硬盘内部结构硬盘的盘片是硬质磁性合金盘片，片厚一般在0.5mm左右，直径主要有1.8in（1in=25.4mm）、2.5in、3.5in和5.25in 4种，其中2.5in和3.5in盘片应用最广。盘片的转速与盘片大小有关，考虑到惯性及盘片的稳定性，盘片越大转速越低。一般来讲，2.5in硬盘的转速在5 400 r/min～7 200 r/ min之间；3.5in硬盘的转速在4 500 r/min～5 400 r/min之间；而5.25in硬盘转速则在3 600 r/min～4 500 r/min之间。随着技术的进步，现在2.5in硬盘的转速最高已达15 000 r/min，3.5in硬盘的转速最高已达12 000 r/min。有的硬盘只装一张盘片，有的硬盘则有多张盘片。这些盘片安装在主轴电机的转轴上，在主轴电机的带动下高速旋转。每张盘片的容量称为单碟容量，而硬盘的容量就是所有盘片容量的总和。早期硬盘由于单碟容量低，所以，盘片较多，有的甚至多达10余片，现代硬盘的盘片一般只有少数几片。一块硬盘内的所有盘片都是完全一样的，不然控制部分就太复杂了。一个牌子的一个系列一般都用同一种盘片，使用不同数量的盘片，就出现了一个系列不同容量的硬盘产品。盘体的完整构造如图1-5所示。图1-5 盘体的完整结构硬盘驱动器采用高精度、轻型磁头驱动/定位系统。这种系统能使磁头在盘面上快速移动，可在极短的时间内精确地定位在由计算机指令指定的磁道上。目前，磁道密度已高达5 400Tpi（每英寸磁道数）或更高；人们还在研究各种新方法，如在盘上挤压（或刻蚀）图形、凹槽和斑点等作为定位和跟踪标记，以提高到和光盘相等的道密度，从而在保持磁盘机高速度、高位密度和高可靠性的优势下，大幅度提高存储容量。硬盘驱动器内的电机都是无刷电机，在高速轴承支持下机械磨损很小，可以长时间连续工作。高速旋转的盘体产生明显的陀螺效应，所以，在硬盘工作时不宜搬动，否则，将增加轴承的工作负荷。为了高速存储和读取信息，硬盘驱动器的磁头质量小，惯性也小，所以，硬盘驱动器的寻道速度明显快于软驱和光驱。硬盘驱动器磁头与磁头臂及伺服定位系统是一个整体。伺服定位系统由磁头臂后的线圈和固定在底板上的电磁控制系统组成。由于定位系统限制，磁头臂只能在盘片的内外磁道之间移动。因此，不管开机还是关机，磁头总在盘片上；所不同的是，关机时磁头停留在盘片启停区，开机时磁头“飞行”在磁盘片上方。硬盘上的数据是如何组织与管理的呢？硬盘首先在逻辑上被划分为磁道、柱面以及扇区，其结构关系如图1-6所示。图1-6 磁头、柱面和扇区每个盘片的每个面都有一个读写磁头，磁盘盘面区域的划分如图1-7所示。磁头靠近主轴接触的表面，即线速度最小的地方，是一个特殊的区域，它不存放任何数据，称为启停区或着陆区（Landing Zone），启停区外就是数据区。在最外圈，离主轴最远的地方是“0”磁道，硬盘数据的存放就是从最外圈开始的。那么，磁头是如何找到“0”磁道的位置的呢？从图1-5中可以看到，有一个“0”磁道检测器，由它来完成硬盘的初始定位。“0”磁道是如此的重要，以致很多硬盘仅仅因为“0”磁道损坏就报废，这是非常可惜的。这种故障的修复技术在后面的章节中有详细的介绍。图1-7 硬盘盘片的启停区和数据区早期的硬盘在每次关机之前需要运行一个被称为Parking的程序，其作用是让磁头回到启停区。现代硬盘在设计上已摒弃了这个虽不复杂却很让人不愉快的小缺陷。硬盘不工作时，磁头停留在启停区，当需要从硬盘读写数据时，磁盘开始旋转。旋转速度达到额定的高速时，磁头就会因盘片旋转产生的气流而抬起，这时磁头才向盘片存放数据的区域移动。盘片旋转产生的气流相当强，足以使磁头托起，并与盘面保持一个微小的距离。这个距离越小，磁头读写数据的灵敏度就越高，当然对硬盘各部件的要求也越高。早期设计的磁盘驱动器使磁头保持在盘面上方几微米处飞行。稍后一些设计使磁头在盘面上的飞行高度降到约0.1μm～0.5μm，现在的水平已经达到0.005μm～0.01μm，这只是人类头发直径的千分之一。气流既能使磁头脱离开盘面，又能使它保持在离盘面足够近的地方，非常紧密地跟随着磁盘表面呈起伏运动，使磁头飞行处于严格受控状态。磁头必须飞行在盘面上方，而不是接触盘面，这种位置可避免擦伤磁性涂层，而更重要的是不让磁性涂层损伤磁头。但是，磁头也不能离盘面太远，否则，就不能使盘面达到足够强的磁化，难以读出盘上的磁化翻转（磁极转换形式，是磁盘上实际记录数据的方式）。硬盘驱动器磁头的飞行悬浮高度低、速度快，一旦有小的尘埃进入硬盘密封腔内，或者一旦磁头与盘体发生碰撞，就可能造成数据丢失，形成坏块，甚至造成磁头和盘体的损坏。所以，硬盘系统的密封一定要可靠，在非专业条件下绝对不能开启硬盘密封腔，否则，灰尘进入后会加速硬盘的损坏。另外，硬盘驱动器磁头的寻道伺服电机多采用音圈式旋转或直线运动步进电机，在伺服跟踪的调节下精确地跟踪盘片的磁道，所以，硬盘工作时不要有冲击碰撞，搬动时要小心轻放。这种硬盘就是采用温彻斯特（Winchester）技术制造的硬盘，所以也被称为温盘。其结构特点如下。①磁头、盘片及运动机构密封在盘体内。②磁头在启动、停止时与盘片接触，在工作时因盘片高速旋转，带动磁头“悬浮”在盘片上面呈飞行状态（空气动力学原理），“悬浮”的高度约为0.1μm～0.3μm，这个高度非常小，图1-8标出了这个高度与头发、烟尘和手指印的大小比较关系，从这里可以直观地“看”出这个高度有多“高”。图1-8 盘片结构及磁头高度示意图③磁头工作时与盘片不直接接触，所以，磁头的加载较小，磁头可以做得很精致，检测磁道的能力很强，可大大提高位密度。④磁盘表面非常平整光滑，可以做镜面使用。下面对“盘面”、“磁道”、“柱面”和“扇区”的含义逐一进行介绍。1. 盘面号硬盘的盘片一般用铝合金材料做基片，高速硬盘也可能用玻璃做基片。玻璃基片更容易达到所需的平面度和光洁度，且有很高的硬度。磁头传动装置是使磁头部件作径向移动的部件，通常有两种类型的传动装置。一种是齿条传动的步进电机传动装置；另一种是音圈电机传动装置。前者是固定推算的传动定位器，而后者则采用伺服反馈返回到正确的位置上。磁头传动装置以很小的等距离使磁头部件做径向移动，用以变换磁道。硬盘的每一个盘片都有两个盘面（Side），即上、下盘面，一般每个盘面都会利用，都可以存储数据，成为有效盘片，也有极个别的硬盘盘面数为单数。每一个这样的有效盘面都有一个盘面号，按顺序从上至下从“0”开始依次编号。在硬盘系统中，盘面号又叫磁头号，因为每一个有效盘面都有一个对应的读写磁头。硬盘的盘片组在2～14片不等，通常有2～3个盘片，故盘面号（磁头号）为0～3或0～5。2. 磁道磁盘在格式化时被划分成许多同心圆，这些同心圆轨迹叫做磁道（Track）。磁道从外向内从0开始顺序编号。硬盘的每一个盘面有300～1 024个磁道，新式大容量硬盘每面的磁道数更多。信息以脉冲串的形式记录在这些轨迹中，这些同心圆不是连续记录数据，而是被划分成一段段的圆弧，这些圆弧的角速度一样。由于径向长度不一样，所以，线速度也不一样，外圈的线速度较内圈的线速度大，即同样的转速下，外圈在同样时间段里，划过的圆弧长度要比内圈划过的圆弧长度大。每段圆弧叫做一个扇区，扇区从“1”开始编号，每个扇区中的数据作为一个单元同时读出或写入。一个标准的3.5in硬盘盘面通常有几百到几千条磁道。磁道是“看”不见的，只是盘面上以特殊形式磁化了的一些磁化区，在磁盘格式化时就已规划完毕。3. 柱面所有盘面上的同一磁道构成一个圆柱，通常称做柱面（Cylinder），每个圆柱上的磁头由上而下从“0”开始编号。数据的读/写按柱面进行，即磁头读/写数据时首先在同一柱面内从“0”磁头开始进行操作，依次向下在同一柱面的不同盘面即磁头上进行操作，只在同一柱面所有的磁头全部读/写完毕后磁头才转移到下一柱面，因为选取磁头只需通过电子切换即可，而选取柱面则必须通过机械切换。电子切换相当快，比在机械上磁头向邻近磁道移动快得多，所以，数据的读/写按柱面进行，而不按盘面进行。也就是说，一个磁道写满数据后，就在同一柱面的下一个盘面来写，一个柱面写满后，才移到下一个扇区开始写数据。读数据也按照这种方式进行，这样就提高了硬盘的读/写效率。一块硬盘驱动器的圆柱数（或每个盘面的磁道数）既取决于每条磁道的宽窄（同样，也与磁头的大小有关），也取决于定位机构所决定的磁道间步距的大小。更深层的内容请参考其他书籍，限于篇幅，这里不再深入介绍。4. 扇区操作系统以扇区（Sector）形式将信息存储在硬盘上，每个扇区包括512个字节的数据和一些其他信息。一个扇区有两个主要部分：存储数据地点的标识符和存储数据的数据段，如图1-9所示。图1-9 硬盘扇区的构成标识符就是扇区头标，包括组成扇区三维地址的三个数字：扇区所在的磁头（或盘面）、磁道（或柱面号）以及扇区在磁道上的位置即扇区号。头标中还包括一个字段，其中有显示扇区是否能可靠存储数据，或者是否已发现某个故障因而不宜使用的标记。有些硬盘控制器在扇区头标中还记录有指示字，可在原扇区出错时指引磁盘转到替换扇区或磁道。最后，扇区头标以循环冗余校验（CRC）值作为结束，以供控制器检验扇区头标的读出情况，确保准确无误。扇区的第二个主要部分是存储数据的数据段，可分为数据和保护数据的纠错码（ECC）。在初始准备期间，计算机用512个虚拟信息字节（实际数据的存放地）和与这些虚拟信息字节相应的ECC数字填入这个部分。扇区头标包含一个可识别磁道上该扇区的扇区号。有趣的是，这些扇区号物理上并不连续编号，它们不必用任何特定的顺序指定。扇区头标的设计允许扇区号可以从1到某个最大值，某些情况下可达255。磁盘控制器并不关心上述范围中什么编号安排在哪一个扇区头标中。在很特殊的情况下，扇区还可以共用相同的编号。磁盘控制器甚至根本就不管数据区有多大，只管读出它所找到的数据，或者写入要求它写的数据。给扇区编号的最简单方法是l，2，3，4，5，6等顺序编号。如果扇区按顺序绕着磁道依次编号，那么，控制器在处理一个扇区的数据期间，磁盘旋转太远，超过扇区间的间隔（这个间隔很小），控制器要读出或写入的下一扇区已经通过磁头，也许是相当大的一段距离。在这种情况下，磁盘控制器就只能等待磁盘再次旋转几乎一周，才能使得需要的扇区到达磁头下面。显然，要解决这个问题，靠加大扇区间的间隔是不现实的，那会浪费许多磁盘空间。许多年前，IBM的一位杰出工程师想出了一个绝妙的办法，即对扇区不使用顺序编号，而是使用一个交叉因子（interleave）进行编号。交叉因子用比值的方法来表示，如3﹕1表示磁道上的第1个扇区为1号扇区，跳过两个扇区即第4个扇区为2号扇区，这个过程持续下去直到给每个物理扇区编上逻辑号为止。例如，每磁道有17个扇区的磁盘按2﹕1的交叉因子编号就是：l，10，2，11，3，12，4，13，5，14，6，15，7，16，8，17，9，而按3﹕1的交叉因子编号就是：l，7，13，2，8，14，3，9，15，4，10，16，5，11，17，6，12。当设置1﹕l的交叉因子时，如果硬盘控制器处理信息足够快，那么，读出磁道上的全部扇区只需要旋转一周；但如果硬盘控制器的后处理动作没有这么快，磁盘所转的圈数就等于一个磁道上的扇区数，才能读出每个磁道上的全部数据。将交叉因子设定为2﹕1时，磁头要读出磁道上的全部数据，磁盘只需转两周。如果2﹕1的交叉因子仍不够慢，磁盘旋转的周数约为磁道的扇区数，这时，可将交叉因子调整为3﹕1，如图1-10所示。图1-10 不同交叉因子的效果示例图1-10所示的是典型的MFM（Modified Frequency Modulation，改进型调频制编码）硬盘，每磁道有17个扇区，画出了用三种不同的扇区交叉因子编号的情况。最外圈的磁道（0号柱面）上的扇区用简单的顺序连续编号，相当于扇区交叉因子是1﹕1。1号磁道（柱面）的扇区按2﹕1的交叉因子编号，而2号磁道按3﹕1的扇区交叉因子编号。早期的硬盘管理工作中，设置交叉因子需要用户自己完成。用BIOS中的低级格式化程序对硬盘进行低级格式化时，就需要指定交叉因子，有时还需要设置几种不同的值来比较其性能，而后确定一个比较好的值，以期硬盘的性能较好。现在的硬盘BIOS已经自己解决这个问题，所以，一般低级格式化程序不再提供这一选项设置。系统将文件存储到磁盘上时，按柱面、磁头、扇区的方式进行，即最先是第1磁道的第一磁头下（也就是第1盘面的第一磁道）的所有扇区，然后，是同一柱面的下一磁头，……，一个柱面存储满后就推进到下一个柱面，直到把文件内容全部写入磁盘。系统也以相同的顺序读出数据。读出数据时通过告诉磁盘控制器要读出扇区所在的柱面号、磁头号和扇区号（物理地址的三个组成部分）进行。磁盘控制器则直接使磁头部件步进到相应的柱面，选通相应的磁头，等待要求的扇区移动到磁头下。在扇区到来时，磁盘控制器读出每个扇区的头标，把这些头标中的地址信息与期待检出的磁头和柱面号做比较（即寻道），然后，寻找要求的扇区号。待磁盘控制器找到该扇区头标时，根据其任务是写扇区还是读扇区，来决定是转换写电路，还是读出数据和尾部记录。找到扇区后，磁盘控制器必须在继续寻找下一个扇区之前对该扇区的信息进行后处理。如果是读数据，控制器计算此数据的ECC码，然后，把ECC码与已记录的ECC码相比较。如果是写数据，控制器计算出此数据的ECC码，与数据一起存储。在控制器对此扇区中的数据进行必要处理期间，磁盘继续旋转。由于对信息的后处理需要耗费一定的时间，在这段时间内，磁盘已转了相当的角度。交叉因子的确定是一个系统级的问题。一个特定硬盘驱动器的交叉因子取决于：磁盘控制器的速度、主板的时钟速度、与控制器相连的输出总线的操作速度等。如果磁盘的交叉因子值太高，就需多花一些时间等待数据在磁盘上存入和读出。如果交叉因子值太低，就会大大降低磁盘性能。前面已经述及，系统在磁盘上写入信息时，写满一个磁道后转到同一柱面的下一个磁头，当柱面写满时，再转向下一柱面。从同一柱面的一个磁道到另一个磁道，从一个柱面转到下一个柱面，每一个转换都需要时间，在此期间磁盘始终保持旋转，这就会带来一个问题：假定系统刚刚结束对一个磁道前一个扇区的写入，并且已经设置了最佳交叉因子比值，现在准备在下一磁道的第一扇区写入，这时，必须等到磁头转换好，让磁头部件重新准备定位在下一道上。如果这种操作占用的时间超过了一点，尽管是交叉存取，磁头仍会延迟到达。这个问题的解决办法是以原先磁道所在位置为基准，把新的磁道上全部扇区号移动约一个或几个扇区位置，这就是磁头扭斜。磁头扭斜可以理解为柱面与柱面之间的交叉因子，已由生产厂设置好，用户一般不用去改变它。磁头扭斜的更改比较困难，但是，它们只在文件很长、超过磁道结尾进行读出和写入时才发挥作用，所以，扭斜设置不正确所带来的时间损失比采用不正确的扇区交叉因子值带来的损失要小得多。交叉因子和磁头扭斜可用专用工具软件来测试和更改。更具体的内容这里就不再详述，毕竟现在很多用户都没有见过这些参数。扇区号存储在扇区头标中，扇区交叉因子和磁头扭斜的信息也存放在这里。最初，硬盘低级格式化程序只是行使有关磁盘控制器的专门职能来完成设置任务。由于这个过程可能破坏低级格式化的磁道上的全部数据，也极少采用。扇区交叉因子由写入到扇区头标中的数字设定，所以，每个磁道可以有自己的交叉因子。在大多数驱动器中，所有磁道都有相同的交叉因子。但有时因为操作上的原因，也可能导致各磁道有不同的扇区交叉因子。如在交叉因子重置程序工作时，由于断电或人为中断，就会造成一些磁道的交叉因子发生了改变，而另一些磁道的交叉因子没有改变。这种不一致性对计算机不会产生不利影响，只是有最佳交叉因子的磁道要比其他磁道的工作速度更快。转自https://is.gd/jwgyUi