2012/10/17

Kernel Message and Hotplug

http://www.kernel.org/doc/pending/hotplug.txt

The hotplug mechanism asynchronously notifies userspace when hardware is
inserted, removed, or undergoes a similar significant state change.  Linux
provides two interfaces to hotplug; the kernel can spawn a usermode helper
process, or it can send a message to an existing daemon listening to a netlink
socket.

-- Usermode helper

The usermode helper hotplug mechanism spawns a new process to handle each
hotplug event.  Each such helper process belongs to the root user (UID 0) and
is a child of the init task (PID 1).  The kernel spawns one process per hotplug
event, supplying environment variables to each new process describing that
particular hotplug event.  By default the kernel spawns instances of
"/sbin/hotplug", but this default can be changed by writing a new path into
"/proc/sys/kernel/hotplug" (assuming /proc is mounted).

A simple bash script to record variables from hotplug events might look like:

  #!/bin/bash

  env >> /filename

It's possible to disable the usermode helper hotplug mechanism (by writing an
empty string into /proc/sys/kernel/hotplug), but there's little reason to
do this unless you want to disable an existing hotplug mechanism.  (From a
performance perspective, a usermode helper won't be spawned if /sbin/hotplug
doesn't exist, and negative dentries will record the fact it doesn't exist
after the first lookup attempt.)

-- Netlink

A daemon listening to the netlink socket receives a packet of data for each
hotplug event, containing the same information a usermode helper would receive
in environment variables.
 
A daemon listening to the netlink socket receives a packet of data for each
hotplug event, containing the same information a usermode helper would receive
in environment variables.

The netlink packet contains a set of null terminated text lines.
The first line of the netlink packet combines the $ACTION and $DEVPATH values,
separated by an @ (at sign).  Each line after the first contains a
KEYWORD=VALUE pair defining a hotplug event variable.

Here's a C program to print hotplug netlink events to stdout:

  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>

  #include <sys/poll.h>
  #include <sys/socket.h>
  #include <sys/types.h>
  #include <unistd.h>

  #include <linux/types.h>
  #include <linux/netlink.h>

  void die(char *s)
  {
 write(2,s,strlen(s));
 exit(1);
  }

  int main(int argc, char *argv[])
  {
 struct sockaddr_nl nls;
 struct pollfd pfd;
 char buf[512];

 // Open hotplug event netlink socket

 memset(&nls,0,sizeof(struct sockaddr_nl));
 nls.nl_family = AF_NETLINK;
 nls.nl_pid = getpid();
 nls.nl_groups = -1;

 pfd.events = POLLIN;
 pfd.fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
 if (pfd.fd==-1)
  die("Not root\n");

 // Listen to netlink socket

 if (bind(pfd.fd, (void *)&nls, sizeof(struct sockaddr_nl)))
  die("Bind failed\n");
 while (-1!=poll(&pfd, 1, -1)) {
  int i, len = recv(pfd.fd, buf, sizeof(buf), MSG_DONTWAIT);
  if (len == -1) die("recv\n");

  // Print the data to stdout.
  i = 0;
  while (i<len) {
   printf("%s\n", buf+i);
   i += strlen(buf+i)+1;
  }
 }
 die("poll\n");

 // Dear gcc: shut up.
 return 0;
  } 

No comments:

Post a Comment

Post Code on Blogger

Simplest way to post code to blogger for me: <pre style="background: #f0f0f0; border: 1px dashed #CCCCCC; color: black;overflow-x:...