当前位置: 首页 > 面试题库 >

Linux C ++下的USB驱动器序列号

龙晟睿
2023-03-14
问题内容

有什么方法可以确定使用C ++的linux中USB驱动器的s / n吗?

如果不是的话,C ++是否与hwinfo -diskand 有任何其他区别hdparm -i


问题答案:

我将尝试总结有关在Linux上进行存储驱动器序列号检索的经验。
我假设您要 存储设备 标识的序列号(按照SCSI规范)而不是 USB设备 的序列号(按照Device
Descriptor
下的USB规范),这两个是不同的实体。

注意!
大多数设备倾向于在USB控制器中实现序列号,而内部SCSI磁盘的序列号未实现。

因此,如果要唯一地标识USB设备,最好的方法是从设备描述符(USB规范)创建字符串,例如
VendorId-ProductId-HardwareRevision-SerialNumber
。在下面,我将描述如何检索存储驱动器的SN ,按要求。

驱动器分为两类(实际上更多,但让我们简化一下):类ATA(hda,hdb …)和类SCSI(sda sdb …)。USB驱动器属于第二类,它们称为
SCSI连接磁盘
。在这两种情况下,都可以使用ioctl调用来检索所需的信息(在我们的情况下为序列号)。

对于 SCSI设备(包括USB驱动器)
,Linux通用驱动程序及其API记录在tldp上。
SCSI设备上的序列号可在重要产品数据(简称:VPD)中找到,并且可以使用SCSI查询命令检索。sdparm是linux中一个可获取此VPD的通用实用程序:

> yum install sdparm
> sdparm --quiet --page=sn /dev/sda
    Unit serial number VPD page:
    3BT1ZQGR000081240XP7

请注意,并非所有设备都具有该序列号,市场上充斥着廉价的仿冒品,一些USB闪存盘返回了奇怪的序列号(例如,我的s​​andisk cruzer仅返回字母“
u”)。为了克服这个问题,有人选择通过混合来自VPD的不同字符串(例如产品ID,供应商ID和序列号)来创建唯一标识符。

C中的代码:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <scsi/scsi.h>
#include <scsi/sg.h>
#include <sys/ioctl.h>

int scsi_get_serial(int fd, void *buf, size_t buf_len) {
    // we shall retrieve page 0x80 as per http://en.wikipedia.org/wiki/SCSI_Inquiry_Command
    unsigned char inq_cmd[] = {INQUIRY, 1, 0x80, 0, buf_len, 0};
    unsigned char sense[32];
    struct sg_io_hdr io_hdr;
            int result;

    memset(&io_hdr, 0, sizeof (io_hdr));
    io_hdr.interface_id = 'S';
    io_hdr.cmdp = inq_cmd;
    io_hdr.cmd_len = sizeof (inq_cmd);
    io_hdr.dxferp = buf;
    io_hdr.dxfer_len = buf_len;
    io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
    io_hdr.sbp = sense;
    io_hdr.mx_sb_len = sizeof (sense);
    io_hdr.timeout = 5000;

    result = ioctl(fd, SG_IO, &io_hdr);
    if (result < 0)
        return result;

    if ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK)
        return 1;

    return 0;
}

int main(int argc, char** argv) {
    char *dev = "/dev/sda";
    char scsi_serial[255];
    int rc;
    int fd;

    fd = open(dev, O_RDONLY | O_NONBLOCK);
    if (fd < 0) {
        perror(dev);
    }

    memset(scsi_serial, 0, sizeof (scsi_serial));
    rc = scsi_get_serial(fd, scsi_serial, 255);
    // scsi_serial[3] is the length of the serial number
    // scsi_serial[4] is serial number (raw, NOT null terminated)
    if (rc < 0) {
        printf("FAIL, rc=%d, errno=%d\n", rc, errno);
    } else
    if (rc == 1) {
        printf("FAIL, rc=%d, drive doesn't report serial number\n", rc);
    } else {
        if (!scsi_serial[3]) {
            printf("Failed to retrieve serial for %s\n", dev);
            return -1;
        }
        printf("Serial Number: %.*s\n", (size_t) scsi_serial[3], (char *) & scsi_serial[4]);
    }
    close(fd);

    return (EXIT_SUCCESS);
}

为了完善起见,我还将提供代码以检索 ATA设备 的序列号(hda,hdb …)。这不适用于USB设备。

#include <stdlib.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <linux/hdreg.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <cctype>
#include <unistd.h>

int main(){
    struct hd_driveid *id;
    char *dev = "/dev/hda";
    int fd;

    fd = open(dev, O_RDONLY|O_NONBLOCK);
    if(fd < 0) {
        perror("cannot open");
    }
    if (ioctl(fd, HDIO_GET_IDENTITY, id) < 0) {
        close(fd);
        perror("ioctl error");
    } else {
        // if we want to retrieve only for removable drives use this branching
        if ((id->config & (1 << 7)) || (id->command_set_1 & 4)) {
            close(fd);
            printf("Serial Number: %s\n", id->serial_no);
        } else {
            perror("support not removable");
        }
        close(fd);
    }
}


 类似资料:
  • 问题内容: 每当将任何USB闪存驱动器(不仅是特定的USB闪存驱动器)插入系统时,我都试图运行一个脚本,并且我已经断断续续地花了大约2周的时间来尝试找出问题。有谁能够帮助我?(如果有帮助,请运行Ubuntu)。 我需要至少传递驱动器序列号和devpath(/ dev / sd **)。 问题答案: 首先,您需要使用规则来检测USB存储设备 /etc/udev/rules.d/10-usbmount

  • 问题内容: 我想知道如何检测USB驱动器。但是我想知道我们是否可以用来检查USB驱动器。我读过的帖子确实解释了如何使用,但我不太了解。如果有人可以提供示例,那就太好了。谢谢。 问题答案: 您可以使用File.listRoots()方法。 这里的问题是,您将需要一个名称或其他信息来将驱动器标识为USB驱动器。否则,您无法使用这种方法告诉普通驱动器和USB驱动器。

  • 问题内容: 我正在尝试从 Raspberry Pi 上的 Android Things 应用的USB驱动器中读取文件。我可以像这样扫描已安装设备的列表: __ 显示以下输出: 但是,我的拇指驱动器不在列表中。所以我想我需要以某种方式安装它。如何安装拇指驱动器并访问其中的文件? 问题答案: 仅亚行解决方案 到目前为止,USB驱动器似乎尚未自动安装。为了使您的代码正常工作,我必须手动安装它。 如您所见

  • 问题内容: 我正在做一个项目,我需要使用基于USB的数字签名来签署pdf。我已经在本地尝试了以下代码,并且能够对pdf进行签名。我的问题是天气,以下代码将在基于客户端服务器的senerio中工作。 我的代码是: 请给我建议。谢谢大家 问题答案: 您使用了错误的iText版本,因此您创建的签名不能为将来使用(请阅读本书以了解代码有什么问题)。 您取决于操作系统是Windows的事实。您的服务器也是W

  • 我正在尝试Google Drive API V3。 拥有一些共享驱动器文件夹的访问权限,并且是所有这些资源的管理员,我想获取一个通过查询筛选的特定文件夹。 出于任何原因,当我尝试按照留档建议插入查询时,它会响应一个错误,这个错误不是很描述性,也不利于调试: 此外,如果我不带条件地执行查询,则响应会成功,并显示整个共享驱动器: 有什么帮助吗? 谢谢

  • 问题内容: 我从LDD3第14章读到了有关热插拔驱动程序的信息。我需要编写一个USB鼠标驱动程序,在插入硬件时会加载该驱动程序。现在,通过做一些实验,我知道有一个名为“ hid-generic”的驱动程序,在插拔时会被调用。 另外,lsmod显示 我的疑问如下 1)为了在插入此鼠标时加载模块(hotplug),我必须在内核中禁用这3个驱动程序,并使用id_table中具有供应商和设备ID的驱动程序