Monitor USB under Linux
#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 (buff
Ersize));
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_hotplu
G_sock ();
while (1) {char buf[uevent_buffer_size*2] = {0};
Recv (Hotplug_sock, &buf, sizeof (BUF), 0);
printf ("Snotest---------------%s\n", buf);
return 0; }
Insert Event
2009-10-09 10:08:20| Category: Linux applicatio| Report | font size subscription to users
There are currently 3 ways to obtain HotPlug events.
One is the HotPlug script. When the HotPlug event occurs, the kernel invokes the script/sbin/hotplug. You can add your own actions in this script. But the 2.6 kernel has made a big difference. HotPlug scripts are no longer supported.
And there is the NetLink. This is a special socket that can accept messages from the kernel.
The following is a netlink routine.
#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;
}
The 2.6 kernel uses a user-state program Udev to mount/dev. This makes it extremely convenient to receive and process information from the kernel.
Udev uses a rule-matching approach to handle device mounts while triggering other processing. For example, the following rules can be used to capture events from a U disk insert. and call the corresponding script.
bus== "USB", kernel== "sd*", run+= "/root/p.sh"
The content of/root/p.sh
#!/bin/bash
Set >>/root/usb.txt
Echo-e "end****" >>/root/usb.txt
This allows you to print the parameters of the event that occurred to the text file. The following is the information of my U disk Plug and pull.
Action=add
Bash=/bin/bash
Bash_argc= ()
bash_argv= () http://wubinjie.spaces.live.com/blog/cns!2055299901bf6246!234.entry
bash_lineno= ([0]= "0")
Bash_source= ([0]= "/root/p.sh")
bash_versinfo= ([0]= "3" [1]= "1" [2]=] [3]= "1" [4]= "Release" [5]= "I686-redhat-linux-gnu")
Bash_version= ' 3.1.17 (1)-release '
devlinks= '/dev/disk/by-id/usb-usb_2.0_6025/dev/disk/by-path/pci-0000:00:1d.2-usb-0:1:1.0-scsi-0:0:0:0 '
Devname=/dev/sda
Devpath=/block/sda
Dirstack= ()
Euid=0
Groups= ()
hostname=linux230
hosttype=i686
Id_bus=usb
id_model=6025
id_path=pci-0000:00:1d.2-usb-0:1:1.0-scsi-0:0:0:0
id_revision=2.00
id_serial=usb_2.0_6025
Id_type=disk
id_vendor=usb_2.0
ifs=$ ' \t\n '
Machtype=i686-redhat-linux-gnu
Major=8
Minor=0
Opterr=1
Optind=1
Ostype=linux-gnu
Path=/usr/local/bin:/bin:/usr/bin
Physdevbus=scsi
Physdevdriver=sd
physdevpath=/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/host5/target5:0:0/5:0:0:0
ppid=3549
ps4= ' + '
pwd=/
seqnum=814
Shell=/bin/bash
Shellopts=braceexpand:hashall:interactive-comments
Shlvl=1
Subsystem=block
Term=dumb
Udevd_event=1
Udev_log=3
Uid=0
_=/bin/bash
end****
Action=add
Bash=/bin/bash
Bash_argc= ()
bash_argv= ()
bash_lineno= ([0]= "0")
Bash_source= ([0]= "/root/p.sh")
bash_versinfo= ([0]= "3" [1]= "1" [2]=] [3]= "1" [4]= "Release" [5]= "I686-redhat-linux-gnu")
Bash_version= ' 3.1.17 (1)-release '
Devlinks= '/dev/disk/by-id/usb-usb_2.0_6025-part1/dev/disk/by-path/pci-0000:00:1d.2-usb-0:1:1.0-scsi-0:0:0:0- Part1 '
Devname=/dev/sda1
Devpath=/block/sda/sda1
Dirstack= ()
Euid=0
Groups= ()
hostname=linux230
hosttype=i686
Id_bus=usb
Id_fs_label=
Id_fs_label_safe=
Id_fs_type=vfat
Id_fs_usage=filesystem
Id_fs_uuid=
Id_fs_version=fat32
id_model=6025
id_path=pci-0000:00:1d.2-usb-0:1:1.0-scsi-0:0:0:0
id_revision=2.00
id_serial=usb_2.0_6025
Id_type=disk
id_vendor=usb_2.0
ifs=$ ' \t\n '
Machtype=i686-redhat-linux-gnu
Major=8
Minor=1
Opterr=1
Optind=1
Ostype=linux-gnu
Path=/usr/local/bin:/bin:/usr/bin
Physdevbus=scsi
Physdevdriver=sd
physdevpath=/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/host5/target5:0:0/5:0:0:0
ppid=3576
ps4= ' + '
pwd=/
seqnum=815
Shell=/bin/bash
Shellopts=braceexpand:hashall:interactive-comments
Shlvl=1
Subsystem=block
Term=dumb
Udevd_event=1
Udev_log=3
Uid=0
_=/bin/bash
end****
You can see that 2 devices are mounted/dev/sda/dev/sda1 one of the partitions and one is a device.