ฉันจะค้นหาจำนวนหน่วยความจำกายภาพที่แน่นอนบน Windows x86-32 บิตโดยใช้ Perl หรือภาษาอื่น ๆ ได้อย่างไร

ฉันจำเป็นต้องรู้ว่าเครื่อง Windows มีหน่วยความจำกายภาพเท่าใดโดยใช้ Perl

ฉันได้ลองใช้ Win32::SystemInfo แล้ว อย่างไรก็ตาม โมดูลนี้ระบุคำเตือนต่อไปนี้:

บนคอมพิวเตอร์ Intel x86 ที่มีหน่วยความจำมากกว่า 2 GB และน้อยกว่า 4 GB ฟังก์ชัน MemoryStatus จะคืนค่า 2 GB สำหรับ TotalPhys เสมอ ในทำนองเดียวกัน หากหน่วยความจำที่มีอยู่ทั้งหมดอยู่ระหว่าง 2 ถึง 4 GB AvailPhys จะถูกปัดเศษลงเป็น 2 GB

ดังนั้นในเครื่องที่มีหน่วยความจำกายภาพ 2-4 GB ฉันได้รับคำตอบที่ผิด

มีวิธีรับหน่วยความจำกายภาพในปริมาณที่ถูกต้องหรือไม่? อาจจะเป็นโมดูลอื่น? หรือใช้ Win32::API โดยตรง?

แก้ไข: จากความคิดเห็นที่ผู้คนให้ไว้ที่นี่ ดูเหมือนว่าข้อจำกัดจะอยู่ใน Win32 API และไม่เฉพาะเจาะจงกับ Win32::SystemInfo. อย่างไรก็ตาม ระบบปฏิบัติการจะรู้แน่ชัดว่ามี RAM เหลืออยู่เท่าใด ดังนั้นจึงต้องมีวิธีดึงข้อมูลนั้นออกมา หากไม่ใช่ภาษา Perl อาจเป็นภาษาอื่นใช่ไหม


person Tom Feiner    schedule 08.01.2009    source แหล่งที่มา
comment
เนื่องจากคุณมีหน่วยความจำเสมือน คุณจำเป็นต้องรู้เรื่องนี้จริง ๆ หรือไม่?   -  person Marius    schedule 08.01.2009
comment
ใช่. บ่อยครั้งสำหรับโปรแกรมที่ต้องใช้หน่วยความจำมาก เราปรารถนาที่จะใช้หน่วยความจำกายภาพมากที่สุดเท่าที่จะเป็นไปได้ (ซึ่งช่วยเพิ่มประสิทธิภาพ) แต่ไม่มีการกดปุ่มสลับ (ซึ่งจะทำลายหน่วยความจำนั้นโดยสิ้นเชิง) หน่วยความจำเสมือนนั้นดี แต่ก็ดีกว่าที่จะหลีกเลี่ยงสำหรับอัลกอริธึมหลายอย่าง   -  person pjf    schedule 08.01.2009
comment
ดูเหมือนจะไม่เป็นข้อจำกัดของ Win32::SystemInfo จริงๆ ดูรายละเอียดที่ support.microsoft.com/kb/274558   -  person Mr. Muskrat    schedule 08.01.2009
comment
รายงานฟรีของ Cygwin ในทำนองเดียวกัน (สูงสุดที่ 2 GB)   -  person Joe Casadonte    schedule 08.01.2009
comment
หากระบบปฏิบัติการรู้ว่าระบบมีหน่วยความจำกายภาพเท่าใด คุณควรจะสามารถใช้ Win32::SystemInfo เพื่อดาวน์โหลดได้ กำลังใช้การเรียก GlobalMemoryStatusEx API หากไม่ได้ผล แสดงว่าอาจใช้งานไม่ถูกต้องและคุณควรยื่นรายงานข้อบกพร่อง   -  person Mr. Muskrat    schedule 09.01.2009


คำตอบ (3)


ตามที่ระบุไว้ในความคิดเห็น นี่เป็นปัญหาของ GlobalMemoryStatus เนื่องจาก สามารถส่งคืนคำตอบได้สูงสุด 2GB และ GlobalMemoryStatusEX ซึ่งช่วยแก้ปัญหาขนาด 2GB นี้ จำกัด แต่ใช้ได้กับระบบ 64 บิตเท่านั้น (เท่าที่ฉันสามารถบอกได้)

ในที่สุดฉันก็ใช้รหัส Perl ต่อไปนี้ซึ่งใช้คลาส Win32::OLE และ WMI Win32_PhysicalMemory ซึ่งจะส่งคืนหน่วยความจำกายภาพในปริมาณที่ถูกต้องแม้ในระบบ 32 บิต:

use strict;
use warnings;
use English;
use Win32::OLE qw( EVENTS HRESULT in );
use Readonly;

sub get_physical_memory {
    my $machine                         = shift || '.'; # Default to local machine
    my Readonly $WMI_MEMORY_CLASS_NAME  = 'Win32_PhysicalMemory';
    my Readonly $MEGABYTE               = 1024*1024;

    my $WMI = 
        Win32::OLE->GetObject( "winmgmts:{impersonationLevel=impersonate,(security)}//$machine/" ) || die "Could not get Win32 object: $OS_ERROR";
    my $total_capacity                  = 0;

    foreach my $object ( in( $WMI->InstancesOf( $WMI_MEMORY_CLASS_NAME ) ) ) {
        $total_capacity += $object->{Capacity};
    }

    my $total_capacity_in_mb            = $total_capacity / $MEGABYTE;
    print "Total Memory : $total_capacity_in_mb \n";
    return $total_capacity_in_mb;
}
person Tom Feiner    schedule 11.01.2009

ฉันคิดได้แค่ว่าคำเตือนที่เข้าร่วมผลลัพธ์ของ Win32::SystemInfo นั้นเป็นคำเตือนที่เข้าร่วมการเรียก Win32 API แบบดิบด้วย เนื่องจาก Perl เองไม่มีปัญหาในการจัดการกับตัวเลขจำนวนมากเช่นนี้ ในกรณีนี้ความเป็นไปได้ในการดึงข้อมูลที่ถูกต้องออกมาดูค่อนข้างสิ้นหวัง

ฉันยังได้ยินมาว่า Windows รุ่น 32 บิตปัจจุบันสามารถใช้ RAM ได้ประมาณ 3.2Gb บนเครื่องที่ติดตั้ง >= 4Gb ซึ่งอาจเป็นคำบอกเล่า แต่ jibes ตัวไหนที่มีข้อ จำกัด อยู่ใน API เอง

person j_random_hacker    schedule 09.01.2009
comment
ขึ้นอยู่กับจำนวนพื้นที่หน่วยความจำที่ฮาร์ดแวร์สำรองไว้ ตัวอย่างเครื่องของฉันที่มีขนาด 3GB แสดงว่ามีพื้นที่เหลือน้อยกว่า 3GB เล็กน้อยเนื่องจากฉันมีการ์ดแสดงผลขนาด 1GB - person Darryl Braaten; 10.01.2009
comment
นั่นสมเหตุสมผลแล้ว บางทีปัญหา Win32::SystemInfo และปัญหาขีดจำกัด 3.2Gb อาจเป็นปัญหาที่แยกจากกันจริงๆ - person j_random_hacker; 10.01.2009

ข้อมูลนี้สามารถดึงมาจาก WMI หรือใช้ SNMP หากคุณเลือกที่จะเปิดใช้งาน SNMP ในกล่องที่จะใช้งาน สำหรับ WMI ฉันไม่มีตัวอย่าง Perl ทันที แต่สำหรับตัวอย่าง VBScript ดูด้านล่าง

อ้างอิง: http://www.microsoft.com/technet/scriptcenter/guide/sas_wmi_dieu.mspx

strComputer = "."

Set objSWbemServices = GetObject("winmgmts:\\" & strComputer)
Set colSWbemObjectSet = _
 objSWbemServices.InstancesOf("Win32_LogicalMemoryConfiguration")

For Each objSWbemObject In colSWbemObjectSet
 Wscript.Echo "Total Physical Memory (kb): " & _
 objSWbemObject.TotalPhysicalMemory
Next

ทดสอบบนระบบ XP ของฉันและดึงผลลัพธ์ที่ต้องการ (ขออภัยด้วย RAM เพียง 1.5GB เท่านั้น) ฉันค่อนข้างแน่ใจว่ามีอินเทอร์เฟซ WMI สำหรับ Perl เช่นกัน หากคุณต้องการใช้ Perl ต่อไป ถ้า SNMP เป็นตัวเลือก สามารถรับหน่วยความจำฟิสิคัลทั้งหมดได้จาก SNMP เช่นกันโดยใช้ไลบรารี Perl SNMP ตัวใดตัวหนึ่ง

แก้ไข: เพิ่งสังเกตเห็น @Mr. ความคิดเห็นของ Muskrat เกี่ยวกับ Microsoft KB http://support.microsoft.com/kb/274558 - เห็นได้ชัด พฤติกรรมที่คุณเห็นด้วย Perl นั้นเป็นข้อจำกัดของการเรียก Win32 API ดังนั้นคุณอาจได้รับผลลัพธ์เดียวกันกับ WMI น่าเสียดายที่ฉันไม่มีเครื่อง RAM ขนาด 2-4GB ให้ลองใช้เพื่อตรวจสอบ

person Jay    schedule 10.01.2009
comment
ขอบคุณ มันทำงานได้อย่างถูกต้อง แม้แต่ในเครื่องที่มี 4GB ก็ตาม อย่างไรก็ตาม ฉันพบวิธีแก้ปัญหา Perl ซึ่งฉันได้โพสต์ไว้ - person Tom Feiner; 11.01.2009