我想知道如何获得USB存储设备的唯一ID。 我已经知道如何从这篇文章中获取SCSI序列号:USB-drive serial number under linux C++ 该帖子提到使用设备描述符来获取ID。有人可以发布一些代码来确定Linux下的设备描述符信息吗?
答案 0 :(得分:2)
ls -l /dev/disk/by-id
答案 1 :(得分:2)
答案 2 :(得分:2)
答案 3 :(得分:1)
添加其他人所说的内容:
USB设备并不总是有序列号;即使存在一个,也不能保证全球唯一。 (例如,我的Apple USB键盘没有序列号和GoPro cameras all have the same bogus serial number of 123456789ABC
。)因此,并不总是可以唯一地识别设备。
答案 4 :(得分:1)
使用USB,"设备名称"设备的连接可能会发生变化,具体取决于设备的连接顺序。 令人惊讶的是,很少有设备具有真实序列号。 如果您无法从设备本身获得唯一标识,唯一的解决方案是依赖于连接的物理地址。如果您将设备插入另一个USB连接器,则其缺点是地址会发生变化。
以编程方式,您可以使用sysfs获取内核所拥有的有关设备的信息。 Sysfs是一种类似文件系统的设备表示,就像内核看到它们一样。 (它不是磁盘上的真实文件)
有了它,你可以: - 使用产品和供应商ID识别设备类型 - 读取设备的序列号(如果有)。 - 读取USB集线器上的物理连接号
您可以从/ sys / class中查找设备类型开始。在这个例子中,我使用USB→LPT端口。但原则是一样的。
$ ls -l /sys/class/usbmisc
lp1 -> ../../devices/pci0000:00/0000:00:1d.0/usb4/4-1/4-1.5/4-1.5:1.0/usbmisc/lp1
lp2 -> ../../devices/pci0000:00/0000:00:1d.0/usb4/4-1/4-1.6/4-1.6:1.0/usbmisc/lp2
从uevent文件中获取设备名称:
cat /sys/class/usbmisc/lp1/uevent
MAJOR=180
MINOR=1
DEVNAME=__usb/lp1__
添加/ dev以便您打开设备名称: / dev / usb / lp1
使用真实路径: $ cd -P / sys / class / usbmisc / lp1
退后3个分支:
$ cd ../../../
/sys/devices/pci0000:00/0000:00:1d.0/usb4/4-1/4-1.5
此目录包含设备上的大量信息:
idProduct 和 idVendor 可用于唯一标识设备类型。
如果有序列文件,并且该文件包含唯一的序列号,则表示您已完成。
否则您的选择是使用物理连接作为标识,这个目录名称是“ 4-1.5 ”它对于物理连接是唯一的,并且如您插入的那样,如您已经提到的那样更改该设备到另一个端口。
答案 5 :(得分:1)
概括了SimonRigét的answer,我想出了这个bash函数,给定可选的供应商ID和产品ID,返回一个设备节点名称列表,与该供应商ID和产品ID相关,如果给定的话。 / p>
getDevNodes() {
if [ -n "$1" ] && [ "$1" != "no_class" ]; then
2>/dev/null find -L /sys/class/$1 -maxdepth 2 -mindepth 2 -name uevent -exec realpath "{}" +
else
find /sys/devices -name uevent
fi | {
if [ -z "$1" ]; then
readarray -t lines < <(find /sys/class -maxdepth 2 -mindepth 2 -type l -print -exec realpath "{}" +)
local -i count=${#lines[@]} sys_dev=count/2 sys_class=0
local -A classes
while [ $sys_dev -lt $count ]; do
class="${lines[$sys_class]#/*/*/}"
class="${class%/*}"
classes["${lines[$sys_dev]}"]="$class"
sys_dev+=1
sys_class+=1
done
fi
readarray -t uevents
for u in "${uevents[@]}"; do
DEVNAME=; DEVTYPE=no_type; while IFS="=" read key value; do {
[ "$key" = "DEVNAME" ] && DEVNAME=/dev/"$value"
} || {
[ "$key" = "DEVTYPE" ] && DEVTYPE="$value"
}; done < "$u"
if [ -n "$DEVNAME" ]; then
path="${u%/uevent}"
while [ "$path" != "/sys/devices" ] && ! [ -f "$path"/idVendor ]; do
path="${path%/*}"
done
[ "$path" != "/sys/devices" ] && {
read readIdVendor < "$path"/idVendor
read readIdProduct < "$path"/idProduct
} || {
readIdVendor=----
readIdProduct=----
}
echo "${1:-${classes[${u%/uevent}]:-no_class}}" "$DEVTYPE" "$readIdVendor" "$readIdProduct" "$DEVNAME"
fi
done
} | grep "^${1:-[[:graph:]]\+} ${2:-[[:graph:]]\+} ${3:-....} ${4:-....}" | cat
}
例如,这就是我的lsusb告诉我的:
$ lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 008: ID 0bda:b719 Realtek Semiconductor Corp.
Bus 001 Device 006: ID 0bda:57b5 Realtek Semiconductor Corp.
Bus 001 Device 004: ID 0bda:0129 Realtek Semiconductor Corp. RTS5129 Card Reader Controller
Bus 001 Device 097: ID 1004:6344 LG Electronics, Inc. G2 Android Phone [tethering mode]
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
因此,如果我想查看哪些设备节点与供应商ID 0x1004和产品ID 0x6344相关联,我会执行以下操作:
$ getDevNodes "" "" 1004 6344
no_class usb_device 1004 6344 /dev/bus/usb/001/097
tty no_type 1004 6344 /dev/ttyACM0
所以我们有两个设备节点,其中一个是 class tty ,没有devtype,另一个是未知类,但有一个devtype usb_device 。 / p>
也可以只提供供应商ID,如下所示:
$ getDevNodes "" "" 0bda
no_class usb_device 0bda 0129 /dev/bus/usb/001/004
no_class usb_device 0bda b719 /dev/bus/usb/001/008
no_class no_type 0bda 57b5 /dev/media0
video4linux no_type 0bda 57b5 /dev/video0
input no_type 0bda 57b5 /dev/input/event14
no_class usb_device 0bda 57b5 /dev/bus/usb/001/006
如果我只想要供应商ID为0bda的 video4linux类设备,那么我会执行以下操作:
$ getDevNodes video4linux "" "" 0bda
video4linux no_type 0bda 57b5 /dev/video0
参数基本上是对设备节点及其相关信息的完整列表进行过滤。省略其中一个参数,或使用空字符串“”作为参数,禁用该特定参数的过滤器。
按以下顺序给出参数:1:类,2:类型,3:供应商ID,4:产品ID。
以下是上述函数的 lite 版本,其运行速度更快,代价是某些功能:设备节点打印时没有附加信息,并且没有设备类型的过滤器。
getDevNodesLite() {
if [ -n "$1" ]; then
2>/dev/null find -L /sys/class/$1 -maxdepth 2 -mindepth 2 -name uevent -exec realpath "{}" +
else
find /sys/devices -name uevent
fi | {
if [ -n "$2" ]; then
readarray -t uevents
for u in "${uevents[@]}"; do
path="${u%/uevent}"
while [ "$path" != "/sys/devices" ] && ! [ -f "$path"/idVendor ]; do
path="${path%/*}"
done
[ "$path" != "/sys/devices" ] && read readValue < "$path"/idVendor && [ "$readValue" = "$2" ] && {
if [ -n "$idProduct" ]; then
read readValue < "$path"/idProduct && [ "$readValue" = "$3" ]
fi
} && echo "$u"
done
else
cat
fi
} | {
readarray -t uevents
[ ${#uevents[@]} -gt 0 ] && sed -n 's,DEVNAME=\(.*\),/dev/\1,p' "${uevents[@]}"
}
}
答案 6 :(得分:0)
执行sudo blkid
,它将列出所有已安装设备的文件系统ID