欢迎来到【winform源码之家】【飞书日历源码】【inv函数源码】cpuid源码-皮皮网网站!!!

皮皮网

【winform源码之家】【飞书日历源码】【inv函数源码】cpuid源码-皮皮网 扫描左侧二维码访问本站手机端

【winform源码之家】【飞书日历源码】【inv函数源码】cpuid源码

2024-12-24 09:36:23 来源:{typename type="name"/} 分类:{typename type="name"/}

1.linux设备驱动程序——设备树(0)-dtb格式
2.VB如何获取硬件信息比如CPU温度,显卡,CPUID号之类的、
3.VC++ MFC如何获取CPU ID及硬盘的序列号?

cpuid源码

linux设备驱动程序——设备树(0)-dtb格式

       设备树的一般操作方式是:开发人员根据开发需求编写dts文件,然后使用dtc将dts编译成dtb文件。

       dts文件是winform源码之家文本格式的文件,而dtb是二进制文件,在linux启动时被加载到内存中,接下来我们需要来分析设备树dtb文件的格式。

       为什么要了解设备树dtb文件的格式

       dtb作为二进制文件被加载到内存中,然后由内核读取并进行解析,如果对dtb文件的格式不了解,那么在看设备树解析相关的内核代码时将会寸步难行,而阅读源代码才是了解设备树最好的方式,所以,飞书日历源码如果需要更透彻的了解设备树解析的细节,第一步就是需要了解设备树的格式。

       dtb格式总览

       dtb的格式是这样的:

       dtb header

       但凡涉及到数据的记录,就一定会有一个总的描述部分,就像磁盘的超级块,书的目录,dtb当然也不例外,这个描述头部就是dtb的header部分,通过这个header部分,用户可以快速地了解到整个dtb的大致信息。

       header可以用这么一个结构体来描述:

       magic

       设备树的魔数,魔数其实就是一个用于识别的数字,表示设备树的开始,linux dtb的inv函数源码魔数为 0xddfeed.

       totalsize

       这个设备树的size,也可以理解为所占用的实际内存空间。

       off_dt_struct

       offset to dt_struct,表示整个dtb中structure部分所在内存相对头部的偏移地址

       off_dt_strings

       offset to dt_string,表示整个dtb中string部分所在内存相对头部的偏移地址

       off_mem_rsvmap

       offset to memory reserve map,dtb中memory reserve map所在内存相对头部的偏移地址,

       version

       设备树的版本,截至目前的最新版本为.

       last_comp_version

       最新的兼容版本

       boot_cpuid_phys

       这部分仅在版本2中存在,后续版本不再使用。

       size_dt_strings

       表示整个dtb中string部分的大小

       size_dt_struct

       表示整个dtb中struct部分的大小

       alignment gap

       中间的alignment gap部分表示对齐间隙,它并非是必须的,它是否被提供以及大小由具体的平台对数据对齐和的要求以及数据是否已经对齐来决定。

       memory reserve map

       memory reserve map:描述保留的内存部分,这个map的数据结构是这样的:

       这部分存储了此结构的列表,整个部分的查看收费源码结尾由一个数据为0的结构来表示(即physical_address和size都为0,总共字节)。

       这一部分的数据并非是节点中的memory子节点,而是在设备开始之前(也就是第一个花括号之前)定义的,例如:

       这一部分的作用是告诉内核哪一些内存空间需要被保留而不应该被系统覆盖使用,因为在内核启动时常常需要动态申请大量的内存空间,只有提前进行注册,用户需要使用的内存才不会被系统征用而造成数据覆盖。

       值得一提的是,对于设备树而言,即使不指定保留内存,系统也会默认为设备树保留相应的内存空间。

       同时,这一部分需要位(8字节)对齐。

       device-tree structure

       device-tree structure:每个节点都会被描述为一个struct,节点之间可以嵌套,蓝帝源码因此也会有嵌套的struct。

       structure的的结构是这样的:

       device-tree strings

       device-tree strings:在dtb中有大量的重复字符串,比如"model","compatile"等等,为了节省空间,将这些字符串统一放在某个地址,需要使用的时候直接使用索引来查看。

       需要注意的是,属性部分格式为key = value,key部分被放置在strings部分,而value部分的字符串并不会放在这一部分,而是直接放在structure中。

       dtb文件解析示例

       光说不练假把式,下面我就使用一个简单的示例来剖析dtb的文件格式。

       下述示例仅仅是一个演示demo,不针对任何平台,为了演示方便,编写了一个非常简单的dts文件。 /dts-v1/; / {

       编译当前dts文件,获取对应的dtb文件。

       鉴于dtb文件为二进制文件,普通编辑器打开显示乱码,我们使用ultraEdit查看,它将数据以进制形式显示:

       整个dtb文件还是比较简单的,图中的红色框出的部分为header部分的数据,可以看到:

       整个头部为字节,进制为0x,从头部信息中off_mem_rsvmap部分可以得到,reserve memory起始地址为0x,上文中提到,这一部分使用一个字节的struct来描述,以一个全为0的struct结尾。

       后字节全为0,可以看出,这里并没有设置reserve memory。

       structure 部分

       上文回顾:每一个属性都是以 key = value的形式来描述,value部分可选。

       偏移地址来到0x(0x+0x),接下来8个字节为,根据上述structure中的描述,这是OF_DT_PROP,即标示属性的开始。

       接下来4字节为,表明该属性的value部分size为字节。

       接下来4字节是当前属性的key在string 部分的偏移地址,这里是,由头部信息中off_dt_strings可以得到,string部分的开始为,偏移地址为0,所以对应字符串为"compatible".

       之后就是value部分,这部分的数据是字符串,可以直接从右侧栏看出,总共字节的字符串"hd,test_dts", "hd,test_xxx",因为字符串之间以0结尾,所以程序可以识别出这是两个字符串。

       可以看出,到这里,compatible = "hd,test_dts", "hd,test_xxx";这个属性就被描述完了,对于属性的描述还是非常简单的。

       按照固有的规律,接下来就是对#address-cells = <0x1>的解析,然后是#size-cells = <0x1>...

       然后就是递归的子节点chosen,memory@等等都是按照上文中提到的structure解析规则来进行解析,最后以结尾。

       与根节点不同的是,子节点有一个unit name,即chosen,memory@这些名称,并非节点中的.name属性。

       而整个结构的结束由来描述。

       一般而言,在位系统中,dtc在编译dts文件时会自动考虑对齐问题,所以对于设备树的对齐字节,我们只需要有所了解即可,并不会常接触到。

       好了,关于linux设备树dtb文件格式的讨论就到此为止啦。

VB如何获取硬件信息比如CPU温度,显卡,CPUID号之类的、

         Dim MemoyCounter As New ComputerInfo()

          Dim CPUCounter As New PerformanceCounter("Processor", "% Processor Time", "_Total")

          Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick

           Dim CPU As Double = CPUCounter.NextValue

           Dim neicun As Double = (MemoyCounter.TotalPhysicalMemory - MemoyCounter.AvailablePhysicalMemory) / MemoyCounter.TotalPhysicalMemory * %

       获取CPU及物理内存使用率

VC++ MFC如何获取CPU ID及硬盘的序列号?

       // “获得Intel CPU ID”按钮消息处理函数

       void CIntelCPUIDDlg::OnBtnCPUID()

       {

        unsigned long s1,s2;

        unsigned char vendor_id[]="------------";//CPU提供商ID

        CString str1,str2,str3;

        // 以下为获得CPU ID的汇编语言指令

        _asm // 得到CPU提供商信息

        {

        xor eax,eax // 将eax清0

        cpuid // 获取CPUID的指令

        mov dword ptr vendor_id,ebx

        mov dword ptr vendor_id[+4],edx

        mov dword ptr vendor_id[+8],ecx

        }

        str1.Format("%s",vendor_id);

        _asm // 得到CPU ID的高位

        {

        mov eax,h

        xor edx,edx

        cpuid

        mov s2,eax

        }

        str2.Format("%X-",s2);

        _asm // 得到CPU ID的低位

        {

        mov eax,h

        xor ecx,ecx

        xor edx,edx

        cpuid

        mov s1,edx

        mov s2,ecx

        }

        str3.Format("%X-%X\n",s1,s2);

        str2=str2+str3;

        m_editVendor.SetWindowText(str1);

        m_editCPUID.SetWindowText(str2);

       }

       // GetHDSerial.cpp: implementation of the CGetHDSerial class.

       //

       //////////////////////////////////////////////////////////////////////

       #include "stdafx.h"

       #include "GetHDSerial.h"

       char m_buffer[];

       WORD m_serial[];

       DWORD m_OldInterruptAddress;

       DWORDLONG m_IDTR;

       // 等待硬盘空闲

       static unsigned int WaitHardDiskIdle()

       {

        BYTE byTemp;

       Waiting:

        _asm

        {

        mov dx, 0x1f7

        in al, dx

        cmp al, 0x

        jb Endwaiting

        jmp Waiting

        }

       Endwaiting:

        _asm

        {

        mov byTemp, al

        }

        return byTemp;

       }

       //中断服务程序

       void _declspec( naked )InterruptProcess(void)

       {

        int byTemp;

        int i;

        WORD temp;

        //保存寄存器值

        _asm

        {

        push eax

        push ebx

        push ecx

        push edx

        push esi

        }

        WaitHardDiskIdle();//等待硬盘空闲状态

        _asm

        {

        mov dx, 0x1f6

        mov al, 0xa0

        out dx, al

        }

        byTemp = WaitHardDiskIdle(); //若直接在Ring3级执行等待命令,会进入死循环

        if ((byTemp&0x)!=0x)

        {

        _asm // 恢复中断现场并退出中断服务程序

        {

        pop esi

        pop edx

        pop ecx

        pop ebx

        pop eax

        iretd

        }

        }

        _asm

        {

        mov dx, 0x1f6 //命令端口1f6,选择驱动器0

        mov al, 0xa0

        out dx, al

        inc dx

        mov al, 0xec

        out dx, al //发送读驱动器参数命令

        }

        byTemp = WaitHardDiskIdle();

        if ((byTemp&0x)!=0x)

        {

        _asm // 恢复中断现场并退出中断服务程序

        {

        pop esi

        pop edx

        pop ecx

        pop ebx

        pop eax

        iretd

        }

        }

        //读取硬盘控制器的全部信息

        for (i=0;i<;i++)

        {

        _asm

        {

        mov dx, 0x1f0

        in ax, dx

        mov temp, ax

        }

        m_serial[i] = temp;

        }

        _asm

        {

        pop esi

        pop edx

        pop ecx

        pop ebx

        pop eax

        iretd

        }

       }

       //////////////////////////////////////////////////////////////////////

       // Construction/Destruction

       //////////////////////////////////////////////////////////////////////

       CGetHDSerial::CGetHDSerial()

       {

       }

       CGetHDSerial::~CGetHDSerial()

       {

       }

       // 读取硬盘序列号函数

       char* CGetHDSerial::GetHDSerial()

       {

        m_buffer[0]='\n';

        // 得到当前操作系统版本

        OSVERSIONINFO OSVersionInfo;

        OSVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);

        GetVersionEx( &OSVersionInfo);

        if (OSVersionInfo.dwPlatformId != VER_PLATFORM_WIN_NT)

        {

        // Windows 9x/ME下读取硬盘序列号

        WORD m_wWin9xHDSerial[];

        Win9xReadHDSerial(m_wWin9xHDSerial);

        strcpy (m_buffer, WORDToChar (m_wWin9xHDSerial, , ));

        }

        else

        {

        // Windows NT//XP下读取硬盘序列号

        DWORD m_wWinNTHDSerial[];

        // 判断是否有SCSI硬盘

        if ( ! WinNTReadIDEHDSerial(m_wWinNTHDSerial))

        WinNTReadSCSIHDSerial(m_wWinNTHDSerial);

        strcpy (m_buffer, DWORDToChar (m_wWinNTHDSerial, , ));

        }

        return m_buffer;

       }

       // Windows9X/ME系统下读取硬盘序列号

       void _stdcall CGetHDSerial::Win9xReadHDSerial(WORD * buffer)

       {

        int i;

        for(i=0;i<;i++)

        buffer[i]=0;

        _asm

        {

        push eax

        //获取修改的中断的中断描述符(中断门)地址

        sidt m_IDTR

        mov eax,dword ptr [m_IDTR+h]

        add eax,3*h+h

        cli

        //保存原先的中断入口地址

        push ecx

        mov ecx,dword ptr [eax]

        mov cx,word ptr [eax-h]

        mov dword ptr m_OldInterruptAddress,ecx

        pop ecx

        //设置修改的中断入口地址为新的中断处理程序入口地址

        push ebx

        lea ebx,InterruptProcess

        mov word ptr [eax-h],bx

        shr ebx,h

        mov word ptr [eax+h],bx

        pop ebx

        //执行中断,转到Ring 0(类似CIH病毒原理)

        int 3h

        //恢复原先的中断入口地址

        push ecx

        mov ecx,dword ptr m_OldInterruptAddress

        mov word ptr [eax-h],cx

        shr ecx,h

        mov word ptr [eax+h],cx

        pop ecx

        sti

        pop eax

        }

        for(i=0;i<;i++)

        buffer[i]=m_serial[i];

       }

       // Windows 9x/ME系统下,将字类型(WORD)的硬盘信息转换为字符类型(char)

       char * CGetHDSerial::WORDToChar (WORD diskdata [], int firstIndex, int lastIndex)

       {

        static char string [];

        int index = 0;

        int position = 0;

        // 按照高字节在前,低字节在后的顺序将字数组diskdata 中内容存入到字符串string中

        for (index = firstIndex; index <= lastIndex; index++)

        {

        // 存入字中的高字节

        string [position] = (char) (diskdata [index] / );

        position++;

        // 存入字中的低字节

        string [position] = (char) (diskdata [index] % );

        position++;

        }

        // 添加字符串结束标志

        string [position] = '\0';

        // 删除字符串中空格

        for (index = position - 1; index > 0 && ' ' == string [index]; index--)

        string [index] = '\0';

        return string;

       }

       // Windows NT//XP系统下,将双字类型(DWORD)的硬盘信息转换为字符类型(char)

       char* CGetHDSerial::DWORDToChar (DWORD diskdata [], int firstIndex, int lastIndex)

       {

        static char string [];

        int index = 0;

        int position = 0;

        // 按照高字节在前,低字节在后的顺序将双字中的低字存入到字符串string中

        for (index = firstIndex; index <= lastIndex; index++)

        {

        // 存入低字中的高字节

        string [position] = (char) (diskdata [index] / );

        position++;

        // 存入低字中的低字节

        string [position] = (char) (diskdata [index] % );

        position++;

        }

        // 添加字符串结束标志

        string [position] = '\0';

        // 删除字符串中空格

        for (index = position - 1; index > 0 && ' ' == string [index]; index--)

        string [index] = '\0';

        return string;

       }

       // Windows NT//XP下读取IDE硬盘序列号

       BOOL CGetHDSerial::WinNTReadIDEHDSerial(DWORD * buffer)

       {

        BYTE IdOutCmd [sizeof (SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];

        BOOL bFlag = FALSE;

        int drive = 0;

        char driveName [];

        HANDLE hPhysicalDriveIOCTL = 0;

        sprintf (driveName, "\\\\.\\PhysicalDrive%d", drive);

        // Windows NT//XP下创建文件需要管理员权限

        hPhysicalDriveIOCTL = CreateFile (driveName,

        GENERIC_READ | GENERIC_WRITE,

        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,

        OPEN_EXISTING, 0, NULL);

        if (hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)

        {

        GETVERSIONOUTPARAMS VersionParams;

        DWORD cbBytesReturned = 0;

        // 得到驱动器的IO控制器版本

        memset ((void*) &VersionParams, 0, sizeof(VersionParams));

        if(DeviceIoControl (hPhysicalDriveIOCTL, IOCTL_GET_VERSION,

        NULL, 0, &VersionParams,

        sizeof(VersionParams),

        &cbBytesReturned, NULL) )

        {

        if (VersionParams.bIDEDeviceMap > 0)

        {

        BYTE bIDCmd = 0; // IDE或者ATAPI识别命令

        SENDCMDINPARAMS scip;

        // 如果驱动器是光驱,采用命令IDE_ATAPI_IDENTIFY, command,

        // 否则采用命令IDE_ATA_IDENTIFY读取驱动器信息

        bIDCmd = (VersionParams.bIDEDeviceMap >> drive & 0x)?

        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;

        memset (&scip, 0, sizeof(scip));

        memset (IdOutCmd, 0, sizeof(IdOutCmd));

        // 获取驱动器信息

        if (WinNTGetIDEHDInfo (hPhysicalDriveIOCTL,

        &scip,

        (PSENDCMDOUTPARAMS)&IdOutCmd,

        (BYTE) bIDCmd,

        (BYTE) drive,

        &cbBytesReturned))

        {

        int m = 0;

        USHORT *pIdSector = (USHORT *)

        ((PSENDCMDOUTPARAMS) IdOutCmd) -> bBuffer;

        for (m = 0; m < ; m++)

        buffer[m] = pIdSector [m];

        bFlag = TRUE; // 读取硬盘信息成功

        }

        }

        }

        CloseHandle (hPhysicalDriveIOCTL); // 关闭句柄

        }

        return bFlag;

       }

       // WindowsNT//XP系统下读取SCSI硬盘序列号

       BOOL CGetHDSerial::WinNTReadSCSIHDSerial (DWORD * buffer)

       {

        buffer[0]='\n';

        int controller = 0;

        HANDLE hScsiDriveIOCTL = 0;

        char driveName [];

        sprintf (driveName, "\\\\.\\Scsi%d:", controller);

        // Windows NT//XP下任何权限都可以进行

        hScsiDriveIOCTL = CreateFile (driveName,

        GENERIC_READ | GENERIC_WRITE,

        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,

        OPEN_EXISTING, 0, NULL);

        if (hScsiDriveIOCTL != INVALID_HANDLE_VALUE)

        {

        int drive = 0;

        DWORD dummy;

        for (drive = 0; drive < 2; drive++)

        {

        char buffer [sizeof (SRB_IO_CONTROL) + SENDIDLENGTH];

        SRB_IO_CONTROL *p = (SRB_IO_CONTROL *) buffer;

        SENDCMDINPARAMS *pin =

        (SENDCMDINPARAMS *) (buffer + sizeof (SRB_IO_CONTROL));

        // 准备参数

        memset (buffer, 0, sizeof (buffer));

        p -> HeaderLength = sizeof (SRB_IO_CONTROL);

        p -> Timeout = ;

        p -> Length = SENDIDLENGTH;

        p -> ControlCode = IOCTL_SCSI_MINIPORT_IDENTIFY;

        strncpy ((char *) p -> Signature, "SCSIDISK", 8);

        pin -> irDriveRegs.bCommandReg = IDE_ATA_IDENTIFY;

        pin -> bDriveNumber = drive;

        // 得到SCSI硬盘信息

        if (DeviceIoControl (hScsiDriveIOCTL, IOCTL_SCSI_MINIPORT,

        buffer,

        sizeof (SRB_IO_CONTROL) +

        sizeof (SENDCMDINPARAMS) - 1,

        buffer,

        sizeof (SRB_IO_CONTROL) + SENDIDLENGTH,

        &dummy, NULL))

        {

        SENDCMDOUTPARAMS *pOut =

        (SENDCMDOUTPARAMS *) (buffer + sizeof (SRB_IO_CONTROL));

        IDSECTOR *pId = (IDSECTOR *) (pOut -> bBuffer);

        if (pId -> sModelNumber [0])

        {

        int n = 0;

        USHORT *pIdSector = (USHORT *) pId;

        for (n = 0; n < ; n++)

        buffer[n] =pIdSector [n];

        return TRUE; // 读取成功

        }

        }

        }

        CloseHandle (hScsiDriveIOCTL); // 关闭句柄

        }

        return FALSE; // 读取失败

       }

       // Windows NT//XP下读取IDE设备信息

       BOOL CGetHDSerial::WinNTGetIDEHDInfo (HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,

        PSENDCMDOUTPARAMS pSCOP, BYTE bIDCmd, BYTE bDriveNum,

        PDWORD lpcbBytesReturned)

       {

        // 为读取设备信息准备参数

        pSCIP -> cBufferSize = IDENTIFY_BUFFER_SIZE;

        pSCIP -> irDriveRegs.bFeaturesReg = 0;

        pSCIP -> irDriveRegs.bSectorCountReg = 1;

        pSCIP -> irDriveRegs.bSectorNumberReg = 1;

        pSCIP -> irDriveRegs.bCylLowReg = 0;

        pSCIP -> irDriveRegs.bCylHighReg = 0;

        // 计算驱动器位置

        pSCIP -> irDriveRegs.bDriveHeadReg = 0xA0 | ((bDriveNum & 1) << 4);

        // 设置读取命令

        pSCIP -> irDriveRegs.bCommandReg = bIDCmd;

        pSCIP -> bDriveNumber = bDriveNum;

        pSCIP -> cBufferSize = IDENTIFY_BUFFER_SIZE;

        // 读取驱动器信息

        return ( DeviceIoControl (hPhysicalDriveIOCTL, IOCTL_GET_DRIVE_INFO,

        (LPVOID) pSCIP,

        sizeof(SENDCMDINPARAMS) - 1,

        (LPVOID) pSCOP,

        sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,

        lpcbBytesReturned, NULL) );

       }