您的位置:首页 > 其它

第二人生的源码分析(七十八)LLOSInfo类实现获取操作系统信息

2008-06-02 20:57 435 查看
由于信息产业在不断地发展,特别像电脑里的操作系统更是更新不断。比如Windows系统,就有WIN NT、Win2000、WIN XP、WIN SERVER等等。下面就来分析这个类的声明代码:
#001 class LLOSInfo
#002 {
#003 public:

构造函数。
#004 LLOSInfo();

把操作系统信息写到流对象。
#005 void stream(std::ostream& s) const;
#006

获取操作系统信息字符串。
#007 const std::string& getOSString() const;
#008 const std::string& getOSStringSimple() const;
#009

操作系统的主版本号。
#010 S32 mMajorVer;

操作系统的次版本号。
#011 S32 mMinorVer;

操作系统的编译号。
#012 S32 mBuild;
#013

获取能打开文件的个数。
#014 #ifndef LL_WINDOWS
#015 static S32 getMaxOpenFiles();
#016 #endif
#017

获取虚拟内存的大小。
#018 static U32 getProcessVirtualSizeKB();

获取保留内存的大小。
#019 static U32 getProcessResidentSizeKB();
#020 private:
#021 std::string mOSString;
#022 std::string mOSStringSimple;
#023 };

接着来分析怎么获取系统的信息,如下:
#001 LLOSInfo::LLOSInfo() :
#002 mMajorVer(0), mMinorVer(0), mBuild(0)
#003 {
#004
#005 #if LL_WINDOWS
#006 OSVERSIONINFOEX osvi;
#007 BOOL bOsVersionInfoEx;
#008

清空操作系统版本信息的结构。
#009 // Try calling GetVersionEx using the OSVERSIONINFOEX structure.
#010 ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));

设置版本结构的大小。
#011 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);

调用WINDOWS的API函数GetVersionEx得到系统的版本信息。
#012 if(!(bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO *) &osvi)))
#013 {
#014 // If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO.

如果OSVERSIONINFOEX获取不成功,就调用旧的API函数。
#015 osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
#016 if(!GetVersionEx( (OSVERSIONINFO *) &osvi))
#017 return;
#018 }

保存WINDOWS的主版本号和次版本号。
#019 mMajorVer = osvi.dwMajorVersion;
#020 mMinorVer = osvi.dwMinorVersion;

保存WINDOWS编译号。
#021 mBuild = osvi.dwBuildNumber;
#022

根据WINDOWS平台ID来分析是那一个WINDOWS版本。
#023 switch(osvi.dwPlatformId)
#024 {

这是WIN NT技术的版本。
#025 case VER_PLATFORM_WIN32_NT:
#026 {

是否是WIN NT。
#027 // Test for the product.
#028 if(osvi.dwMajorVersion <= 4)
#029 {
#030 mOSStringSimple = "Microsoft Windows NT ";
#031 }

是否是WIN 2000.
#032 else if(osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
#033 {
#034 mOSStringSimple = "Microsoft Windows 2000 ";
#035 }

是否是WIN XP。
#036 else if(osvi.dwMajorVersion ==5 && osvi.dwMinorVersion == 1)
#037 {
#038 mOSStringSimple = "Microsoft Windows XP ";
#039 }

是否WIN2003或XP 64位版本。
#040 else if(osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
#041 {
#042 if(osvi.wProductType == VER_NT_WORKSTATION)
#043 mOSStringSimple = "Microsoft Windows XP x64 Edition ";
#044 else
#045 mOSStringSimple = "Microsoft Windows Server 2003 ";
#046 }

是否是WIN VISTA。
#047 else if(osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0)
#048 {
#049 if(osvi.wProductType == VER_NT_WORKSTATION)
#050 mOSStringSimple = "Microsoft Windows Vista ";
#051 else mOSStringSimple = "Microsoft Windows Vista Server ";
#052 }

如果根据版本号都找不到,就直接读取注册表的信息。
#053 else // Use the registry on early versions of Windows NT.
#054 {
#055 HKEY hKey;
#056 WCHAR szProductType[80];
#057 DWORD dwBufLen;
#058 RegOpenKeyEx( HKEY_LOCAL_MACHINE,
#059 L"SYSTEM//CurrentControlSet//Control//ProductOptions",
#060 0, KEY_QUERY_VALUE, &hKey );
#061 RegQueryValueEx( hKey, L"ProductType", NULL, NULL,
#062 (LPBYTE) szProductType, &dwBufLen);
#063 RegCloseKey( hKey );
#064 if ( lstrcmpi( L"WINNT", szProductType) == 0 )
#065 {
#066 mOSStringSimple += "Professional ";
#067 }
#068 else if ( lstrcmpi( L"LANMANNT", szProductType) == 0 )
#069 {
#070 mOSStringSimple += "Server ";
#071 }
#072 else if ( lstrcmpi( L"SERVERNT", szProductType) == 0 )
#073 {
#074 mOSStringSimple += "Advanced Server ";
#075 }
#076 }
#077
#078 std::string csdversion = utf16str_to_utf8str(osvi.szCSDVersion);
#079 // Display version, service pack (if any), and build number.
#080 char tmp[MAX_STRING]; /* Flawfinder: ignore */
#081 if(osvi.dwMajorVersion <= 4)
#082 {
#083 snprintf( /* Flawfinder: ignore */
#084 tmp,
#085 sizeof(tmp),
#086 "version %d.%d %s (Build %d)",
#087 osvi.dwMajorVersion,
#088 osvi.dwMinorVersion,
#089 csdversion.c_str(),
#090 (osvi.dwBuildNumber & 0xffff));
#091 }
#092 else
#093 {
#094 snprintf( /* Flawfinder: ignore */
#095 tmp,
#096 sizeof(tmp),
#097 "%s (Build %d)",
#098 csdversion.c_str(),
#099 (osvi.dwBuildNumber & 0xffff));
#100 }
#101 mOSString = mOSStringSimple + tmp;
#102 }
#103 break;
#104

下面是WIN95,WIN98,WIN ME的版本号识别。
#105 case VER_PLATFORM_WIN32_WINDOWS:
#106 // Test for the Windows 95 product family.
#107 if(osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
#108 {
#109 mOSStringSimple = "Microsoft Windows 95 ";
#110 if ( osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B' )
#111 {
#112 mOSStringSimple += "OSR2 ";
#113 }
#114 }
#115 if(osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
#116 {
#117 mOSStringSimple = "Microsoft Windows 98 ";
#118 if ( osvi.szCSDVersion[1] == 'A' )
#119 {
#120 mOSStringSimple += "SE ";
#121 }
#122 }
#123 if(osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
#124 {
#125 mOSStringSimple = "Microsoft Windows Millennium Edition ";
#126 }
#127 mOSString = mOSStringSimple;
#128 break;
#129 }
#130 #else

下面LINUX的版本号识别。
#131 struct utsname un;
#132 if(uname(&un) != -1)
#133 {
#134 mOSStringSimple.append(un.sysname);
#135 mOSStringSimple.append(" ");
#136 mOSStringSimple.append(un.release);
#137
#138 mOSString = mOSStringSimple;
#139 mOSString.append(" ");
#140 mOSString.append(un.version);
#141 mOSString.append(" ");
#142 mOSString.append(un.machine);
#143
#144 // Simplify 'Simple'
#145 std::string ostype = mOSStringSimple.substr(0, mOSStringSimple.find_first_of(" ", 0));
#146 if (ostype == "Darwin")
#147 {
#148 // Only care about major Darwin versions, truncate at first '.'
#149 S32 idx1 = mOSStringSimple.find_first_of(".", 0);
#150 std::string simple = mOSStringSimple.substr(0, idx1);
#151 if (simple.length() > 0)
#152 mOSStringSimple = simple;
#153 }
#154 else if (ostype == "Linux")
#155 {
#156 // Only care about major and minor Linux versions, truncate at second '.'
#157 S32 idx1 = mOSStringSimple.find_first_of(".", 0);
#158 S32 idx2 = (idx1 != std::string::npos) ? mOSStringSimple.find_first_of(".", idx1+1) : std::string::npos;
#159 std::string simple = mOSStringSimple.substr(0, idx2);
#160 if (simple.length() > 0)
#161 mOSStringSimple = simple;
#162 }
#163 }
#164 else
#165 {
#166 mOSStringSimple.append("Unable to collect OS info");
#167 mOSString = mOSStringSimple;
#168 }
#169 #endif
#170
#171 }

上面主要通过WINDOWS的API函数GetVersionEx来获取版本信息,然后根据版本号获取相应的字符串信息。至于这个版本函数的使用,请参考我写的《Windows API一日一练》这本书。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: