udev(九)-- 写个程序检测我们的设备插拔

原创文章,转载请注明出处,谢谢!       
       作者:清林,博客名:飞空静渡

在这个教程里我将写一个程序,其作用是检测系统的设备插拔事件,当有设备插入 系统时,就可以检测到这个设备并把设备的信息显示出来,如果设备从系统里移除,也同样可以检测出来,并移除设备。这个代码是参考了udev-139的源码 的,如果读者有兴趣也可以参考udev的源码。其中在udev-139代码中有个小小的错误,我将在下面的代码中说出。

首先先说一下udev的一个命令,你可以在控制台下运行:

udevadm  monitor

我的运行如下图所示:


当插入我的金士顿优盘时,便可以检测到优盘的插入,如下图:


我们现在要做就是写个程序,其输出和上面的一样,其实也就是udevadm的 源码,我只是把它的大部分代码移除,只留个检测插拔事件的代码,并把很多地方的宏和函数集成到一个文件中。其中具体代码的API可参考libudev Reference Manual的说明:http://www.kernel.org/pub/linux/utils/kernel/hotplug/libudev /ch01.html


下面是源代码udevadm.c:

  1. #include <unistd.h>   
  2. #include <stdio.h>   
  3. #include <stdlib.h>   
  4. #include <stddef.h>   
  5. #include <string.h>   
  6. #include <errno.h>   
  7. #include <getopt.h>   
  8. #include <fcntl.h>   
  9. #include <errno.h>   
  10. #include <signal.h>   
  11. #include <getopt.h>   
  12. #include <sys/time.h>   
  13. #include <sys/socket.h>   
  14. #include <sys/un.h>   
  15. #include <sys/select.h>   
  16. #include <linux/types.h>   
  17. #include <linux/netlink.h>   
  18. #undef asmlinkage   
  19. #ifdef __i386__   
  20. #define asmlinkage __attribute__((regparm(0)))   
  21. #else   
  22. #define asmlinkage    
  23. #endif   
  24. #define UDEV_MAX(a,b) ((a) > (b) ? (a) : (b))   
  25. #define udev_list_entry_foreach(entry, first) /   
  26.     for  (entry = first; /  
  27.          entry != NULL; /  
  28.          entry = udev_list_entry_get_next(entry))  
  29. static   int  debug;  
  30. static   int  udev_exit;  
  31. static   void  asmlinkage sig_handler( int  signum)  
  32. {  
  33.     if  (signum == SIGINT || signum == SIGTERM)  
  34.         udev_exit = 1;  
  35. }  
  36. static   void  print_device( struct  udev_device *device,  const   char  *source,  int  env)  
  37. {  
  38.     struct  timeval tv;  
  39.     struct  timezone tz;  
  40.     gettimeofday(&tv, &tz);  
  41.     printf("%-6s[%llu.%06u] %-8s %s (%s)/n" ,  
  42.            source,  
  43.            (unsigned long   long ) tv.tv_sec, (unsigned  int ) tv.tv_usec,  
  44.            udev_device_get_action(device),  
  45.            udev_device_get_devpath(device),  
  46.            udev_device_get_subsystem(device));  
  47.     if  (env) {  
  48.         struct  udev_list_entry *list_entry;  
  49.         udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(device))  
  50.             printf("%s=%s/n" ,  
  51.                    udev_list_entry_get_name(list_entry),  
  52.                    udev_list_entry_get_value(list_entry));  
  53.         printf("/n" );  
  54.     }  
  55. }  
  56. int  udevadm_monitor( struct  udev *udev)  
  57. {  
  58.     struct  sigaction act;  
  59.     int  env = 0;  
  60.     int  print_kernel = 0;  
  61.     int  print_udev = 0;  
  62.     struct  udev_monitor *udev_monitor = NULL;  
  63.     struct  udev_monitor *kernel_monitor = NULL;  
  64.     fd_set readfds;  
  65.     int  rc = 0;  
  66.     if  (!print_kernel && !print_udev) {  
  67.         print_kernel = 1;  
  68.         print_udev =1;  
  69.     }  
  70.     if  (getuid() != 0 && print_kernel) {  
  71.         fprintf(stderr, "root privileges needed to subscribe to kernel events/n" );  
  72.         goto  out;  
  73.     }  
  74.     /* set signal handlers */   
  75.     memset(&act, 0x00, sizeof ( struct  sigaction));  
  76.     act.sa_handler = (void  (*)( int )) sig_handler;  
  77.     sigemptyset(&act.sa_mask);  
  78.     act.sa_flags = SA_RESTART;  
  79.     sigaction(SIGINT, &act, NULL);  
  80.     sigaction(SIGTERM, &act, NULL);  
  81.     printf("monitor will print the received events for:/n" );  
  82.     if  (print_udev) {  
  83.         udev_monitor = udev_monitor_new_from_socket(udev, "@/org/kernel/udev/monitor" );  
  84.         if  (udev_monitor == NULL) {  
  85.             rc = 1;  
  86.             goto  out;  
  87.         }  
  88.         if  (udev_monitor_enable_receiving(udev_monitor) < 0) {  
  89.             rc = 2;  
  90.             goto  out;  
  91.         }  
  92.         printf("UDEV the event which udev sends out after rule processing/n" );  
  93.     }  
  94.       
  95.     if  (print_kernel) {  
  96.         kernel_monitor = udev_monitor_new_from_netlink(udev, "udev" );  //这里的udev源码中没有"udev"这个参数,不加进去返回值就为NULL,所以要加这个   
  97.         if  (kernel_monitor == NULL) {  
  98.             rc = 3;  
  99.             printf("udev_monitor_new_from_netlink() error/n" );  
  100.             goto  out;  
  101.         }  
  102.         if  (udev_monitor_enable_receiving(kernel_monitor) < 0) {  
  103.             rc = 4;  
  104.             goto  out;  
  105.         }  
  106.         printf("UEVENT the kernel uevent/n" );  
  107.     }  
  108.       
  109.     printf("/n" );  
  110.     while  (!udev_exit) {  
  111.         int  fdcount;  
  112.         FD_ZERO(&readfds);  
  113.         if  (kernel_monitor != NULL)  
  114.             FD_SET(udev_monitor_get_fd(kernel_monitor), &readfds);  
  115.         if  (udev_monitor != NULL)  
  116.             FD_SET(udev_monitor_get_fd(udev_monitor), &readfds);  
  117.         fdcount = select(UDEV_MAX(udev_monitor_get_fd(kernel_monitor), udev_monitor_get_fd(udev_monitor))+1,  
  118.                  &readfds, NULL, NULL, NULL);  
  119.         if  (fdcount < 0) {  
  120.             if  (errno != EINTR)  
  121.                 fprintf(stderr, "error receiving uevent message: %m/n" );  
  122.             continue ;  
  123.         }  
  124.         if  ((kernel_monitor != NULL) && FD_ISSET(udev_monitor_get_fd(kernel_monitor), &readfds)) {  
  125.             struct  udev_device *device;  
  126.             device = udev_monitor_receive_device(kernel_monitor);  
  127.             if  (device == NULL)  
  128.                 continue ;  
  129.             print_device(device, "UEVENT" , env);  
  130.             udev_device_unref(device);  
  131.         }  
  132.         if  ((udev_monitor != NULL) && FD_ISSET(udev_monitor_get_fd(udev_monitor), &readfds)) {  
  133.             struct  udev_device *device;  
  134.             device = udev_monitor_receive_device(udev_monitor);  
  135.             if  (device == NULL)  
  136.                 continue ;  
  137.             print_device(device, "UDEV" , env);  
  138.             udev_device_unref(device);  
  139.         }  
  140.     }  
  141. out:  
  142.     udev_monitor_unref(udev_monitor);  
  143.     udev_monitor_unref(kernel_monitor);  
  144.     return  rc;  
  145. }  
  146. int  main( int  argc,  char  *argv[])  
  147. {  
  148.     struct  udev *udev;  
  149.     int  rc = 1;  
  150.     udev = udev_new();  
  151.     if  (udev == NULL)  
  152.         goto  out;  
  153.     udevadm_monitor(udev);  
  154.     goto  out;  
  155.     rc = 2;  
  156. out:  
  157.     udev_unref(udev);  
  158.     return  rc;  
  159. }  

下面是Makefile

  1. myudevadm: udevadm.c  
  2.        gcc -g -Wall -ludev udevadm.c -o myudevadm  

当插入和拔出优盘是的显示如下图:



记得加个sudo,要退出按ctrl-c,我的运行环境是ubuntu9.10。可看到我的优盘设备是sde,有关分区是sde4,这个你可以在/dev目录下找到,并且是usb设备。/

来源:http://blog.csdn.net/fjb2080/archive/2009/12/15/5009791.aspx

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值