1.IDEåACHIåºå«
2.VC++ MFCå¦ä½è·åCPU IDå硬ççåºåå·ï¼
3.在 Linux 上检测 IDE/SATA SSD 硬盘的传输速度
IDEåACHIåºå«
åºå«å¨äºæ¥å£ãé度ãç¹æ§ä¸ä¸æ ·ã1ãæ¥å£ä¸ä¸æ ·ãSATAç»ä¸äºå¤§å°ç¡¬ççæ¥å£ãIDE没æç»ä¸å¤§å°ã
2ãé度ä¸ä¸æ ·ãIDEæé«ï¼SATAç°å¨æé«Må·¦å³ã
3ãç¹æ§ä¸ä¸æ ·ãIDEä¸æ¯æNCQãTRIMçãæ æ³ä½¿ç¨åºæ硬ççã
æ©å±èµæï¼
AHCIæ¬è´¨æ¯ä¸ç§PCI类设å¤ï¼å¨ç³»ç»å åæ»çº¿å串è¡ATA设å¤å é¨é»è¾ä¹é´æ®æ¼ä¸ç§éç¨æ¥å£çè§è²ï¼å³å®å¨ä¸åçæä½ç³»ç»å硬件ä¸æ¯éç¨çï¼ãè¿ç±»è®¾å¤æè¿°äºä¸ä¸ªå«æ§å¶åç¶æåºåãå½ä»¤åºåå ¥å£è¡¨çéç¨ç³»ç»å åç»æï¼æ¯ä¸ªå½ä»¤è¡¨å ¥å£å å«SATA设å¤ç¼ç¨ä¿¡æ¯ï¼åä¸ä¸ªæåï¼ç¨äºå¨è®¾å¤å主æºä¼ è¾æ°æ®çï¼æ述表çæéã
å¯è§åç¨åºè®¾è®¡ä¹è¶æ¥è¶éè¦ï¼æè°çå¯è§åç¨åºè®¾è®¡åVisual BasicæVisual C++并ä¸åï¼æ¯æå¯è§åç¨åºè®¾è®¡çIDEå¯ä»¥è®©å¼å人åç´æ¥ç§»å¨ç¨åºåå æ¥å»ºç«æµç¨å¾åç»æå¾ï¼ç¶åç´æ¥åç¼è¯æ解éï¼è¿ä¸ç±»çæµç¨å¾é常æ¯ä»¥UML为åºç¡ã
è¿æ ·ççé¢å 为ä¹é«çMindstormså¼å§æ®åï¼ä¸äºå ¬å¸ä¹å¼å§éè¿æµè§å¨Mozillaååæ£å¼ç¨åºè®¾è®¡ï¼LabVIEWï¼å¾è¿æ¹é¢åªåãä»å¹´ä»£å¼å§ï¼ç¬¬ä¸ä¸ªå¯è§åç¨åºè®¾è®¡ç³»ç»âMaxï¼å°±æ¯ä»¥ç±»æ¯åæå¨ç设计为æ¦æ ·ï¼åæ¶è¢«ç¨æ¥å¼åå³æ¶é³ä¹æ¼åºè½¯ä»¶ã
è¿ç§æ¹æ³ä¹è¢«ç¨å¨ä¸ä¸è½¯ä»¶ï¼ä¾å¦Openlabï¼è¿ç±»ç使ç¨è éè¦å®æ´ç¨åºè®¾è®¡è¯è¨çå¼¹æ§ï¼å¹¶ä¸æ³è¦ä¼ ç»çå¦ä¹ æ²çº¿ãå¯è§åç¨åºè®¾è®¡è¯è¨æå¦ä¸ä¸ªåå è´¹åå¼æ¾æºä»£ç çæ¿ä»£åï¼Mindscriptï¼å ·æå å¯ç³»ç»åè¿ç»æ°æ®åºççã
åèèµæï¼ç¾åº¦ç¾ç§-AHCI
ç¾åº¦ç¾ç§-IDE
VC++ MFCå¦ä½è·åCPU IDå硬ççåºåå·ï¼
// âè·å¾Intel CPU IDâæé®æ¶æ¯å¤çå½æ°
void CIntelCPUIDDlg::OnBtnCPUID()
{
unsigned long s1,s2;
unsigned char vendor_id[]="------------";//CPUæä¾åID
CString str1,str2,str3;
// 以ä¸ä¸ºè·å¾CPU IDçæ±ç¼è¯è¨æ令
_asm // å¾å°CPUæä¾åä¿¡æ¯
{
xor eax,eax // å°eaxæ¸ 0
cpuid // è·åCPUIDçæ令
mov dword ptr vendor_id,ebx
mov dword ptr vendor_id[+4],edx
mov dword ptr vendor_id[+8],ecx
}
str1.Format("%s",vendor_id);
_asm // å¾å°CPU IDçé«ä½
{
mov eax,h
xor edx,edx
cpuid
mov s2,eax
}
str2.Format("%X-",s2);
_asm // å¾å°CPU IDçä½ä½
{
mov eax,h
xor ecx,ecx
xor edx,edx
cpuid
mov s1,edx
mov s2,ecx
}
str3.Format("%X-%X\n",s1,s2);
str2=str2+str3;
m_editVendor.SetWindowText(str1);
m_editCPUID.SetWindowText(str2);
}
// GetHDSerial.cpp: implementation of the CGetHDSerial class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "GetHDSerial.h"
char m_buffer[];
WORD m_serial[];
DWORD m_OldInterruptAddress;
DWORDLONG m_IDTR;
// çå¾ ç¡¬ç空é²
static unsigned int WaitHardDiskIdle()
{
BYTE byTemp;
Waiting:
_asm
{
mov dx, 0x1f7
in al, dx
cmp al, 0x
jb Endwaiting
jmp Waiting
}
Endwaiting:
_asm
{
mov byTemp, al
}
return byTemp;
}
//ä¸ææå¡ç¨åº
void _declspec( naked )InterruptProcess(void)
{
int byTemp;
int i;
WORD temp;
//ä¿åå¯åå¨å¼
_asm
{
push eax
push ebx
push ecx
push edx
push esi
}
WaitHardDiskIdle();//çå¾ ç¡¬ç空é²ç¶æ
_asm
{
mov dx, 0x1f6
mov al, 0xa0
out dx, al
}
byTemp = WaitHardDiskIdle(); //è¥ç´æ¥å¨Ring3级æ§è¡çå¾ å½ä»¤ï¼ä¼è¿å ¥æ»å¾ªç¯
if ((byTemp&0x)!=0x)
{
_asm // æ¢å¤ä¸æç°åºå¹¶éåºä¸ææå¡ç¨åº
{
pop esi
pop edx
pop ecx
pop ebx
pop eax
iretd
}
}
_asm
{
mov dx, 0x1f6 //å½ä»¤ç«¯å£1f6,éæ©é©±å¨å¨0
mov al, 0xa0
out dx, al
inc dx
mov al, 0xec
out dx, al //åé读驱å¨å¨åæ°å½ä»¤
}
byTemp = WaitHardDiskIdle();
if ((byTemp&0x)!=0x)
{
_asm // æ¢å¤ä¸æç°åºå¹¶éåºä¸ææå¡ç¨åº
{
pop esi
pop edx
pop ecx
pop ebx
pop eax
iretd
}
}
//读å硬çæ§å¶å¨çå ¨é¨ä¿¡æ¯
for (i=0;i<;i++)
{
_asm
{
mov dx, 0x1f0
in ax, dx
mov temp, ax
}
m_serial[i] = temp;
}
_asm
{
pop esi
pop edx
pop ecx
pop ebx
pop eax
iretd
}
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CGetHDSerial::CGetHDSerial()
{
}
CGetHDSerial::~CGetHDSerial()
{
}
// 读å硬çåºåå·å½æ°
char* CGetHDSerial::GetHDSerial()
{
m_buffer[0]='\n';
// å¾å°å½åæä½ç³»ç»çæ¬
OSVERSIONINFO OSVersionInfo;
OSVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx( &OSVersionInfo);
if (OSVersionInfo.dwPlatformId != VER_PLATFORM_WIN_NT)
{
// Windows 9x/MEä¸è¯»å硬çåºåå·
WORD m_wWin9xHDSerial[];
Win9xReadHDSerial(m_wWin9xHDSerial);
strcpy (m_buffer, WORDToChar (m_wWin9xHDSerial, , ));
}
else
{
// Windows NT//XPä¸è¯»å硬çåºåå·
DWORD m_wWinNTHDSerial[];
// å¤ææ¯å¦æSCSI硬ç
if ( ! WinNTReadIDEHDSerial(m_wWinNTHDSerial))
WinNTReadSCSIHDSerial(m_wWinNTHDSerial);
strcpy (m_buffer, DWORDToChar (m_wWinNTHDSerial, , ));
}
return m_buffer;
}
// Windows9X/MEç³»ç»ä¸è¯»å硬çåºåå·
void _stdcall CGetHDSerial::Win9xReadHDSerial(WORD * buffer)
{
int i;
for(i=0;i<;i++)
buffer[i]=0;
_asm
{
push eax
//è·åä¿®æ¹çä¸æçä¸ææ述符ï¼ä¸æé¨ï¼å°å
sidt m_IDTR
mov eax,dword ptr [m_IDTR+h]
add eax,3*h+h
cli
//ä¿ååå çä¸æå ¥å£å°å
push ecx
mov ecx,dword ptr [eax]
mov cx,word ptr [eax-h]
mov dword ptr m_OldInterruptAddress,ecx
pop ecx
//设置修æ¹çä¸æå ¥å£å°å为æ°çä¸æå¤çç¨åºå ¥å£å°å
push ebx
lea ebx,InterruptProcess
mov word ptr [eax-h],bx
shr ebx,h
mov word ptr [eax+h],bx
pop ebx
//æ§è¡ä¸æï¼è½¬å°Ring 0ï¼ç±»ä¼¼CIHç æ¯åçï¼
int 3h
//æ¢å¤åå çä¸æå ¥å£å°å
push ecx
mov ecx,dword ptr m_OldInterruptAddress
mov word ptr [eax-h],cx
shr ecx,h
mov word ptr [eax+h],cx
pop ecx
sti
pop eax
}
for(i=0;i<;i++)
buffer[i]=m_serial[i];
}
// Windows 9x/MEç³»ç»ä¸ï¼å°åç±»åï¼WORDï¼ç硬çä¿¡æ¯è½¬æ¢ä¸ºå符类åï¼charï¼
char * CGetHDSerial::WORDToChar (WORD diskdata [], int firstIndex, int lastIndex)
{
static char string [];
int index = 0;
int position = 0;
// æç §é«åèå¨åï¼ä½åèå¨åç顺åºå°åæ°ç»diskdata ä¸å 容åå ¥å°å符串stringä¸
for (index = firstIndex; index <= lastIndex; index++)
{
// åå ¥åä¸çé«åè
string [position] = (char) (diskdata [index] / );
position++;
// åå ¥åä¸çä½åè
string [position] = (char) (diskdata [index] % );
position++;
}
// æ·»å å符串ç»ææ å¿
string [position] = '\0';
// å é¤å符串ä¸ç©ºæ ¼
for (index = position - 1; index > 0 && ' ' == string [index]; index--)
string [index] = '\0';
return string;
}
// Windows NT//XPç³»ç»ä¸ï¼å°ååç±»åï¼DWORDï¼ç硬çä¿¡æ¯è½¬æ¢ä¸ºå符类åï¼charï¼
char* CGetHDSerial::DWORDToChar (DWORD diskdata [], int firstIndex, int lastIndex)
{
static char string [];
int index = 0;
int position = 0;
// æç §é«åèå¨åï¼ä½åèå¨åç顺åºå°ååä¸çä½ååå ¥å°å符串stringä¸
for (index = firstIndex; index <= lastIndex; index++)
{
// åå ¥ä½åä¸çé«åè
string [position] = (char) (diskdata [index] / );
position++;
// åå ¥ä½åä¸çä½åè
string [position] = (char) (diskdata [index] % );
position++;
}
// æ·»å å符串ç»ææ å¿
string [position] = '\0';
// å é¤å符串ä¸ç©ºæ ¼
for (index = position - 1; index > 0 && ' ' == string [index]; index--)
string [index] = '\0';
return string;
}
// Windows NT//XPä¸è¯»åIDE硬çåºåå·
BOOL CGetHDSerial::WinNTReadIDEHDSerial(DWORD * buffer)
{
BYTE IdOutCmd [sizeof (SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
BOOL bFlag = FALSE;
int drive = 0;
char driveName [];
HANDLE hPhysicalDriveIOCTL = 0;
sprintf (driveName, "\\\\.\\PhysicalDrive%d", drive);
// Windows NT//XPä¸å建æ件éè¦ç®¡çåæé
hPhysicalDriveIOCTL = CreateFile (driveName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, 0, NULL);
if (hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
{
GETVERSIONOUTPARAMS VersionParams;
DWORD cbBytesReturned = 0;
// å¾å°é©±å¨å¨çIOæ§å¶å¨çæ¬
memset ((void*) &VersionParams, 0, sizeof(VersionParams));
if(DeviceIoControl (hPhysicalDriveIOCTL, IOCTL_GET_VERSION,
NULL, 0, &VersionParams,
sizeof(VersionParams),
&cbBytesReturned, NULL) )
{
if (VersionParams.bIDEDeviceMap > 0)
{
BYTE bIDCmd = 0; // IDEæè ATAPIè¯å«å½ä»¤
SENDCMDINPARAMS scip;
// å¦æ驱å¨å¨æ¯å 驱ï¼éç¨å½ä»¤IDE_ATAPI_IDENTIFYï¼ command,
// å¦åéç¨å½ä»¤IDE_ATA_IDENTIFY读å驱å¨å¨ä¿¡æ¯
bIDCmd = (VersionParams.bIDEDeviceMap >> drive & 0x)?
IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
memset (&scip, 0, sizeof(scip));
memset (IdOutCmd, 0, sizeof(IdOutCmd));
// è·å驱å¨å¨ä¿¡æ¯
if (WinNTGetIDEHDInfo (hPhysicalDriveIOCTL,
&scip,
(PSENDCMDOUTPARAMS)&IdOutCmd,
(BYTE) bIDCmd,
(BYTE) drive,
&cbBytesReturned))
{
int m = 0;
USHORT *pIdSector = (USHORT *)
((PSENDCMDOUTPARAMS) IdOutCmd) -> bBuffer;
for (m = 0; m < ; m++)
buffer[m] = pIdSector [m];
bFlag = TRUE; // 读å硬çä¿¡æ¯æå
}
}
}
CloseHandle (hPhysicalDriveIOCTL); // å ³éå¥æ
}
return bFlag;
}
// WindowsNT//XPç³»ç»ä¸è¯»åSCSI硬çåºåå·
BOOL CGetHDSerial::WinNTReadSCSIHDSerial (DWORD * buffer)
{
buffer[0]='\n';
int controller = 0;
HANDLE hScsiDriveIOCTL = 0;
char driveName [];
sprintf (driveName, "\\\\.\\Scsi%d:", controller);
// Windows NT//XPä¸ä»»ä½æéé½å¯ä»¥è¿è¡
hScsiDriveIOCTL = CreateFile (driveName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, 0, NULL);
if (hScsiDriveIOCTL != INVALID_HANDLE_VALUE)
{
int drive = 0;
DWORD dummy;
for (drive = 0; drive < 2; drive++)
{
char buffer [sizeof (SRB_IO_CONTROL) + SENDIDLENGTH];
SRB_IO_CONTROL *p = (SRB_IO_CONTROL *) buffer;
SENDCMDINPARAMS *pin =
(SENDCMDINPARAMS *) (buffer + sizeof (SRB_IO_CONTROL));
// åå¤åæ°
memset (buffer, 0, sizeof (buffer));
p -> HeaderLength = sizeof (SRB_IO_CONTROL);
p -> Timeout = ;
p -> Length = SENDIDLENGTH;
p -> ControlCode = IOCTL_SCSI_MINIPORT_IDENTIFY;
strncpy ((char *) p -> Signature, "SCSIDISK", 8);
pin -> irDriveRegs.bCommandReg = IDE_ATA_IDENTIFY;
pin -> bDriveNumber = drive;
// å¾å°SCSI硬çä¿¡æ¯
if (DeviceIoControl (hScsiDriveIOCTL, IOCTL_SCSI_MINIPORT,
buffer,
sizeof (SRB_IO_CONTROL) +
sizeof (SENDCMDINPARAMS) - 1,
buffer,
sizeof (SRB_IO_CONTROL) + SENDIDLENGTH,
&dummy, NULL))
{
SENDCMDOUTPARAMS *pOut =
(SENDCMDOUTPARAMS *) (buffer + sizeof (SRB_IO_CONTROL));
IDSECTOR *pId = (IDSECTOR *) (pOut -> bBuffer);
if (pId -> sModelNumber [0])
{
int n = 0;
USHORT *pIdSector = (USHORT *) pId;
for (n = 0; n < ; n++)
buffer[n] =pIdSector [n];
return TRUE; // 读åæå
}
}
}
CloseHandle (hScsiDriveIOCTL); // å ³éå¥æ
}
return FALSE; // 读å失败
}
// Windows NT//XPä¸è¯»åIDE设å¤ä¿¡æ¯
BOOL CGetHDSerial::WinNTGetIDEHDInfo (HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
PSENDCMDOUTPARAMS pSCOP, BYTE bIDCmd, BYTE bDriveNum,
PDWORD lpcbBytesReturned)
{
// 为读å设å¤ä¿¡æ¯åå¤åæ°
pSCIP -> cBufferSize = IDENTIFY_BUFFER_SIZE;
pSCIP -> irDriveRegs.bFeaturesReg = 0;
pSCIP -> irDriveRegs.bSectorCountReg = 1;
pSCIP -> irDriveRegs.bSectorNumberReg = 1;
pSCIP -> irDriveRegs.bCylLowReg = 0;
pSCIP -> irDriveRegs.bCylHighReg = 0;
// 计ç®é©±å¨å¨ä½ç½®
pSCIP -> irDriveRegs.bDriveHeadReg = 0xA0 | ((bDriveNum & 1) << 4);
// 设置读åå½ä»¤
pSCIP -> irDriveRegs.bCommandReg = bIDCmd;
pSCIP -> bDriveNumber = bDriveNum;
pSCIP -> cBufferSize = IDENTIFY_BUFFER_SIZE;
// 读å驱å¨å¨ä¿¡æ¯
return ( DeviceIoControl (hPhysicalDriveIOCTL, IOCTL_GET_DRIVE_INFO,
(LPVOID) pSCIP,
sizeof(SENDCMDINPARAMS) - 1,
(LPVOID) pSCOP,
sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
lpcbBytesReturned, NULL) );
}
在 Linux 上检测 IDE/SATA SSD 硬盘的传输速度
检测 Linux 上 IDE/SATA SSD 硬盘的传输速度
在 Linux 环境下,我们可以通过 hdparm 和 dd 命令来评估硬盘性能。hdparm 是一个强大的工具,提供了对各种硬盘的abv源码 ioctls 的命令行接口,这些接口由 Linux 系统的 ATA/IDE/SATA 设备驱动程序子系统所支持。确保使用最新的内核版本,并且推荐使用最新内核源代码的包含头文件来编译 hdparm。
使用 `hdparm` 命令检测硬盘速度的步骤如下:
以 root 权限登录,运行以下命令:
或者
为了获取更准确的数据,重复此操作 2-3 次。这个操作测量了系统处理器、广州南到鹤山源码高速缓存和存储器的吞吐量指标。例如:
要确定 SATA 硬盘的连接速度,请执行:
输出将显示硬盘的速度,即 1.5Gb/s、3.0Gb/s 或 6.0Gb/s。FIL分币源码请确保 BIOS/主板支持 SATA-II/III。
使用 `dd` 命令同样可以获取速度信息:
通过调整 `dd` 命令参数,可以进行更详细的性能测试。
除了命令行工具外,您还可以使用“磁盘实用程序”GUI 工具。Vue源码有多少在最新版本的 Gnome 中,该工具简称为“磁盘”。要测试硬盘性能,请按照相应的指南进行操作。
为了安全地测试硬盘性能,高级拦截马源码选择只读模式。此模式下不会损坏数据。若要测试读写性能并可能导致数据丢失,请确保谨慎操作。
本文由 LCTT 原创编译,Linux中国荣誉推出。作者是 nixCraft 的创始人,系统管理员专家,也是 Linux 操作系统/Unix shell 脚本的培训师。他与多个行业领域合作,包括 IT、教育、国防、空间研究和非营利组织。