U盘枚举(自己总结)

2024-05-31

U盘枚举(自己总结)(精选3篇)

篇1:U盘枚举(自己总结)

插入U盘

直接拔出

安全拔出

A9枚举

Linux USB gadget设备驱动解析(2)---驱动调试 作者:刘洪涛, 华清远见嵌入式学院金牌讲师。

这一节主要把在实现“linuxU盘功能”过程中的一些调试过程记录下来,并加以解析。

一、背景知识

1、USB Mass Storage类规范概述

USB 组织在universal Serial Bus Mass Storage Class Spaceification 1.1版本中定义了海量存储设备类(Mass Storage Class)的规范,这个类规范包括四个

独立的子类规范,即:

1.USB Mass Storage Class Control/Bulk/Interrupt(CBI)Transport 2.USB Mass Storage Class Bulk-Only Transport 3.USB Mass Storage Class ATA Command Block 4.USB Mass Storage Class UFI Command Specification 前 两个子规范定义了数据/命令/状态在USB 上的传输方法。Bulk-Only 传输规范仅仅使用Bulk 端点传送数据/命令/状态,CBI 传输规范则使用Control/Bulk/Interrupt 三种类型的端点进行数据/命令/状态传送。后两个子规范则定义了存储介质的操作命令。ATA 命令规范用于硬盘,UFI 命令规范是针对USB 移动存储。Microsoft Windows 中提供对Mass Storage 协议的支持,因此USB 移动设备只需要遵循 Mass Storage 协议来组织数据和处理命令,即可实现与PC 机交换数据。而Flash 的存储单元组织形式采用FAT16 文件系统,这样,就可以直接在Windows的浏览器中通过可移动磁盘来交换数据了,Windows 负责对FAT16 文件系统的管理,USB 设备不需要干预FAT16 文件系统操作的具体细节。

USB(Host)唯一通过描述符了解设备的有关信息,根据这些信息,建立起通信,在这 些描述符中,规定了设备所使用的协议、端点情况等。因此,正确地提供描述符,是USB 设备正常工作的先决条件。

Linux-2.6.26内核中在利用USB gadget驱动实现模拟U盘时主要涉及到file_storage.c、s3c2410_udc.c等驱动文件(这些文件的具体结构,将在下一篇文章中 描述)。此时我们想先从这些代码中找到USB描述描述符,从中确定使用的存储类规范,从而确定协议。确定通讯协议是我们调试的基础。存储类规范是由接口描述符决定的。接口描述符各项的定义义如下:

其中,bInteaceClass、bInterfaceSubClass、bInterfaceProtocol可以判断出设备是否是存储类,以及属于哪种存储子类和存储介质的操作命令。在file_storage.c文件中,/* USB protocol value = the transport method */ #define USB_PR_CBI 0x00 // Control/Bulk/Interrupt #define USB_PR_CB 0x01 // Control/Bulk w/o interrupt #define USB_PR_BULK 0x50 // Bulk-only /* USB subclass value = the protocol encapsulation */ #define USB_SC_RBC 0x01 // Reduced Block Commands(flash)#define USB_SC_8020 0x02 // SFF-8020i, MMC-2, ATAPI(CD-ROM)#define USB_SC_QIC 0x03 // QIC-157(tape)#define USB_SC_UFI 0x04 // UFI(floppy)#define USB_SC_8070 0x05 // SFF-8070i(removable)#define USB_SC_SCSI 0x06 // Transparent SCSI 默认的情况是:

mod_data = { // Default values.transport_parm = “BBB”,.protocol_parm = “SCSI”, „„

默认的赋值如下:

bInterfaceClass=08 表示:存储类

bInterfaceSubClass=0x06 表示:透明的SCSI指令 bInterfaceProtocol=0x50 表示:bulk-only 传输

2、Bulk-Only 传输协议

下面看看Bulk-Only 传输协议:(详细的规范请阅读《Universal Serial BusMass Storage ClassBulk-Only Transport》)

设 备插入到USB 后,USB 即对设备进行搜索,并要求设备提供相应的描述符。在USBHost 得到上述描述符后,即完成了设备的配置,识别出为Bulk-Only 的Mass Storage 设备,然后即进入Bulk-Only 传输方式。在此方式下,USB 与设备间的所有数据均通过Bulk-In和Bulk-Out 来进行传输,不再通过控制端点传输任何数据。

在 这种传输方式下,有三种类型的数据在USB 和设备之间传送,CBW、CSW 和普通数据。CBW(Command Block Wrapper,即命令块包)是从USB Host 发送到设备的命令,命令格式遵从接口中的bInterfaceSubClass 所指定的命令块,这里为SCSI 传输命令集。USB设备需要将SCSI 命令从CBW 中提取出来,执行相应的命令,完成以后,向Host 发出反映 当前命令执行状态的CSW(Command Status Wrapper),Host 根据CSW 来决定是否继续发 送下一个CBW 或是数据。Host 要求USB 设备执行的命令可能为发送数据,则此时需要将 特定数据传送出去,完毕后发出CSW,以使Host 进行下一步的操作。USB 设备所执行的操

作可用下图描述:

CBW的格式如下:

dCBWSignature:

CBW的标识,固定值:43425355h(little endian)。dCBWTag:

主机发送的一个命令块标识,设备需要原样作为dCSWTag(CSW中的一部分)再发送给Host;主要用于关联CSW到对应的CBW。dCBWDataTransferLength:

本次CBW命令要求在命令与回应之间传输的字节数。如果为0,则不传输数据。bmCBWFlags:

反映数据传输的方向,0 表示来自Host,1 表示发至Host; bCBWLUN:

对于有多个LUN逻辑单元的设备,用来选择具体目标。如果没有多个LUN,则写0。

bCBWCBLength:

命令的长度,范围在0~16.CBWCB:

传输的具体命令,符合bInterfaceSubClass.中定义的命令规范,此处是SCSI CSW命令格式如下:

dCSWSignature:

CSW的标识,固定值:53425355h(little endian)dCSWTag:

设置这个标识和CBW中的dCBWTag一致,参照上面关于dCBWTag的解释 dCSWDataResidue:

还需要传送的数据,此数据根据dCBWDataTransferLength-本次已经传送的数据得到

bCSWStatus:

指示命令的执行状态。如果命令正确执行,bCSWStatus 返回0 即可。

3、SCSI指令集

Bulk-Only 的CBW 中的CBWCB 中的内容即为如下格式的命令块描述符(Command Block Descriptor)。SCSI-2 有三种字长的命令,6 字节、10字节和12字节,Microsoft Windows 环境下支持12 字节长的命令。

Operation Code:

操作代码,表示特定的命令。高3 位为Group Code,共有8 种组合,即8 个组,低5 五位为Command Code,可以有32 种命令。Logicol unit Number:

为了兼容SCSI-1 而设的,此处可以不必关心。Logical block address:

为高位在前,低位在后的逻辑块地址,即扇区地址。第2 位为高位,第3、4、5 依次为低位。

Transfer length:

为需要从逻辑块地址处开始传输的扇区数(比如在Write 命令中)。Parameter list length:

为需要传输的数据长度(比如在Mode Sense 命令中); Allocation length:

为初始程序为返回数据所分配的最大字节数,此值可以为零,表示不需要传送数据。

SCSI指令集的Direct Accesss 类型存储介质的传输命令有许多,Mass Storage协议只用到了其中的一些。更多的SCSI指令参见:http://en.wikipedia.org/wiki/SCSI_command 指令代码 指令名称 说明

04h Format Unit 格式化存储单元 12h Inquiry 索取器件信息 1Bh Start/Stop load/unload 55h Mode select 允许Host对外部设备设置参数。5Ah Mode Sense 向host传输参数 Eh Prevent/Allow Medium Removal 写保护

>28h Read(10)Host读存储介质中的二进制数据 A8h Read(12)同上,不过比较详细一点 25h Read Capacity 要求设备返回当前容量

23h Read Format Capacity 查询当前容量及可用空间 03h Request Sense 请求设备向主机返回执行结果,及状态数据

01h Rexero Unit 返回零轨道 2Bh Seek(10)为设备分配到特定地址 1Dh Send Diagnostic 执行固件复位并执行诊断

00h Test Unit Ready 请求设备报告是否处于Ready状态 2Fh Verify 在存储中验证数据

2Ah Write(10)从主机向介质写二进制数据 AAh Write(12)同上,不过比较详细 2Eh Write and Verify 写二进制数据并验证

对于不同的命令,其命令块描述符略有不同,其要求的返回内容也有所不同,根据相 应的文档,可以对每种请求作出适当的回应。比如,下面是INQUIRY 请求的命令块描述符和其返回内容的数据格式:如:INQUIRY 命令描述符:

返回数据格式

Host 会依次发出INQUIRY、Read Capacity、UFI Mode Sense 请求,如果上述请求的返回结果都正确,则Host 会发出READ 命令,读取文件系统0 簇0 扇区的MBR 数据,进入文件系统识别阶段。

4、利用USB View观察结果

可通过USB View软件查看到USB设置阶段获取到的信息。

二、出现的主要问题

在调试过程中遇到了一个问题。现象是:在目标板加载完驱动后,即执行完: # insmod g_file_storage.ko file=“/dev/mtdblock2” stall=“0” removable=“1” 后,接好USB线。此时在windows端设备出有usb storage设备加入,但出现不了盘符。

下面记录下调试过程。

三、调试过程

根据规范,当完成SCSI指令集中Inquiry 命令时,可以出现盘符。所以可以通过bushound软件查看通讯过程,找出原因。下面是利用bushound工具在出现问题时采集到的数据。

Dev Phase Data Info Time Cmd.Phase.Ofs------------------------------------26 CTL 80 06 00 0100 00 00 1012 03 01 02........%.......4.8ms 1.2.0 03 01..1.2.16 26 CTL 80 06 00 0201 01 04 c000 00 20 00 GET DESCRIPTR 16us 3.1.0 26 DI 09 02 20 0001 09 04 0081 02 40 0002 40 00 00 P.....@......@..3.2.16 26 CTL 80 06 00 0301 01 04 c000 00 04 00 GET DESCRIPTR 15us 5.1.0 26 DI 04 03 09 04....3.9ms 6.1.0 26 CTL 80 06 03 0309 04 1a 00 GET DESCRIPTR 18us 7.1.0 26 DI 1a 03 33 0030 00 34 0037 00 37 0000 00 00 00 SET CONFIG 16us 8.1.0 26 CTL 01 0b 00 0000 00 01 00 CLASS 62ms 10.1.0 26 DI 00.3.9ms 10.2.0 26 DO 55 53 42 4324 00 00 0000 00 00 0000 00 00...$...........11.1.16 26 DI 00 80 02 024c 69 6e 752d 53 74 6f64 67 65 74 File-Stor Gadget 12.1.16 30 33 31 32 0312 12.1.32 26 CTL 80 06 00 0201 01 04 c000 02 08 06...............4.1ms 13.2.0 50 05 07 0500 07 05 0200 00 20 00 GET DESCRIPTR 2.7sc 14.1.0 26 DI 09 02 20 0001 09 04 0081 02 40 0002 40 00 00 P.....@......@..14.2.16 26 USTS 05 00 00 c0 no response 2.8sc 15.1.0 注意上面红色部分的代码,DO发出了55 53 42 43开 始的CBW命令块,命令码是12,即Inquiry命令。要求目标返回Inquiry命令要求的数据,长度是0x24。接下来设备端通过DI返回了设备信 息。按照规范,在返回完了数据后,设备端还应该通过DI向系统返回CSW的值。但实际的捕获内容并没有。所以导致不能正确出现盘符。

在file_storage.c中,发送数据时都会调用到start_transfer()函数。在此函数中加入printk调试语句,观察现象。发现只要加入的调试语句,windows端就能够正常设别设备了。于是,可以猜测是因为需要在连续 两次发送之间加上一些延时。在函数中加入udelay(800)后,windows系统可以正常发现设备了。具体的代码架构,将在下一遍文章中解析。下面是程序正常后,用bushound捕获到的数据。

红色部分,可以看出设备正确的按照规范在发送完数据后,返回CSW信息。

四、总结做好USB gadget驱动、或者USB host驱动调试需要: ·掌握一定的知识基础

包括:USB协议、具体的类设备规范、USB驱动程序架构、USB设备端控制器操作等。·合理利用调试工具。

包括:USB view、bushound、及一些硬件USB信号分析仪。

一、追踪USB大容量设备的实现流程

1、从main.c开始

(1)main函数的执行流程

Set_System();//设置时钟、端口等。

Set_USBClock();//设置usb的时钟

USB_Interrupts_Config();//设置中断

Led_Config();//设置所使用的到的灯。

MSD_Init();//SD卡初始化

Get_Medium_Characteristics();//获取SD块总数、每块字节数。

USB_Init();//USB_init.c提供的初始化函数。从这里开始USB设备被主机检测到。

while(1)

{ //USB的工作都是在中断中完成的,主执行流程什么也没做。

}

(2)与鼠标例程不同的地方

在中断配置中,使能了USB高优先级中断。

NVIC_InitStructure.NVIC_IRQChannel= USB_HP_CAN_TX_IRQChannel;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

用到了几个灯指示,这个我的开发板上用不到,就不详细看了。

MSD_Init(),是对SD卡进行初始化。该函数在msd.c中,我看了一下它的SD卡实现的代码,比我的SD函数代码齐整多了。以后有时间要把我的USB驱动好好的整理一下。不过现在就先不管了。

接下来这个函数获取SD卡的容量,这样的函数我在SD卡驱动中也实现了,改变一下调用方式就行了。

USB_Init()函数在usb_init.c库函数中,但它最终会调用user_prop.c宏的用户初始化例程。下面就追踪进去看一看。

(3)大容量存储设备的初始化

void MASS_init()

{ pInformation->Current_Configuration = 0;

PowerOn();连接电缆主机很快发总线复位。

_SetISTR(0);

wInterrupt_Mask = IMR_MSK;

_SetCNTR(wInterrupt_Mask);开启复位和传输中断。

pInformation->Current_Feature = MASS_ConfigDescriptor[7];

while(pInformation->Current_Configuration == 0)

{

NOP_Process();

}

bDeviceState = CONFIGURED;//这句执行完成后,设备处于已配置状态。我先在这里加一句调试语句。

#if usb_debug

Uart_PutString(“设备已配置”);

#endif

}

2、进入复位中断

(1)先列出中断处理代码

发生总线复位中断以后,处理是在usb_prop.c的Mass_Reset()函数中完成的。

void MASS_Reset(){

Device_Info.Current_Configuration = 0;

SetBTABLE(BTABLE_ADDRESS);

SetEPType(ENDP0, EP_CONTROL);//端点0控制端点

SetEPTxStatus(ENDP0, EP_TX_NAK);//不响应IN

SetEPRxAddr(ENDP0, ENDP0_RXADDR);//设置接收缓冲区(OUT)

SetEPRxCount(ENDP0, Device_Property.MaxPacketSize);接收长度。

SetEPTxAddr(ENDP0, ENDP0_TXADDR);//发送缓冲区(IN)

Clear_Status_Out(ENDP0);

SetEPRxValid(ENDP0);//使能端点0的接收。

SetEPType(ENDP1, EP_BULK);//端点1批量模式

SetEPTxAddr(ENDP1, ENDP1_TXADDR);//设置发送缓冲区(IN)

SetEPTxStatus(ENDP1, EP_TX_NAK);发送不响应。

SetEPRxStatus(ENDP1, EP_RX_DIS);//接收无效。对OUT无效

SetEPType(ENDP2, EP_BULK);//端点2批量模式

SetEPRxAddr(ENDP2, ENDP2_RXADDR);//设置接收缓冲区OUT

SetEPRxCount(ENDP2, Device_Property.MaxPacketSize);

SetEPRxStatus(ENDP2, EP_RX_VALID);

SetEPTxStatus(ENDP2, EP_TX_DIS);//发送无效,对IN无效

SetDeviceAddress(0);//使能USB接口模块。

CBW.dSignature = BOT_CBW_SIGNATURE;

Bot_State = BOT_IDLE;//命令状态机初始化为空闲状态

}

在这里没有我没有看到将批量端点设置为双缓冲模式的迹象,难道这个例程没有用它?

3、进入枚举过程

因为在鼠标例程中已经详细分析过枚举过程,这里主要是大容量设备枚举过程中不同的地方做一下分析。

(1)获取设备描述符、设置地址。

(2)获取配置描述符

(3)获取配置描述符集合,这里主要讲接口描述符分析一下。

0x09, /* bLength: Interface Descriptor size */

0x04, /* bDescriptorType: */

0x00, /* bInterfaceNumber: Number of Interface */

0x00, /* bAlternateSetting: Alternate setting */

0x02, /* bNumEndpoints*/ 使用两个端点

0x08, /* bInterfaceClass: MASS STORAGE Class,大容量存储类 */

0x06, /* bInterfaceSubClass : SCSI transparent,SCSI传输*/

0x50, /* nInterfaceProtocol,仅批量传输*/ 4, /* iInterface: */

(4)获取字符串描述符

(5)类请求实现:

类获取逻辑盘:

一般返回0

类请求复位:

ClearDTOG_TX(ENDP1);

ClearDTOG_RX(ENDP2);

CBW.dSignature = BOT_CBW_SIGNATURE;

Bot_State = BOT_IDLE;

(6)设置配置

在用户设置的回调函数中,又调用

void Mass_Storage_SetConfiguration(void)

{

if(pInformation->Current_Configuration)

{

ClearDTOG_TX(ENDP1);

ClearDTOG_RX(ENDP2);

Bot_State = BOT_IDLE;}

} 这个工作前面已经做过了。

4、主机发命令INQUIRY

(1)首先进入批量输出中断

该中断的回调函数调用Mass_Storage_Out()进行处理。

(2)追踪进入Mass_Storage_Out()

void Mass_Storage_Out(void)

{

u8 CMD;

CMD = CBW.CB[0];//

Data_Len = GetEPRxCount(ENDP2);

PMAToUserBufferCopy(Bulk_Data_Buff,ENDP2_RXADDR, Data_Len);

switch(Bot_State)

{

case BOT_IDLE:

CBW_Decode();//第一次收到命令肯定调用这个解码函数。

break;//它的作用应该是填充CBW命令块封包结构

case BOT_DATA_OUT:

if(CMD == SCSI_WRITE10)

{

SCSI_Write10_Cmd();

break;

}

}

(3)追踪进入CBW_Decode()

这个函数的代码较长,我就不列举在这里了,我就分析一下本次的主要工作。

首先将用户缓冲区的数据复制到命令封包结构里面。

然后准备好状态封包结构:

CSW.dTag = CBW.dTag;//这个标志由主机生成,可以用于检查设备是否正确收到该命令。

CSW.dDataResidue = CBW.dDataLength;

然后主要是根据命令操作码,调用相应的SCSI命令处理函数。

switch(CBW.CB[0])

{

case SCSI_REQUEST_SENSE:

SCSI_RequestSense_Cmd();

break;

case SCSI_INQUIRY:

SCSI_Inquiry_Cmd();

break;

我这里就列出了两项,实际的命令是很多的。本次主要是查询处理。

(4)追踪进入SCSI_Inquiry_Cmd()

以上函数是在usb_bot.c里面,现在跳转到usb_scsi.c里面。

这个函数的主要工作是调用Transfer_Data_Request(Inquiry_Data, Inquiry_Data_Length)来完成。

这个Inquiry_Data = Standard_Inquiry_Data,后面这个Standard_Inquiry_Data是scsi_data.c里面定义的一个数据结构,专门用于inquiry命令的返回。

u8 Standard_Inquiry_Data[] =

{

0x00, /* Direct Access Device */

0x80, /* RMB = 1: Removable Medium */

0x02, /* Version: No conformance claim to standard */

0x02, //这里圈圈的书上说应该为 0x01

36BULK_MAX_PACKET_SIZE;

Block_offset = BULK_MAX_PACKET_SIZE;

}

else

{

UserToPMABufferCopy(Data_Buffer + Block_offset, ENDP1_TXADDR, BULK_MAX_PACKET_SIZE);

Block_Read_count-= BULK_MAX_PACKET_SIZE;

Block_offset += BULK_MAX_PACKET_SIZE;

}

SetEPTxCount(ENDP1, BULK_MAX_PACKET_SIZE);SetEPTxStatus(ENDP1, EP_TX_VALID);

Memory_Offset += BULK_MAX_PACKET_SIZE;

Transfer_Length-= BULK_MAX_PACKET_SIZE;//剩下的需要传输的字节数。

CSW.dDataResidue-= BULK_MAX_PACKET_SIZE;

Led_RW_ON();

}

这里不清楚的是主机是一次把512字节读完,还是每次发一个命令读取64字节。我觉得应该是发一次读命令,8次“IN”读取一个扇区,再发一个“IN”读取命令状态封包。

8、写命令WRITE(10)

这个命令的处理过程跟读命令的处理差不多,只是最后它会调用Write_Memory()进行处理。

i = 0;

for(;Counter < temp;Counter++)

{

Data_Buffer[Counter] = Bulk_Data_Buff[i];

i++;

}

从接受缓冲区得到的数据总是先放到用户缓冲区,这个缓冲区有512个字节。

if(!(Transfer_Length % 512))

{

Counter = 0;

MSD_WriteBlock(Data_Buffer, Memory_OffsetInquiry之后会发出ReadFormatCapacity命令,这个命令在SCSI规范中是“厂家自定义命令”,可以参考UFI命令集文档(实际上,U盘所使用的所有SCSI命令集都可以参考UFI文档,它比SCSI标准文档更简洁明了)。注意这个命令在BusHound里是没有描述的,必须在“Device”选项页里勾选上这个U盘所对应的USB Mass Storage Device这个节点,才能看到这个命令的数据流。

-ReadFormatCapacity之后会发出ReadCapacity命令。

-U盘读数据(读扇区)时会发送Read(10)。ReadCapacity完成后就会发送Read(10)读取U盘的第一个扇区。

-U盘写数据时(写扇区)会发送Write(10)。

-TestUnitReady会在无其他数据传输时会定时发送,如果设备没有回应成功的CSW给主机,则主机认为设备已不存在。此时如果再双击磁盘图标,Windows会提示“请插入磁盘”。RequestSense:如果CSW指示此次传输不成功,那么主机会发出此请求。ModeSense6/10这两个命令可以不支持(不支持不代表不反应,任何一个命令你都要做出反应,对于不支持的命令,可以通过STALL握手来向主机表明),暂时也未遇到过什么异常情况,而且我查看过一些U盘,有相当一部分就是随便回了几个数据给主机。这两个命令只会在U盘插入后发送一次,此后不再发送。

U盘开发的几点体会

如果你开发过USB相关项目,理解USB的一些基本概念,例如设备描述符、配置描述符、子类规范等,那么开发U盘只要概念清晰应该不难。以下是我开发过程中的几个相关步骤:

       保证USB 芯片正常工作,用其他USB成功项目验证硬件连接及固件的正确性

按Mass Storage协议 Bulk-Only 模式提供描述符,使PC 机控制面板上设备类型出现Mass Storage Device 响应SCSI指令集中Inquiry 命令,可以出现盘符 实现FAT16文件系统

处理SCSI命令集中READ命令及其他UFI命令,可以访问盘符 处理SCSI命令集中WRITE命令 U盘开发成功

开发U盘有三个工具软件应该必备:USBVIEW 察看设备描述符,端点测试等;BUSHOUND 截取USB总线数据,可分析UFI命令及U盘返回的数据流;串口助手可实时了解U盘所收命令流及程序流程由于每个人知识面不同,我想实现上面的几个步骤遇到的问题也不一样。对我最大的困惑是实现FAT16文件系统,直到在微软网站找到它的白皮书才算解惑。这里简介一下方便大家有的放矢。USB 组织定义了海量存储设备类(Mass Storage Class)的规范,这个类规范包括四个独立的子类规范,即:

1.USB Mass Storage Class Control/Bulk/Interrupt(CBI)Transport 2.USBMass Storage Class Bulk-Only Transport 3.USB Mass Storage Class ATA Command Block 4.USB Mass Storage Class UFI Command Specification。

前两个子规范定义了数据/命令/状态在USB 上的传输方法。Bulk-Only 传输规范仅仅使用Bulk 端点传送数据/命令/状态,CBI 传输规范则使用Control/Bulk/Interrupt三种类型的端点进行数据/命令/状态传送。后两个子规范则定义了存储介质的操作命令。ATA 命令规范用于硬盘,UFI 命令规范是针对USB 移动存储。

Windows95 OSR2和Windows 98开始支持FAT32 文件系统,它是对早期DOS的FAT16文件系统的增强,由于文件系统的核心--文件分配表FAT由16位扩充为32位,所以称为FAT32文件系统。在一逻辑盘(硬盘的一分区)超过 512 兆字节时使用这种格式,会更高效地存储数据,减少硬盘空间的浪费,一般还会使程序运行加快,使用的计算机系统资源更少,因此是使用大容量硬盘存储文件的极有效的系统。本人对Windows 98下的FAT32 文件系统做了分析实验,总体上与FAT16文件系统变化不大,现将有关变化部分简介如下:

(一)FAT32 文件系统将逻辑盘的空间划分为三部分,依次是引导区(BOOT区)、文件分配表区(FAT区)、数据区(DATA区)。引导区和文件分配表区又合称为系统区。

(二)引导区从第一扇区开始,使用了三个扇区,保存了该逻辑盘每扇区字节数,每簇对应的扇区数等等重要参数和引导记录。之后还留有若干保留扇区。而FAT16文件系统的引导区只占用一个扇区,没有保留扇区。

(三)文件分配表区共保存了两个相同的文件分配表,因为文件所占用的存储空间(簇链)及空闲空间的管理都是通过FAT实现的,FAT如此重要,保存两个以便第一个损坏时,还有第二个可用。文件系统对数据区的存储空间是按簇进行划分和管理的,簇是空间分配和回收的基本单位,即,一个文件总是占用若干个整簇,文件所使用的最后一簇剩余的空间就不再使用,而是浪费掉了。

从统计学上讲,平均每个文件浪费0.5簇的空间,簇越大,存储文件时空间浪费越多,利用率越低。因此,簇的大小决定了该盘数据区的利用率。FAT16系统簇号用16位二进制数表示,从0002H到FFEFH个可用簇号(FFF0H到FFFFH另有定义,用来表示坏簇,文件结束簇等),允许每一逻辑盘的数据区最多不超过FFEDH(65518)个簇。FAT32系统簇号改用32位二进制数表示,大致从00000002H到FFFFFEFFH个可用簇号。FAT表按顺序依次记录了该盘各簇的使用情况,是一种位示图法。每簇的使用情况用32位二进制填写,未被分配的簇相应位置写零;坏簇相应位置填入特定值;已分配的簇相应位置填入非零值,具体为:如果该簇是文件的最后一簇,填入的值为FFFFFF0FH,如果该簇不是文件的最后一簇,填入的值为该文件占用的下一个簇的簇号,这样,正好将文件占用的各簇构成一个簇链,保存在FAT表中。0000000H、00000001H两簇号不使用,其对应的两个DWORD位置(FAT表开头的8个字节)用来存放该盘介质类型编号。FAT表的大小就由该逻辑盘数据区共有多少簇所决定,取整数个扇区。

(四)FAT32系统一簇对应8个逻辑相邻的扇区,理论上,这种用法所能管理的逻辑盘容量上限为16TB(16384GB),容量大于16TB时,可以用一簇对应16个扇区,依此类推。FAT16系统在逻辑盘容量介于128MB到256MB时,一簇对应8个扇区,容量介于256MB到512MB时,一簇对应16个扇区,容量介于512MB到1GB时,一簇对应32个扇区,容量介于1GB到2GB时,一簇对应32个扇区,超出2GB的部分无法使用。显然,对于容量大于512MB的逻辑盘,采用FAT32的簇比采用FAT16的簇小很多,大大减少了空间的浪费。

但是,对于容量小于512MB的盘,采用FAT32虽然一簇8个扇区,比使用FAT16一簇16个扇区,簇有所减小,但FAT32的FAT表较大,占用空间较多,总数据区被减少,两者相抵,实际并不能增加有效存储空间,所以微软建议对小于512M的逻辑盘不使用FAT32。

另外,对于使用FAT16文件系统的用户提一建议,硬盘分区时,不要将分区(逻辑盘)容量正好设为某一区间的下限,例:将一逻辑盘容量设为1100M(稍大于1024M),则使用时其有效存储容量比分区为950M的一般还少,因其簇大一倍,浪费的空间较多。还有,使用FDISK等对分区指定容量时,由于对1MB的定义不一样(标准的二进制的1MB为1048576B,有的系统将1MB理解为1000000B,1000KB等),及每个分区需从新磁道开始等因素,实际分配的容量可能稍大于指定的容量,亦需注意掌握。

(五)根目录区(ROOT区)不再是固定区域、固定大小,可看作是数据区的一部分。因为根目录已改为根目录文件,采用与子目录文件相同的管理方式,一般情况下从第二簇开始使用,大小视需要增加,因此根目录下的文件数目不再受最多512的限制。FAT16文件系统的根目录区(ROOT区)是固定区域、固定大小的,是从FAT区之后紧接着的32个扇区,最多保存512个目录项,作为系统区的一部分。

(六)目录区中的目录项变化较多,一个目录项仍占32字节,可以是文件目录项、子目录项、卷标项(仅跟目录有)、已删除目录项、长文件名目录项等。目录项中原来在DOS下保留未用的10个字节都有了新的定义,全部32字节的定义如下:

(1)0--7字节 文件正名。(2)8--10字节 文件扩展名。

(3)11字节 文件属性,按二进制位定义,最高两位保留未用,0至5位分别是只读位、隐藏位、系统位、卷标位、子目录位、归档位。

(4)12--13字节 仅长文件名目录项用,用来存储其对应的短文件名目录项的文件名字节校验和等。(5)14--15字节 24位二进制的文件建立时间,其中的高5位为小时,次6位为分钟。

(6)16--17字节 16位二进制的文件建立日期,其中的高7位为相对于1980年的年份值,次4位为月份,后5位为月内日期。

(7)18--19字节 16位二进制的文件最新访问日期,定义同(6)。(8)20--21字节 起始簇号的高16位。

(9)22--23字节 16位二进制的文件最新修改时间,其中的高5位为小时,次6位为分钟,后5位的二倍为秒数。

(10)24--25字节 16位二进制的文件最新修改日期,定义同(6)。(11)26--27字节 起始簇号的低16位。(12)28--31字节 32位的文件字节长度。

其中第(4)至(8)项为以后陆续定义的。对于子目录项,其(12)为零;已删除目录项的首字节值为E5H。在可以使用长文件名的FAT32系统中,文件目录项保存该文件的短文件名,长文件名用若干个长文件名目录项保存,长文件名目录项倒序排在文件短目录项前面,全部是采用双字节内码保存的,每一项最多保存十三个字符内码,首字节指明是长文件名的第几项,11字节一般为0FH,12字节指明类型,13字节为校验和,26--27字节为零。

(七)以前版本的 Windows 和DOS与 FAT32 不兼容,不能识别FAT32分区,有些程序也依赖于 FAT16文件系统,不能和 FAT32 驱动器一道工作。将硬盘转换为 FAT32,就不能再用双引导运行以前版本的Windows(Windows 95 [Version 4.00.950]、Windows NT 3.x、Windows NT 4.0 和 Windows 3.x)。

磁盘结构综述 1.硬盘结构

硬盘的内部是由圆形金属片堆叠起来的,每个盘片的两面都有一个磁头(Head)负责读写这个磁面(Side),在每个磁面上划分了一圈一圈的同心圆,叫做柱面(Cylinder)对于软盘通常称之为磁道,在每个柱面中又划分了若干段,称之为扇区(Sector)。由于技术的发展,硬盘的密度越来越大,使得硬盘的实际盘片数越来越少,对磁盘操作的柱面、磁头、扇区被硬盘控制器内部转换,已经不是实际的柱面、磁头、扇区了。由于最早时磁盘存取系统估计不足,传输数据时只给扇区留了6位,柱面留了10位,磁头留了8位。也就是说,柱面最大只能为1023。但是大硬盘的柱面远大于这个数,所以后来就采用将柱面数减少,将磁头数增加的方式来满足磁盘寻址的要求,对于实际地址的转换在BIOS中进行,这叫逻辑块寻址方式(Logical Block Addressing,LBA)硬盘中有关柱面、磁头、扇区的数据都是以此为基准的。

篇2:U盘枚举(自己总结)

首先需要准备的工具:1.U盘、闪存卡、移动硬盘

2.软件:UISO9,win7系统ISO文件。

由于win7 ISO文件大小不一,最小的32位系统单一版的也需要2.42GB容量,所以在准备移动存储产品上,起步容量要从4GB,另一种包括32位与64位的容量 在4GB左右,因为像U盘这些产品虽然容量为4GB,但格完后只会剩下3.7GB左右,所以你的移动存储产品容量达到8GB,否则将不够安装那么就可以安 装多版本的启动文件。

软件工具方面选择的是这个UltraISO软碟通,它是一款功能强大而又方便实用的软碟文件制作/编辑/转换工具,它可以直接编辑软碟文件和从 软碟中提取文件,也可以从CD-ROM直接制作软碟或者将硬盘上的文件制作成ISO文件。同时,你也可以处理ISO文件的启动信息,从而制作可引导光盘。 使用UltraISO,你可以随心所欲地制作/编辑软碟文件,配合光盘刻录软件烧录出自己所需要的光碟。

那么下面就开始正式介绍做系统盘的工序了,其实方法简单到你都不相信,仅仅只需要一部的工序就可以搞定了。

首先我们先拿U盘来做一个示范,在电脑上插入U盘后,双击打开UltraISO软碟通,就会出现下面的程序框,点击文件—打开,查找你ISO文件所处位置,双击既可,就会将ISO文件引入到这个程序之中。

下图就是将windows7系统ISO文件引入到程序中后的界面效果,上半部就是ISO文件,下半部就是让你选择将这个文件引入哪个硬盘中,这时你要选择的就是点击你的U盘盘符,

本文来自玛雅部落

当一切准备就绪后,点击上方的启动,就会开始在你的U盘中写入文件,在这之前程序还会提示你“写入文件后,原来的文件都将消失,是否继续”,这 也是要对大家讲清楚的一点,用这些移动存储产品做系统盘的话,之前的文件都会消失,如果你

的U盘中又很重要的文件一定要实先转移出来

在一切都搞定后就是一段等待的时间,然后一个新的系统安装盘就这样做好了,是不是很简单,当然闪存卡和移动硬盘的制作工序与U盘是一摸一样的,另外虽然在安装时会把之前的文件全部删除,但是写入后你的移动存储产品的剩余空间还是可以利用的,这点不需要担心。

做好了系统安装盘,下面要做的就是安装了,首先要对BIOS进行一个小小的改动,一般BIOS都是设置硬盘启动或者光驱启动,我们要将其改为USB启动。

BIOS设置移动存储首先引导:

下面,我们以设置移动硬盘为首引导设备为例进行讲解:打开计算机之后,按DEL键进入Award BIOS设置程序,大家会看到如下的界面:

选择第二行Advanced BIOS Features(高级BIOS设置),按回车进入以下界面:

首先,确保上图中第二行(主板不同,位置不一样)First Boot Device后面的设置为,也就是首先从硬盘引导。然后在第一行Hard Disk Boot Priority后的上敲回车。在这里设置当你有多个硬盘时,设置具体哪一个硬盘为首先引导的设备。在这里一定要搞清楚和First Boot Device的区别。

敲击回车之后,我们会看到如上图的列表,列表中的USB-HDD0:Lenovo USB Hard Drive 2.0就是我们连接到计算机上的移动硬盘。所以,我们需要将它的位置设为第一个,也就是首先从移动硬盘引导,而不是WDxxxx、STxxxx。

篇3:打造自己的优质U盘

数据完整性校验

下载地址:http://t.cn/zlBFgc5

用户有时会发现,在购买U盘时,说不定什么时候就遭遇了传说中的缩水U盘。360安全卫士等安全套装均有检测U盘真实容量的功能,360真实容量检测工具通过的U盘,虽然容量上没什么问题,但是用户每次试图往U盘中存储体积较大的文件时,几乎每次都会得到文件损坏的提示,实际这是由于闪存中出现了坏块所导致的。

此时我们就可以使用MyDiskTest的数据完整性校验功能来测试闪存是否有坏块,是否采用黑片。运行软件后,用户只需选中U盘的盘符,再选中“数据完整性校验”后点击“开始测试”(如图1)。如果无法通过,说明该盘存在比较严重的质量问题。

USB 传输率加速

下载地址:http://t.cn/zlBFDco

“U盘提速小工具”是笔者原创作品,它的使用非常简单。启动该工具之后,如果发现最后挂接的USB设备的最大传输速率未设置成2M,软件会自动设置成2M,并提示请重启进行测试(如图2)。

不过要让设置生效,还必须重启电脑。如果不使用该工具,许多地方提供的方法都必须经过一个比较复杂的过程才能完成。

经过该工具调整之后,可以发现对移动硬盘来说,大文件读写速度的确提升了一些,不过不是所有大小的文件都得到提升,总体上来看性能有所增强,下面图3和图4表示设置前后传输速度的变化:

可以看出来大多数情况下速度有所提升,不过在传输小文件时并不会感觉到明显的提升,甚至可能有小幅度的下降,所以笔者建议大家在传输大型文件时再启用该工具。

金山U盘的快速启动与重连

下载地址:http://t.cn/zlBsU8C

虽然金山U盘在功能上同其他U盘管理工具有些雷同,但是它的安全弹出和重新启用功能很好。如果U盘未被占用,可以及时使用安全弹出功能,而用户如果使用了U盘内的文件,软件会自动弹出对话框提示还有U盘内的文件被打开,避免用户误操作(如图5)。

上一篇:穿越大半个中国去睡你诗歌下一篇:公务员请假