我日常用Ubuntu系统,当U盘插入的时候,Ubuntu总是帮我讲我的U盘挂载到/media目录下:
-
manu@manu-hacks:/media$ ll
-
total 12
-
drwxr-xr-x 3 root root 4096 Dec 17 23:11 ./
-
drwxr-xr-x 23 root root 4096 Nov 29 22:40 ../
- drwx------ 19 manu manu 4096 Jan 1 1970 Ubuntu 12.0/
-
manu@manu-hacks:/media$ ps -ef|grep udevd
-
root 378 1 0 19:31 ? 00:00:00 /sbin/udevd --daemon
-
root 9310 378 0 23:11 ? 00:00:00 /sbin/udevd --daemon
-
root 9311 378 0 23:11 ? 00:00:00 /sbin/udevd --daemon
- manu 9339 8894 0 23:13 pts/1 00:00:00 grep --color=auto udevd
在2007年李先静前辈在给出了一个sample程序,因为目前我对netlink的机制理解不够深入,我讲前辈的代码copy于此,学习了一番。还是那句话,没有恶意抄袭前辈的意思,光荣属于前辈:
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <string.h>
-
#include <ctype.h>
-
#include <sys/un.h>
-
#include <sys/ioctl.h>
-
#include <sys/socket.h>
-
#include <linux/types.h>
-
#include <linux/netlink.h>
-
#include <errno.h>
-
-
static int init_hotplug_sock(void)
-
{
-
struct sockaddr_nl snl;
-
const int buffersize = 16 * 1024 * 1024;
-
int retval;
-
-
memset(&snl, 0x00, sizeof(struct sockaddr_nl));
-
snl.nl_family = AF_NETLINK;
-
snl.nl_pid = getpid();
-
snl.nl_groups = 1;
-
-
int hotplug_sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
-
if (hotplug_sock == -1) {
-
printf("error getting socket: %s", strerror(errno));
-
return -1;
-
}
-
-
/* set receive buffersize */
-
setsockopt(hotplug_sock, SOL_SOCKET, SO_RCVBUFFORCE, &buffersize, sizeof(buffersize));
-
-
retval = bind(hotplug_sock, (struct sockaddr *) &snl, sizeof(struct sockaddr_nl));
-
if (retval < 0) {
-
printf("bind failed: %s", strerror(errno));
-
close(hotplug_sock);
-
hotplug_sock = -1;
-
return -1;
-
}
-
-
return hotplug_sock;
-
}
-
-
#define UEVENT_BUFFER_SIZE 2048
-
-
int main(int argc, char* argv[])
-
{
-
int hotplug_sock = init_hotplug_sock();
-
-
while(1)
-
{
-
char buf[UEVENT_BUFFER_SIZE*2] = {0};
-
recv(hotplug_sock, &buf, sizeof(buf), 0);
-
printf("%s\n", buf);
-
}
-
-
return 0;
- }
当我拔出我的U盘的时候输出:
-
remove@/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0/host8/target8:0:0/8:0:0:0/bsg/8:0:0:0
-
remove@/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0/host8/target8:0:0/8:0:0:0/scsi_generic/sg2
-
remove@/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0/host8/target8:0:0/8:0:0:0/scsi_device/8:0:0:0
-
remove@/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0/host8/target8:0:0/8:0:0:0/scsi_disk/8:0:0:0
-
remove@/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0/host8/target8:0:0/8:0:0:0/block/sdb/sdb4
-
remove@/devices/virtual/bdi/8:16
-
remove@/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0/host8/target8:0:0/8:0:0:0/block/sdb
-
remove@/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0/host8/target8:0:0/8:0:0:0
-
remove@/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0/host8/scsi_host/host8
-
remove@/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0/host8
-
remove@/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0
-
remove@/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2
- remove@/host8/target8:0:0
-
add@/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2
-
add@/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0
-
add@/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0/host9
-
add@/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0/host9/scsi_host/host9
-
add@/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0/host9/target9:0:0
-
add@/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0/host9/target9:0:0/9:0:0:0
-
add@/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0/host9/target9:0:0/9:0:0:0/scsi_disk/9:0:0:0
-
add@/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0/host9/target9:0:0/9:0:0:0/scsi_device/9:0:0:0
-
add@/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0/host9/target9:0:0/9:0:0:0/scsi_generic/sg2
-
add@/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0/host9/target9:0:0/9:0:0:0/bsg/9:0:0:0
-
add@/devices/virtual/bdi/8:16
-
add@/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0/host9/target9:0:0/9:0:0:0/block/sdb
- add@/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0/host9/target9:0:0/9:0:0:0/block/sdb/sdb4
-
change@/devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0003:00/power_supply/ADP1
-
change@/devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0003:00/power_supply/ADP1
- change@/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:0e/PNP0C09:00/PNP0C0A:00/power_supply/BAT1
udev同时提供了udevadmin,这个工具也非常实用。我们可以用udevadm来侦测内核事件。
-
manu@manu-hacks:~/code/c/self/udev$ udevadm monitor
-
custom logging function 0xb8670008 registered
-
selinux=0
-
runtime dir '/run/udev'
-
calling: monitor
-
monitor will print the received events for:
-
UDEV - the event which udev sends out after rule processing
-
KERNEL - the kernel uevent
-
-
KERNEL[14475.004474] add /devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2 (usb)
-
KERNEL[14475.007146] add /devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0 (usb)
-
KERNEL[14475.007442] add /devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0/host11 (scsi)
-
KERNEL[14475.007709] add /devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0/host11/scsi_host/host11 (scsi_host)
-
UDEV [14475.016589] add /devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2 (usb)
-
UDEV [14475.017925] add /devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0 (usb)
-
UDEV [14475.019205] add /devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0/host11 (scsi)
- 。。。。。。
-
manu@manu-hacks:~/code/c/self/udev$ udevadm info -a -n /dev/sdb
-
custom logging function 0xb8950008 registered
-
selinux=0
-
runtime dir '/run/udev'
-
calling: info
-
device 0xb8950318 has devpath '/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0/host11/target11:0:0/11:0:0:0/block/sdb'
-
-
Udevadm info starts with the device specified by the devpath and then
-
walks up the chain of parent devices. It prints for every device
-
found, all possible attributes in the udev rules key format.
-
A rule to match, can be composed by the attributes of the device
-
and the attributes from one single parent device.
-
-
looking at device '/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0/host11/target11:0:0/11:0:0:0/block/sdb':
-
KERNEL=="sdb"
-
SUBSYSTEM=="block"
-
DRIVER==""
-
ATTR{ro}=="0"
-
device 0xb89507f0 has devpath '/devices/virtual/bdi/8:16'
-
ATTR{size}=="15794176"
-
ATTR{stat}==" 176 580 1365 204 0 0 0 0 0 204 204"
-
ATTR{range}=="16"
-
ATTR{discard_alignment}=="0"
-
device 0xb89507f0 has devpath '/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0/host11/target11:0:0/11:0:0:0'
-
ATTR{events}=="media_change"
-
ATTR{ext_range}=="256"
-
ATTR{events_poll_msecs}=="2000"
-
ATTR{alignment_offset}=="0"
-
ATTR{inflight}==" 0 0"
-
ATTR{removable}=="1"
-
ATTR{capability}=="51"
-
ATTR{events_async}==""
-
-
device 0xb8950b60 has devpath '/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0/host11/target11:0:0/11:0:0:0'
-
looking at parent device '/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0/host11/target11:0:0/11:0:0:0':
-
KERNELS=="11:0:0:0"
-
SUBSYSTEMS=="scsi"
-
DRIVERS=="sd"
-
ATTRS{rev}=="8.07"
-
ATTRS{type}=="0"
-
ATTRS{scsi_level}=="5"
-
ATTRS{model}=="Flash Disk "
-
ATTRS{state}=="running"
-
ATTRS{queue_type}=="none"
-
ATTRS{iodone_cnt}=="0x1a4"
-
ATTRS{iorequest_cnt}=="0x1a4"
-
ATTRS{timeout}=="30"
-
ATTRS{evt_media_change}=="0"
-
ATTRS{max_sectors}=="240"
-
ATTRS{ioerr_cnt}=="0x2"
-
device 0xb8951868 has devpath '/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0/host11/target11:0:0/11:0:0:0/scsi_generic/sg2'
-
ATTRS{queue_depth}=="1"
-
ATTRS{vendor}=="Generic "
-
ATTRS{device_blocked}=="0"
-
ATTRS{iocounterbits}=="32"
-
-
device 0xb89519c8 has devpath '/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0/host11/target11:0:0'
-
looking at parent device '/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0/host11/target11:0:0':
-
KERNELS=="target11:0:0"
-
SUBSYSTEMS=="scsi"
-
DRIVERS==""
-
-
device 0xb8951e78 has devpath '/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0/host11'
-
looking at parent device '/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0/host11':
-
KERNELS=="host11"
-
SUBSYSTEMS=="scsi"
-
DRIVERS==""
-
-
device 0xb8952220 has devpath '/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0'
-
looking at parent device '/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0':
-
KERNELS=="1-1.2:1.0"
-
SUBSYSTEMS=="usb"
-
DRIVERS=="usb-storage"
-
ATTRS{bInterfaceClass}=="08"
-
ATTRS{bInterfaceSubClass}=="06"
-
ATTRS{bInterfaceProtocol}=="50"
-
ATTRS{bNumEndpoints}=="02"
-
ATTRS{supports_autosuspend}=="1"
-
ATTRS{bAlternateSetting}==" 0"
-
ATTRS{bInterfaceNumber}=="00"
-
- .......
-
manu@manu-hacks:/etc/udev$ ll
-
total 24
-
drwxr-xr-x 3 root root 4096 Dec 15 23:56 ./
-
drwxr-xr-x 147 root root 12288 Dec 17 23:32 ../
-
drwxr-xr-x 2 root root 4096 Dec 17 23:11 rules.d/
- -rw-r--r-- 1 root root 219 Dec 15 23:56 udev.conf
如果我检查到有USB插入,我会判断U盘是否是特殊的那块U盘,如果是,我需要将U盘挂载到指定的路径下如/mnt/manu_usb,当有U盘拔出的时候,需要判断是否特殊的U盘,是的话umount掉。
-
root@manu-hacks:/etc/udev/rules.d# cat 11-add-usb.rules
-
ACTION!="add",GOTO="farsight"
-
KERNEL=="sd[a-z][0-9]",SUBSYSTEMS=="usb",RUN+="/home/manu/code/shell/mount-special-usb.sh %k"
-
label="farsight"
-
-
root@manu-hacks:/etc/udev/rules.d# cat 11-remove-usb.rules
-
ACTION !="remove",GOTO="farsight"
-
SUBSYSTEM!="block",GOTO="farsight"
-
KERNEL=="sd[a-z][0-9]", RUN+="/home/manu/code/shell/umount-special-usb.sh %k"
-
LABEL="farsight"
- root@manu-hacks:/etc/udev/rules.d#
- udevadm control --reload-rules
插入我的U盘后:
-
root@manu-hacks:/etc/udev/rules.d# mount
-
/dev/sda1 on / type ext4 (rw,errors=remount-ro)
-
proc on /proc type proc (rw,noexec,nosuid,nodev)
-
sysfs on /sys type sysfs (rw,noexec,nosuid,nodev)
-
none on /sys/fs/fuse/connections type fusectl (rw)
-
none on /sys/kernel/debug type debugfs (rw)
-
none on /sys/kernel/security type securityfs (rw)
-
udev on /dev type devtmpfs (rw,mode=0755)
-
devpts on /dev/pts type devpts (rw,noexec,nosuid,gid=5,mode=0620)
-
tmpfs on /run type tmpfs (rw,noexec,nosuid,size=10%,mode=0755)
-
none on /run/lock type tmpfs (rw,noexec,nosuid,nodev,size=5242880)
-
none on /run/shm type tmpfs (rw,nosuid,nodev)
-
gvfs-fuse-daemon on /home/manu/.gvfs type fuse.gvfs-fuse-daemon (rw,nosuid,nodev,user=manu)
- /dev/sdb4 on /mnt/manu_usb type vfat (rw)
-
root@manu-hacks:/etc/udev/rules.d# mount
-
/dev/sda1 on / type ext4 (rw,errors=remount-ro)
-
proc on /proc type proc (rw,noexec,nosuid,nodev)
-
sysfs on /sys type sysfs (rw,noexec,nosuid,nodev)
-
none on /sys/fs/fuse/connections type fusectl (rw)
-
none on /sys/kernel/debug type debugfs (rw)
-
none on /sys/kernel/security type securityfs (rw)
-
udev on /dev type devtmpfs (rw,mode=0755)
-
devpts on /dev/pts type devpts (rw,noexec,nosuid,gid=5,mode=0620)
-
tmpfs on /run type tmpfs (rw,noexec,nosuid,size=10%,mode=0755)
-
none on /run/lock type tmpfs (rw,noexec,nosuid,nodev,size=5242880)
-
none on /run/shm type tmpfs (rw,nosuid,nodev)
- gvfs-fuse-daemon on /home/manu/.gvfs type fuse.gvfs-fuse-daemon (rw,nosuid,nodev,user=manu)
参考文献:
1 Writing udev rules
2 udev的实现原理
3 How to reload udev rules without reboot?
4 Understand output of `udevadm info -a -n /dev/sdb`