zl程序教程

您现在的位置是:首页 >  工具

当前栏目

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

源码操作系统 实现 分析 获取 信息 第二 人生
2023-09-14 09:10:42 时间
由于信息产业在不断地发展,特别像电脑里的操作系统更是更新不断。比如 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一日一练》这本书。