Linux USB 设备基础理论

通过扫描以下目录获取物理节点所有 USB 设备:

/sys/bus/usb/devices/usb*
/sys/bus/usb/devices/usb*/$busnum-*

从该文件系统收集某一个设备的主要信息如下:

{
    "busnum": 1,
    "class": 0,
    "devnum": 2,
    "level": 1,
    "manufacturer": "QEMU",
    "port": 0,
    "prodid": "0001",
    "product": "QEMU USB Tablet",
    "speed": "12",
    "usbpath": "1",
    "vendid": "0627"
}

文件含义

目录下部分文件含义如下:

  • busnum: 总线号
  • devnum: 设备号(该总线的第几台设备)
  • speed: 速率
  • bDeviceClass: 设备类型
  • idVendor: 设备的生产商ID,由USB设备生产商向USB-IF官方来统一管理和申请
  • idProduct: 该生产商生产的产品编号,同一厂商下的不同idProduct代表着该公司不同的产品系列
  • product: 制造商
  • manufacturer: 产品
  • serial: USB 硬件设备序列号 ,例如 0000:00:01.2

定位方法

定位某一个 USB 设备的方法有两种:

  • busnum + devnum
  • idVendor + idProduct

设备类型bDeviceClass

类代码 用法 描述
00h 设备描述符 Use class information in the interface Descriptors
01h 接口描述符 音频
02h 设备描述符、接口描述符 通讯设备,如电话,moden等等
03h 接口描述符 HID设备
05h 接口描述符 Physical
06h 接口描述符 Image
07h 接口描述符 打印机
08h 接口描述符 大容量存储
09h 设备描述符 Hub USB集线器
0Ah 接口描述符 CDC-Data
0Bh 接口描述符 Smart Card
0Dh 接口描述符 Content Security
0Eh 接口描述符 UVC视频/CAMERA
0Fh 接口描述符 Personal Healthcare
10h 接口描述符 音视频设备
11h 设备描述符 Billboard Device Class
12h 接口描述符 USB Type-C Bridge Class
DCh 设备描述符、接口描述符 Diagnostic Device
E0h 接口描述符 无线控制器
EFh 设备描述符、接口描述符 Miscellaneous
FEh 接口描述符 Application Specific
FFh 设备描述符、接口描述符 厂商用自定义

参考文献

使用 qemu-img 转换镜像格式

qemu-img镜像格式转换工具支持vhd、vmdk、qcow2、raw、vhdx、qcow、vdi或qed社区格式的镜像的相互转换。

查看信息

$ qemu-img info vzdump-qemu-125-2022_08_16-13_40_42.vma                                                                                                                                                                                    
image: vzdump-qemu-125-2022_08_16-13_40_42.vma                                                                                                                                                                                                                                
file format: raw                                                                                                                                                                                                                                                              
virtual size: 3 GiB (3221810176 bytes)                                                                                                                                                                                                                                        
disk size: 3 GiB

$ qemu-img info vzdump-qemu-125-2022_08_16-13_40_42.qcow2 
image: vzdump-qemu-125-2022_08_16-13_40_42.qcow2
file format: qcow2
virtual size: 3 GiB (3221810176 bytes)
disk size: 3 GiB
cluster_size: 65536
Format specific information:
    compat: 1.1
    compression type: zlib
    lazy refcounts: false
    refcount bits: 16
    corrupt: false
    extended l2: false

格式转换

执行如下命令转换镜像文件格式。

# 转换 vmdk 格式为 qcow2 格式
$ qemu-img convert -p -f vmdk -O qcow2 centos6.9.vmdk centos6.9.qcow2

# 转换 vma(raw) 为 qcow2
$ qemu-img convert -p -f raw -O qcow2 vzdump-qemu-125-2022_08_16-13_40_42.vma vzdump-qemu-125-2022_08_16-13_40_42.qcow2
    (100.00/100%)

上述命令中各参数对应的说明如下:

  • -p 标识转换的进度条。
  • -f 源镜像格式。
  • -O 目标镜像格式 + 源镜像文件名称 + 目标文件名称。

转换完成后,目标文件会出现在源镜像文件所在的目录下。

参考文献

Win11 手动调整任务栏大小 | 定制任务栏 2022

最近自己的 MacBook Air M1 资源吃紧,干起活来常常被内存拖累。

虽然平时都是远程开发,但终端一多,网页一多,很容易达到性能瓶颈导致工作效率下降。于是心生一计,在计算资源较充足的开发服务器上开一台高性能的桌面虚拟机,恰好此前一直没有使用过 Win11,趁此机会体验一下。

装好之后一切都好,就是嫌这个任务栏太大,不能像 Win10 那样直接调整为小任务栏。因此就有了这篇文章,介绍两种定制 Win11 任务栏的方法。

先看效果,再介绍方法。

调整前:

修改后:

怎么样,是不是省出了很多宝贵的桌面空间,下面介绍两种方法。

方法一 – 修改注册表(不推荐)

1、同时按下 win+r ,打开运行,在打开栏中输入 regedit ,然后按下回车确定调出注册表编辑器;

2、接着定位到注册表如下路径

HKEY_CURRENT_USER\Software\Microsoft\ Windows\CurrentVersion\Explorer\Advanced

3、右键右侧空白处,选择新建一个 DWORD 值,将它命名为 TaskbarSi

4、双击打开这个 TaskbarSi 值,将 value data 更改为 重启之后就是小任务栏了。

(数字 是小任务栏,1 是中任务栏, 2 是大任务栏)。

该方法不需要安装第三方工具即可修改,但是适配很差,修改为小图标后,右下角会布局会乱,因此不推荐该方法。

方法二 – StartAllBack (推荐)

StartAllBack 是一款 Win11 开始菜单增强工具,能包括:开始菜单样式和操作、个性化任务栏及资源管理器等。

通过这个工具即可方便的定制 Win11 任务栏,甚至可以修改为 Win7 样式。

前往 StartAllBack 官网下载即可,如果打不开,可以在本站的 资源站 获取,安装包名为 StartAllBack_3.5.1_setup.exe

安装结束后可以在 C:\Program Files\StartAllBack 找到其可执行程序,运行即可定制,一看就懂。

总结

本文介绍了两种 Win11 任务栏的定制方法,同样的关键词在网络上能找到的大都是方法一,但是这种方法已经过时,因此就有了这篇文章。希望对你有用。

参考文献

Perl 特性之不安全的依赖

最近写 Perl 程序时遇到一个很奇怪的问题:

Insecure dependency in unlink while running with -T switch at ../tmpfile.pl line 44.

经过检查,发现这是 Perl 语言一个特性,在运行时使用 -w 或 -T 都意味着 “万无一失” 标志。

-T 标志意味着任何来自外部世界的值(例如从文件读取)都被认为是潜在的威胁,并且不允许在与系统相关的操作中使用这些值,比如写文件、执行系统命令等等。

-w 作用与 use warning 相同,会抛出一些有用的警告信息,如 using uninitialized variable

为了更清晰的表述该问题,我抽象出一个简单的示例程序:

#!/usr/bin/perl -wT

use strict;
use warnings;

use Digest::MD5;

my $DIR_PATH="/var/tmp";
my $PREFIX = "somedemotmpfile";

sub make_file {
    my ($filename) = @_;

    open my $fh, '>', $filename;
    print {$fh} "1" . "\n";
    print {$fh} "2" . "\n";
    print {$fh} "3" . "\n";
    close $fh;
}

sub make_tmpfile {
    foreach (1..5){
    my $tmpfilename = "$DIR_PATH/$PREFIX-" . Digest::MD5::md5_hex($_ . time() . $$);
    make_file($tmpfilename);
    }
}

sub clean_tmpfile {
    opendir (my $dh, $DIR_PATH) || die "Can not open $DIR_PATH/n";
    my @dots=grep { !/^\.+$/ } readdir($dh);
    closedir($dh);

    foreach my $file (@dots)
    {
    my $afile = "$DIR_PATH/$file";
    my $now = time();
    if (-e $afile && $afile =~ m/(^.*$PREFIX.*$)/) {
        #$afile = $1;
        my $mtime = (stat ($afile))[9];
        my $margin = $now - $mtime;
        print("$afile - Last change: $mtime - now: $now - margin(s): $margin\n");
        eval {
            unlink $afile;
        };
        warn $@ if $@;
    }
    }
}

sub main {
    make_tmpfile();
    clean_tmpfile();
}

main();

执行该程序,得到如下输出:

# perl -T ../tmpfile.pl
/var/tmp/somedemotmpfile-e48d74ec998a1462661eb11b7576d7e5 - Last change: 1658904122 - now: 1658904122 - margin(s): 0
Insecure dependency in unlink while running with -T switch at ../tmpfile.pl line 44.
/var/tmp/somedemotmpfile-a071ba8e02d34ef2878d7a698a22b93c - Last change: 1658904122 - now: 1658904122 - margin(s): 0
Insecure dependency in unlink while running with -T switch at ../tmpfile.pl line 44.
/var/tmp/somedemotmpfile-1a63c4b7965dc50c519e7aa68c8b081a - Last change: 1658904122 - now: 1658904122 - margin(s): 0
Insecure dependency in unlink while running with -T switch at ../tmpfile.pl line 44.

可以看到,当我从文件系统读取一些文件,并尝试直接删除这些问题时,这步操作被阻止,并报出警告 Insecure dependency in unlink while running with -T switch

为了消除“污染”,最简单的方法是使用严格正则匹配后的结果再做操作,代码修改如下:

diff --git a/study_perl/tmpfile.pl b/study_perl/tmpfile.pl
index 6520a25..51ef684 100644
--- a/study_perl/tmpfile.pl
+++ b/study_perl/tmpfile.pl
@@ -36,7 +36,7 @@ sub clean_tmpfile {
     my $afile = "$DIR_PATH/$file";
     my $now = time();
     if (-e $afile && $afile =~ m/(^.*$PREFIX.*$)/) {
-        #$afile = $1;
+        $afile = $1;
         my $mtime = (stat ($afile))[9];
         my $margin = $now - $mtime;
         print("$afile - Last change: $mtime - now: $now - margin(s): $margin\n");

再次尝试运行,得到正确的结果:

# perl -T ../tmpfile.pl
/var/tmp/somedemotmpfile-f036c279daa16297818f6ec2dad9f338 - Last change: 1658904375 - now: 1658904375 - margin(s): 0
/var/tmp/somedemotmpfile-f532d49f86ae1c486ec593c71a073e73 - Last change: 1658904375 - now: 1658904375 - margin(s): 0
/var/tmp/somedemotmpfile-e48d74ec998a1462661eb11b7576d7e5 - Last change: 1658904122 - now: 1658904375 - margin(s): 253
/var/tmp/somedemotmpfile-a071ba8e02d34ef2878d7a698a22b93c - Last change: 1658904122 - now: 1658904375 - margin(s): 253
/var/tmp/somedemotmpfile-a140c4f6095a0431194a91ead41ce605 - Last change: 1658904375 - now: 1658904375 - margin(s): 0
/var/tmp/somedemotmpfile-1a63c4b7965dc50c519e7aa68c8b081a - Last change: 1658904122 - now: 1658904375 - margin(s): 253

执行成功,且删除了之前的残留文件。

经过这次问题解决,发现 Perl 在安全方面的特性值得学习,在编译或解释层面阻挡常见安全操作被执行,可以使得我们写出更加安全的代码。

即使不写 perl 代码,使用其他语言写程序时也可有所启发。

参考文献

shell 中格式化显示 json 字符串

有时需要在终端环境中查看 json 数据,比如使用 curl 调试接口时。直接看到的 json 数据是类似这样的:

$ echo '{"foo": "lorem", "bar": "ipsum"}'
{"foo": "lorem", "bar": "ipsum"}

如果想要以更直观的方式格式化显示 json 数据,可以利用 python3 提供的标准库 json 来实现:

$ echo '{"foo": "lorem", "bar": "ipsum"}' | python3 -m json.tool
{
    "foo": "lorem",
    "bar": "ipsum"
}

为了更方便地使用这一工具,可以为它设置一个别名:

将下面内容写入 ~/.bashrc 或其他您的 shell 配置文件中:

alias pjson='python3 -m json.tool'

执行 source ~/.bashrc

之后在该 shell 下就可以这样用了:

$ echo '{"foo": "lorem", "bar": "ipsum"}' | pjson
{
    "foo": "lorem",
    "bar": "ipsum"
}

参考文献