UOS系统下获取硬盘序列号

#include <stdio.h>
#include <fcntl.h>
#include <scsi/scsi.h>
#include <scsi/sg.h>
#include <asm/types.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <net/if.h>
#include<sys/ioctl.h>

#define SG_CHECK_CONDITION    0x02

#define SG_DRIVER_SENSE        0x08



#define SG_ATA_16        0x85

#define SG_ATA_16_LEN        16



#define SG_ATA_LBA48        1

#define SG_ATA_PROTO_NON_DATA    ( 3 << 1)

#define SG_ATA_PROTO_PIO_IN    ( 4 << 1)

#define SG_ATA_PROTO_PIO_OUT    ( 5 << 1)

#define SG_ATA_PROTO_DMA    ( 6 << 1)

#define SG_ATA_PROTO_UDMA_IN    (11 << 1) /* not yet supported in libata */

#define SG_ATA_PROTO_UDMA_OUT    (12 << 1) /* not yet supported in libata */



#define ATA_USING_LBA        (1 << 6)



enum {
		ATA_OP_IDENTIFY            = 0xec,

    	//SG_CDB2_TLEN_NODATA    = 0 << 0,

		//SG_CDB2_TLEN_FEAT    = 1 << 0,

		SG_CDB2_TLEN_NSECT    = 2 << 0,

		

		//SG_CDB2_TLEN_BYTES    = 0 << 2,

		SG_CDB2_TLEN_SECTORS    = 1 << 2,

		

		//SG_CDB2_TDIR_TO_DEV    = 0 << 3,

		SG_CDB2_TDIR_FROM_DEV    = 1 << 3,

		

		SG_CDB2_CHECK_COND    = 1 << 5,

};





#define START_SERIAL 10 /* ASCII serial number */

#define LENGTH_SERIAL 10 /* 10 words (20 bytes or characters) */

void print_ascii(unsigned short *p, unsigned char length, char *SZID) {

    unsigned char ii;

    char cl;

    int len=0;

    for (ii = 0; ii< length; ii++) 
    {

        if(((char) 0x00ff&((*p)>>8)) != ' ') break;

        if((cl = (char) 0x00ff&(*p)) != ' ') 
        {

            if(cl != '\0')

			{

				SZID[len]=cl;

				len++;

				printf("%c",cl);

			}

            p++; ii++;

            break;

        }

        p++;

    }



    for (; ii < length; ii++) {

        __u8 c;

        c = (*p) >> 8;

        if (c)

		{

			SZID[len]=c;

			len++;

		}

        c = (*p);

        if (c) 

		{

			SZID[len]=c;

			len++;

		}

        p++;

    }

	SZID[len]='\n';

}

//获取硬盘ID
int get_sata_serial(char *szDevice, char *szid)
{
	int fd = 0;
	static __u8 args[512] = { 0 };

    __u16 *id = (__u16 *)(args);

    

    void *data = (void *)(args);

    unsigned int data_bytes = 512;
    
    unsigned char cdb[SG_ATA_16_LEN] = { 0 };

    unsigned char sb[32], *desc;

    unsigned char ata_status, ata_error;

    struct sg_io_hdr io_hdr;
	
	fd = open(szDevice,O_RDONLY);
	if(fd<0)
	{
		printf("open sda error.\n");
		return -1;
	}
	
	cdb[0] = SG_ATA_16;

    cdb[1] = SG_ATA_PROTO_PIO_IN;

    cdb[2] = SG_CDB2_CHECK_COND;

    cdb[2] |= SG_CDB2_TLEN_NSECT | SG_CDB2_TLEN_SECTORS;

    cdb[2] |= SG_CDB2_TDIR_FROM_DEV;

    cdb[13] = ATA_USING_LBA;

    cdb[14] = ATA_OP_IDENTIFY;


	memset(&(sb[0]), 0, sizeof(sb));
	
	//设置sg_io_hdr结构体
	memset(&io_hdr, 0, sizeof(struct sg_io_hdr));

    io_hdr.interface_id = 'S';	//必须是大"S",表示Scsi Generic.

    io_hdr.cmd_len      = SG_ATA_16_LEN;	//表示该scsi命令的长度,它必须<=16

    io_hdr.mx_sb_len	= sizeof(sb);

    io_hdr.dxfer_direction    = SG_DXFER_FROM_DEV;	//表示数据传输方向,比如对于写命令该变量可取值为SG_DXFER_TO_DEV,对于读命令则取SG_DXFER_FROM_DEV

    io_hdr.dxfer_len	= data_bytes;	//表示数据传输阶段会传输多少字节

    io_hdr.dxferp       = data;

    io_hdr.cmdp    	    = cdb;

    io_hdr.sbp			= sb;

    io_hdr.timeout    	= 10000; /* msecs */
    
	if (ioctl(fd, SG_IO, &io_hdr) == -1) {

        fprintf(stderr, "SG_IO ioctl not supported\n");

        return -1;    /* SG_IO not supported */

    }
    
    if (io_hdr.host_status || io_hdr.driver_status != SG_DRIVER_SENSE

     || (io_hdr.status && io_hdr.status != SG_CHECK_CONDITION))

    {

		errno = EIO;

        return -2;

    }
    
    if (sb[0] != 0x72 || sb[7] < 14) {

        errno = EIO;

        return -3;

    }

    desc = sb + 8;

    if (desc[0] != 9 || desc[1] < 12){

        errno = EIO;

        return -4;
    }



    ata_error = desc[3];

    ata_status = desc[13];

    if (ata_status & 0x01) {    /* ERR_STAT */

        errno = EIO;

        return -5;
    }

	print_ascii( &id[START_SERIAL], LENGTH_SERIAL, szid);
return 0;
}

int main(void)
{
	char szid[64] = { 0 };	
	get_sata_serial((char*)"/dev/sda", szid);
	printf("硬盘系列号为:%s\n",szid);

}

记录一下UOS系统下的硬件信息获取方式,测试可用。系统:UOSx86_x64桌面专业版

以g++ xxx.cpp -o xxx 编译,执行时需要以权限的方式运行:sudo ./xxx

参考:https://bbs.csdn.net/topics/310003001

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值