2014-04-29 7 views
11

में एसएसडी का पता लगाने के लिए मैं अपने सी ++ एप्लिकेशन के प्रदर्शन और व्यवहार को बदलना चाहता हूं, यह बताता है कि सिस्टम ड्राइव एक एसएसडी है या नहीं। उदाहरण:विंडोज

    एसएसडी के साथ
  • , मैं अपने gameserver आवेदन प्रत्येक नक्शे पूरी तरह से सभी वस्तुओं के साथ आदेश प्रदर्शन को अधिकतम करने में लोड करना चाहते हैं।
  • एचडीडी के साथ, मैं चाहता हूं कि मेरे गेमरवर एप्लिकेशन को प्रत्येक मानचित्र में केवल आवश्यक वस्तुओं और इकाइयों को लोड करने के लिए, बाहरी वस्तुओं को लोड न किया जाए।

मैं http://msdn.microsoft.com/en-gb/library/windows/desktop/aa364939(v=vs.85).aspx है, जो यह निर्धारित करने के लिए एक निश्चित ड्राइव एक HDD, सीडी-रोम, डीवीडी ROM, हटाने योग्य मीडिया, आदि है का एक तरीका है देखा है, लेकिन यह अभी भी पता नहीं लगा सकते मुख्य सिस्टम ड्राइव है कि क्या एक एसएसडी मैंने Is there any way of detecting if a drive is a SSD? भी देखा है, लेकिन समाधान केवल लिनक्स पर लागू होता है।

मैंने सोचा कि मैं किसी भी तरह से एक बड़ा जुर्माना (500 एमबी) उत्पन्न कर सकता हूं, और फिर फ़ाइल लिखने में कितना समय लगता है, लेकिन हालांकि अन्य सिस्टम चर परिणाम को आसानी से प्रभावित कर सकते हैं।

विंडोज़ में, सी ++ का उपयोग करके, क्या यह पता लगाने का कोई तरीका है कि मुख्य सिस्टम ड्राइव एक एसएसडी है या नहीं?

+2

यह एक जटिल मुद्दा यह है कि आसान एक उपयोगकर्ता के चलाया स्विच द्वारा के साथ निपटा जा सकता है जैसा लगता है। – kusma

+7

मैं समय को मापने के साथ जाऊंगा, क्योंकि यह गति महत्वपूर्ण बात है और यह तथ्य नहीं कि यह स्वयं में एक एसएसडी है। – jcoder

+0

[इस] पर एक नज़र डालें (http://www.msfn.org/board/topic/151836-need-script-to-detect-ssd/) – Theolodis

उत्तर

10

आप माइक्रोसॉफ्ट डब्लूएमआई क्लास MSFT_PhysicalDisk का उपयोग कर सकते हैं। 4 का मेडियोटाइप एसएसडी है और स्पिंडलस्पीड 0 होगा। अधिक जानकारी के लिए लिंक देखें।

https://msdn.microsoft.com/en-us/library/windows/desktop/hh830532(v=vs.85)

13

मेरा मानना ​​है कि आप गलत टूल का उपयोग कर रहे हैं। एक एसएसडी होने के आधार पर धारणाएं बनाने के बजाय आपको धीमे और तेज़ ड्राइव के साथ अपना कोड अच्छी तरह से काम करना चाहिए, उदाहरण के लिए आवश्यक वस्तुओं को पहले और बाद में लोड करना। तीन वर्षों में आविष्कार [...] एसएसडी की तुलना में नियमित रूप से हार्ड ड्राइव को तेज कर सकता है जो आपके कोड को तोड़ देगा। पूरी तरह से गति के आधार पर जाकर रैम डिस्क, एनएफएस, यूएसबी 3.0-स्टिक्स और अन्य सामानों के लिए भी काम करेगा जो आपने नहीं किया या नहीं कर सकते हैं।

संपादित करें: एक एचडीडी वास्तव में एक धीमी एसएसडी के समान नहीं है। जबकि वे एचडीडी पढ़ने और लिखने में दोनों तेजी से हैं, मांगने के लिए महत्वपूर्ण समय की जरूरत है। इस प्रकार दो अलग-अलग एक्सेस रणनीतियों का उपयोग करना समझ में आता है: एसएसडी के लिए यादृच्छिक पहुंच के माध्यम से महत्वपूर्ण डेटा चुनना और क्रमशः एचडीडी के लिए पढ़ना। आप शायद अनुक्रमिक रणनीति को लागू करने के साथ ही दूर हो जाएंगे क्योंकि एसएसडी के साथ अभी भी ठीक काम करना चाहिए। हालांकि एसएसडी के बजाय एचडीडी की जांच करना अधिक समझ में आता है, क्योंकि आपको एचडीडी विशेष का इलाज करने की आवश्यकता है जबकि एसएसडी, रैमडिस्क, एनएफएस और इतने पर समय तलाशने से पीड़ित नहीं होना चाहिए और इस तरह इसका इलाज किया जा सकता है।

+0

मैंने इसके बजाय एक और जवाब स्वीकार किया क्योंकि यह एक समाधान प्रदान करता है, हालांकि यह उत्तर उपयोगी है और इसे बर्खास्त नहीं किया जाना चाहिए। – cybermonkey

4

ड्राइव प्रकार से परेशान न हों। अपने कुछ गेम डेटा को पढ़कर माप करें जो किसी भी तरह से लोड हो और तय करें कि किस रणनीति का उपयोग करना है। (कॉन्फ़िगरेशन विकल्प बनाना न भूलें :)

निचले भाग में मेरा आंत वृत्ति मुझे बताती है कि दृष्टिकोण गलत है। अगर किसी के पास धीमी डिस्क है तो फ्लाई लोडिंग पर प्रीलोडिंग अधिक महत्वपूर्ण होनी चाहिए क्योंकि स्टटरिंग का कारण बनता है। दूसरी ओर यदि ड्राइव पर्याप्त तेज़ है तो मुझे स्मृति बर्बाद करने की आवश्यकता नहीं है क्योंकि मैं पर्याप्त तेज़ी से फ्लाई पर डेटा लोड कर सकता हूं।

6

हां, यह निर्धारित करने का एक उच्च मौका है कि ड्राइव एक एसएसडी है या नहीं। एसएसडी आम तौर पर टीआरआईएम कमांड का समर्थन करता है, इसलिए मैं यह देखने के लिए जांच करूंगा कि ड्राइव TRIM कमांड का समर्थन करती है या नहीं।

विंडोज़ में, आप IOCTL_STORAGE_QUERY_PROPERTY का उपयोग DEVICE_TRIM_DESCRIPTOR संरचना प्राप्त करने के लिए कर सकते हैं जो आपको बताएगा कि टीआरआईएम सक्षम है या नहीं।

यदि आप वास्तव में जानते हैं कि आप क्या कर रहे हैं, तो आप कच्चे पहचान डिवाइस पैकेज प्राप्त कर सकते हैं और डेटा को स्वयं समझ सकते हैं। SATA ड्राइव के लिए यह शब्द 16 9 बिट 0 होगा।

+0

बहुत अच्छा। यह वास्तव में मेरे सभी एसएसडी के लिए काम करता है। अब ड्राइव के आरपीएम का पता लगाने के बारे में, जिसे एसएसडी को 0 या किसी के रूप में रिपोर्ट नहीं करना चाहिए। क्या उसके पास कोई कामकाजी कोड है? इसके लिए 'IOCTL_SCSI_MINIPORT' का उपयोग किया जा सकता है। सबसे अच्छा मैं अब तक पा सकता हूं यह आधा उत्तर प्रश्न है: https://social.msdn.microsoft.com/Forums/en-US/66a9f916-bbb6-4e51-91f5-8587968691cb/get-rpm-of-disk? फोरम = vcmfcatl – c00000fd

+0

आरपीएम पहचान डिवाइस पैकेज के नाममात्र मीडिया रोटेशन रेट फ़ील्ड (शब्द 217) में रिपोर्ट किया गया है। –

+0

@tchau।देव का मतलब है DEVICE_TRIM_DESCRIPTOR-> TrimEnabled हमेशा शब्द 169-> bit0 के बराबर है? (और, इस प्रकार, यदि डिवाइस "1" की रिपोर्ट करता है तो इसका मतलब केवल यह है कि यह टीआरआईएम का समर्थन करता है, और इसका मतलब यह नहीं है कि यह वास्तव में काम नहीं कर रहा है, उदाहरण के लिए वर्णित [यहां] (http://askubuntu.com/a/439655/ 9 2 9 48)।) – Igor

10

कुछ शोध किया करने के बाद और इस पृष्ठ पर जवाब से जानकारी का उपयोग कर, यहाँ विंडोज 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 है। मैं यह नहीं कह रहा हूं कि यह आपके मामले में भी होगा। यह सिर्फ मेरे ड्राइव के साथ मेरी खोज है।