获取序列号和型号信息的 scsi 查询命令

Posted

技术标签:

【中文标题】获取序列号和型号信息的 scsi 查询命令【英文标题】:scsi inquiry commands to get serial and model information 【发布时间】:2014-03-08 19:06:18 【问题描述】:

我在通过查询从 SCSI 驱动器获取序列号和型号信息时遇到问题。我的查询总是返回空字符串。

这是一个快速而肮脏的查询代码,它至少应该输出查询的整个返回。输出未格式化以真正获取特定信息,但它仍然可以工作。但事实并非如此。

#define          DRIVEAMOUNT                20
#define          MODELINQUIRY               0x12,0x00,0x00,0x00,0x4A,0x00     /* SCSI command for standard inquiry*/
#define          SERIALINQUIRY              0x12,0x01,0x80,0x00,0x60,0x00     /* SCSI command for VPD inquiry page 0x80 for serial number */

/* used libraries */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <scsi/sg.h>
#include <inttypes.h>

/* send scsi command and recieve output, designed for use with *ONLY* an inquiry command but might work with more than only inquiry*/
int SCSI_sendcmd(uint64_t sg_fd, unsigned char *cmdblk, char *output) 
    unsigned char reply_buffer[96];
    sg_io_hdr_t  io_hdr;
    int i;

    /* Send INQUIRY command */
    memset(&io_hdr,0,sizeof(sg_io_hdr_t));
    io_hdr.interface_id='S';
    io_hdr.dxfer_direction=SG_DXFER_FROM_DEV;
    io_hdr.dxfer_len=sizeof(reply_buffer);
    io_hdr.dxferp=reply_buffer;
    io_hdr.cmd_len=sizeof(cmdblk);
    io_hdr.cmdp=cmdblk;
    io_hdr.timeout=1000;

    if (ioctl(sg_fd,SG_IO,&io_hdr)<0) return 3;   /* cannot send inquiry command */

    if ((io_hdr.info&SG_INFO_OK_MASK)!=SG_INFO_OK) return 2;  /* inquiry command failed */

    for (i=0;i<96;i++) 
       output[i]=reply_buffer[i];
    
    return 1; /*succes*/


int main () 
    /* initialize various vars.*/
    FILE                                    *driveptr; 

    int                                     i;

    char                                    OSpointer[9];

    unsigned char                           output1[96],
                                            output2[96],
                                            serialinq[6]=SERIALINQUIRY,                          /* var to store SCSI inquiry for serial number */
                                            modelinq[6]=MODELINQUIRY;                            /* var to store SCSI inquiry for model string */

    for (i=0;i<DRIVEAMOUNT;i++) 
        strcpy(OSpointer,"/dev/sdX");
        OSpointer[7]='a'+i;

        driveptr=fopen(OSpointer,"r");
        if (driveptr==NULL) 
            continue;
        

        if (SCSI_sendcmd(fileno(driveptr),modelinq,output1)==1)  printf("model:|%s|\n",output1);
        if (SCSI_sendcmd(fileno(driveptr),serialinq,output2)==1) printf("serial:|%s|\n",output2);
        printf("\n");

        fclose(driveptr);
     

【问题讨论】:

【参考方案1】:

字符串的前半部分有终止('\0') 字符,%s 只打印出来,直到达到这样的字符!要么删除它们,要么循环打印出每个字符!

【讨论】:

这没有提供问题的答案。要批评或要求作者澄清,请在他们的帖子下方发表评论 - 您可以随时评论自己的帖子,一旦您有足够的reputation,您就可以comment on any post。【参考方案2】:
for (i=0;i<96;i++) 
       output[i]=reply_buffer[i];

应该从reply_buffer[4]开始

【讨论】:

【参考方案3】:

使用SCSI_sendcmd() 的调试器检查replay_bufferoutput 的内容会显示结果的样子。 示例(gdb):

(gdb) n
34         output[i]=reply_buffer[i];
(gdb) p reply_buffer 
$2 = "\000\000\005\002[\000\000\000ATA     WDC WD7500AVDS-60A01", '\000' <repeats 23 times>, "`\003 \002`", '\000' <repeats 31 times>

【讨论】:

以上是关于获取序列号和型号信息的 scsi 查询命令的主要内容,如果未能解决你的问题,请参考以下文章

Linux 查询服务器序列号命令

电脑主要硬件配置信息查询

linux系统下查看服务器的型号等信息

Linux通过命令查询服务器型号主板CPU内存及硬盘信息

获取硬盘序列号

Linux下获取CPU内存信息的命令