对于系统的热插拔事件,内核可以自动地帮我们做很多事情。如果我想做一个能够知道热插拔发生的用户软件该怎么实现呢?
手册
浅尝
有不少很low的方法,例如定时访问有没有新的设备文件被内核建立,本文肯定不是讲这种的。
最近了解到了一个叫NETLINK的东西,它使我们可以通过socket编程直接获取操作系统上报的热插拔事件。
代码演示
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <asm/types.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <errno.h>
int main(int argc, char **argv)
{
int ret, buffersize = 1024;
int fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
struct sockaddr_nl nl;
memset(&nl, 0, sizeof(struct sockaddr_nl));
nl.nl_family = AF_NETLINK;
nl.nl_pid = getpid();
nl.nl_groups = 1;
if (fd < 0)
{
printf("error@%d, %s\n", __LINE__, strerror(errno));
exit(EXIT_FAILURE);
}
ret = bind(fd, (struct sockaddr *)&nl, sizeof(struct sockaddr_nl));
setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &buffersize, sizeof(buffersize));
while(1)
{
char buf[1024] = {0};
recv(fd, &buf, sizeof(buf), 0);
printf("%s\n", buf);
}
return 0;
}
输出
插入优盘
add@/devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1.2
add@/devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1.2/1-1.2:1.0
add@/devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1.2/1-1.2:1.0/host1
add@/devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1.2/1-1.2:1.0/host1/scsi_host/host1
add@/devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1.2/1-1.2:1.0/host1/target1:0:0
add@/devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1.2/1-1.2:1.0/host1/target1:0:0/1:0:0:0
add@/devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1.2/1-1.2:1.0/host1/target1:0:0/1:0:0:0/scsi_disk/1:0:0:0
add@/devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1.2/1-1.2:1.0/host1/target1:0:0/1:0:0:0/scsi_device/1:0:0:0
add@/devices/virtual/bdi/8:0
add@/devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1.2/1-1.2:1.0/host1/target1:0:0/1:0:0:0/block/sda
add@/devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1.2/1-1.2:1.0/host1/target1:0:0/1:0:0:0/block/sda/sda1
拔出优盘
remove@/devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1.2/1-1.2:1.0/host1/target1:0:0/1:0:0:0/scsi_device/1:0:0:0
remove@/devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1.2/1-1.2:1.0/host1/target1:0:0/1:0:0:0/scsi_disk/1:0:0:0
remove@/devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1.2/1-1.2:1.0/host1/target1:0:0/1:0:0:0/block/sda/sda1
remove@/devices/virtual/bdi/8:0
remove@/devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1.2/1-1.2:1.0/host1/target1:0:0/1:0:0:0/block/sda
remove@/devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1.2/1-1.2:1.0/host1/target1:0:0/1:0:0:0
remove@/devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1.2/1-1.2:1.0/host1/target1:0:0
remove@/devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1.2/1-1.2:1.0/host1/scsi_host/host1
remove@/devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1.2/1-1.2:1.0/host1
remove@/devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1.2/1-1.2:1.0
remove@/devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1.2
瞎分析
输出中有/devices/virtual/bdi/8:0,/block/sda,/block/sda/sda1,我想他们分别是后备设备、块设备文件、对应块设备的第一个分区的块设备文件。