कुछ शोध किया करने के बाद और इस पृष्ठ पर जवाब से जानकारी का उपयोग कर, यहाँ विंडोज 7 और बाद के लिए मेरे कार्यान्वयन सी WinAPIs का उपयोग कर रहा है:
//Open drive as such: "\\?\PhysicalDriveX" where X is the drive number
//INFO: To get drive number from a logical drive letter, check this method:
// (But keep in mind that a single logical drive, or a volume,
// can span across several physical drives, as a "spanned volume.")
// http://stackoverflow.com/a/11683906/843732
#include <WinIoCtl.h>
#include <Ntddscsi.h>
DWORD bytesReturned;
//As an example, let's test 1st physical drive
HANDLE hDevice = ::CreateFile(L"\\\\?\\PhysicalDrive0"
GENERIC_READ | GENERIC_WRITE, //We need write access to send ATA command to read RPMs
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, 0, NULL);
if(hDevice != INVALID_HANDLE_VALUE)
{
//Check TRIM -- should be Y for SSD
_tprintf(L"TRIM=");
STORAGE_PROPERTY_QUERY spqTrim;
spqTrim.PropertyId = (STORAGE_PROPERTY_ID)StorageDeviceTrimProperty;
spqTrim.QueryType = PropertyStandardQuery;
bytesReturned = 0;
DEVICE_TRIM_DESCRIPTOR dtd = {0};
if(::DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY,
&spqTrim, sizeof(spqTrim), &dtd, sizeof(dtd), &bytesReturned, NULL) &&
bytesReturned == sizeof(dtd))
{
//Got it
_tprintf(L"%s", dtd.TrimEnabled ? L"Y" : L"N");
}
else
{
//Failed
int err = ::GetLastError();
_tprintf(L"?");
}
//Check the seek-penalty value -- should be N for SSD
_tprintf(L", seekPenalty=");
STORAGE_PROPERTY_QUERY spqSeekP;
spqSeekP.PropertyId = (STORAGE_PROPERTY_ID)StorageDeviceSeekPenaltyProperty;
spqSeekP.QueryType = PropertyStandardQuery;
bytesReturned = 0;
DEVICE_SEEK_PENALTY_DESCRIPTOR dspd = {0};
if(::DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY,
&spqSeekP, sizeof(spqSeekP), &dspd, sizeof(dspd), &bytesReturned, NULL) &&
bytesReturned == sizeof(dspd))
{
//Got it
_tprintf(L"%s", dspd.IncursSeekPenalty ? L"Y" : L"N");
}
else
{
//Failed
int err = ::GetLastError();
_tprintf(L"?");
}
//Get drive's RPMs reading -- should be 1 for SSD
//CODE SOURCE: https://emoacht.wordpress.com/2012/11/06/csharp-ssd/
_tprintf(L", RPM=");
ATAIdentifyDeviceQuery id_query;
memset(&id_query, 0, sizeof(id_query));
id_query.header.Length = sizeof(id_query.header);
id_query.header.AtaFlags = ATA_FLAGS_DATA_IN;
id_query.header.DataTransferLength = sizeof(id_query.data);
id_query.header.TimeOutValue = 5; //Timeout in seconds
id_query.header.DataBufferOffset = offsetof(ATAIdentifyDeviceQuery, data[0]);
id_query.header.CurrentTaskFile[6] = 0xec; // ATA IDENTIFY DEVICE
bytesReturned = 0;
if(::DeviceIoControl(hDevice, IOCTL_ATA_PASS_THROUGH,
&id_query, sizeof(id_query), &id_query, sizeof(id_query), &bytesReturned, NULL) &&
bytesReturned == sizeof(id_query))
{
//Got it
//Index of nominal media rotation rate
//SOURCE: http://www.t13.org/documents/UploadedDocuments/docs2009/d2015r1a-ATAATAPI_Command_Set_-_2_ACS-2.pdf
// 7.18.7.81 Word 217
//QUOTE: Word 217 indicates the nominal media rotation rate of the device and is defined in table:
// Value Description
// --------------------------------
// 0000h Rate not reported
// 0001h Non-rotating media (e.g., solid state device)
// 0002h-0400h Reserved
// 0401h-FFFEh Nominal media rotation rate in rotations per minute (rpm)
// (e.g., 7 200 rpm = 1C20h)
// FFFFh Reserved
#define kNominalMediaRotRateWordIndex 217
_tprintf(L"%d", (UINT)id_query.data[kNominalMediaRotRateWordIndex]);
}
else
{
//Failed
int err = ::GetLastError();
_tprintf(L"?");
}
_tprintf(L"\n");
::CloseHandle(hDevice);
}
मामले में आप ड्राइवर की जरूरत नहीं है DDK, शामिल हैं यहां कुछ परिभाषाएं हैं:
#ifndef StorageDeviceTrimProperty
#define StorageDeviceTrimProperty 8
#endif
#ifndef DEVICE_TRIM_DESCRIPTOR
typedef struct _DEVICE_TRIM_DESCRIPTOR {
DWORD Version;
DWORD Size;
BOOLEAN TrimEnabled;
} DEVICE_TRIM_DESCRIPTOR, *PDEVICE_TRIM_DESCRIPTOR;
#endif
#ifndef StorageDeviceSeekPenaltyProperty
#define StorageDeviceSeekPenaltyProperty 7
#endif
#ifndef DEVICE_SEEK_PENALTY_DESCRIPTOR
typedef struct _DEVICE_SEEK_PENALTY_DESCRIPTOR {
DWORD Version;
DWORD Size;
BOOLEAN IncursSeekPenalty;
} DEVICE_SEEK_PENALTY_DESCRIPTOR, *PDEVICE_SEEK_PENALTY_DESCRIPTOR;
#endif
struct ATAIdentifyDeviceQuery
{
ATA_PASS_THROUGH_EX header;
WORD data[256];
};
आखिरकार, मेरे परीक्षणों का निष्कर्ष।
मेरे पास सैटा केबल के माध्यम से कई सैमसंग एसएसडी जुड़े हुए हैं, और एक पीसीआईई एसएसडी ड्राइव जो पीसीआई स्लॉट का उपयोग कर सीधे लॉजिक बोर्ड से जुड़ा हुआ है। मेरे पास एक बड़ा आंतरिक पश्चिमी डिजिटल एचडीडी (कताई ड्राइव) भी है जो सैटा केबल के माध्यम से और कुछ बाहरी कताई एचडीडी के माध्यम से भी जुड़ा हुआ है।
यहाँ मैं उनके लिए क्या मिलता है:
Samsung SSD 256GB: TRIM=Y, seekPenalty=N, RPM=1
Samsung SSD 500GB: TRIM=Y, seekPenalty=N, RPM=1
PCIs SSD: TRIM=Y, seekPenalty=?, RPM=0
Internal WD HDD: TRIM=N, seekPenalty=?, RPM=0
External WD HDD: TRIM=?, seekPenalty=?, RPM=?
External Cavalry HDD: TRIM=?, seekPenalty=Y, RPM=?
तो जैसा कि आप देख, मेरे मामले में, केवल पैरामीटर यह सही है सभी 6 ड्राइव के लिए TRIM है। मैं यह नहीं कह रहा हूं कि यह आपके मामले में भी होगा। यह सिर्फ मेरे ड्राइव के साथ मेरी खोज है।
यह एक जटिल मुद्दा यह है कि आसान एक उपयोगकर्ता के चलाया स्विच द्वारा के साथ निपटा जा सकता है जैसा लगता है। – kusma
मैं समय को मापने के साथ जाऊंगा, क्योंकि यह गति महत्वपूर्ण बात है और यह तथ्य नहीं कि यह स्वयं में एक एसएसडी है। – jcoder
[इस] पर एक नज़र डालें (http://www.msfn.org/board/topic/151836-need-script-to-detect-ssd/) – Theolodis