每当我取消挂起笔记本电脑时,我打开(正在运行)的 tmux 窗口dmesg -w
就会亮起:
从 tmux 手册页来看,这意味着窗口中运行的应用程序已经敲响了终端铃声。
我有另一台机器,其设置基本相同(相同的操作系统,相同的 tmux 配置),但这种情况不会发生——仅在这台特定的笔记本电脑上发生。为什么 dmesg 在这台机器上取消挂起时会响起终端铃声?
软件版本:
$ uname -a
Linux localhost 3.10.18 #1 SMP Mon Jan 8 23:08:08 PST 2018 armv7l armv7l armv7l GNU/Linux
$ lsb_release -cr
Release: 16.04
Codename: xenial
$ tmux -V
tmux 2.6
$ dmesg --version
dmesg from util-linux 2.27.1
答案1
如果你检查 dmesg 的输出,你可以通过 grep 查找 ASCII BEL 字符来准确地看到它何时敲响铃声\a
:
$ dmesg | grep -C1 $'\a'
[ 5.706427] usb 1-2: Manufacturer: HD WebCam
[ 5.706434] usb 1-2: SerialNumber: NC2141103Q533020AALM03
[ 5.798439] Unsafe core_pattern used with suid_dumpable=2. Pipe handler or fully qualified core dump path required.
--
[13843.531106] usb 1-2: Manufacturer: HD WebCam
[13843.531115] usb 1-2: SerialNumber: NC2141103Q533020AALM03
[13843.546586] uvcvideo: Found UVC 1.00 device HD WebCam (0bda:57cf)
有趣的是,铃声似乎是在初始化网络摄像头的过程中发生的。我们可以通过 od 管道来准确检查 BEL 正在打印的行中的位置:
$ dmesg | grep $'\a' | head -n 1 | od -c
0000000 [ 5 . 7 0 6 4 3 4 ] u
0000020 s b 1 - 2 : S e r i a l N u
0000040 m b e r : \a N C 2 1 4 1 1 0 3
0000060 Q 5 3 3 0 2 0 A A L M 0 3 \n
0000076
BEL 在此表示为\a
,并且它打印在序列号 ( SerialNumber: ␇NC214...
) 之前。 dmesg 似乎不太可能在一行的中间插入一个 BEL,所以也许是内核在记录它。
我们来检查一下源代码。也许 USB 驱动程序在记录序列号时正在打印铃声。我们可以用活格列普快速搜索Linux 4.12源码,发现相关文件很可能是drivers/usb/core/hub.c
.然后,我们可以使用以下命令返回 Linux 3.10.18 源代码灵丹妙药,并找到相关函数:
static void announce_device(struct usb_device *udev)
{
dev_info(&udev->dev, "New USB device found, idVendor=%04x, idProduct=%04x\n",
le16_to_cpu(udev->descriptor.idVendor),
le16_to_cpu(udev->descriptor.idProduct));
dev_info(&udev->dev,
"New USB device strings: Mfr=%d, Product=%d, SerialNumber=%d\n",
udev->descriptor.iManufacturer,
udev->descriptor.iProduct,
udev->descriptor.iSerialNumber);
show_string(udev, "Product", udev->product);
show_string(udev, "Manufacturer", udev->manufacturer);
show_string(udev, "SerialNumber", udev->serial);
}
show_string
是一个非常简单的函数,定义在上面announce_device
,几乎只是打印用冒号和空格分隔的参数:
static void show_string(struct usb_device *udev, char *id, char *string)
{
if (!string)
return;
dev_info(&udev->dev, "%s: %s\n", id, string);
}
所以添加铃声的也不是内核。
USB 设备的序列号是多少?
我们可以使用 lsusb 检查:
$ lsusb -vd 0bda:57cf | grep iSerial
iSerial 2 NC2141103Q533020AALM03
好的,现在让我们通过 od 进行管道传输:
$ lsusb -vd 0bda:57cf | grep iSerial | od -c
0000000 i S e r i a l
0000020 2 \a N C 2
0000040 1 4 1 1 0 3 Q 5 3 3 0 2 0 A A L
0000060 M 0 3 \n
0000064
这表明网络摄像头的序列号实际上包含 ASCII BEL。