C Linux libudev测试应用程序未接收删除事件
我正在为我们正在开发的新平台创建一个测试应用程序,以测试C Linux libudev测试应用程序未接收删除事件,c,linux,usb,udev,C,Linux,Usb,Udev,我正在为我们正在开发的新平台创建一个测试应用程序,以测试libudev,并确保在插入或删除特定的usb设备时,我们的C应用程序能够得到正确的通知 在我们的系统上,每次删除并添加此设备时,它都会安装在不同的位置,例如/dev/hidraw0或/dev/hidraw1等。因此,我的测试应用程序使用libudev来监视事件并通过hidraw设备枚举,以便找到它的安装位置。每次设备状态更改、插入或删除时,代码都会找到它的安装位置并重新启动libudev事件监视 我的问题是: 1-我看到“添加”事件。但为
libudev
,并确保在插入或删除特定的usb
设备时,我们的C
应用程序能够得到正确的通知
在我们的系统上,每次删除并添加此设备时,它都会安装在不同的位置,例如/dev/hidraw0
或/dev/hidraw1
等。因此,我的测试应用程序使用libudev
来监视事件并通过hidraw
设备枚举,以便找到它的安装位置。每次设备状态更改、插入或删除时,代码都会找到它的安装位置并重新启动libudev
事件监视
我的问题是:
1-我看到“添加”事件。但为什么我从未看到删除事件?2-我是否正确关闭并重新启动了
libudev
监控,以确保资源不会泄漏
示例输出:找到了佐治亚大学。SysPath=[/sys/class/hidraw/hidraw2] DevPath=[/dev/hidraw2]
启动监视器返回2
UGA添加了……
找到了UGA。SysPath=[/sys/class/hidraw/hidraw2] DevPath=[/dev/hidraw2]
启动监视器返回2
UGA添加了……
找到了UGA。SysPath=[/sys/class/hidraw/hidraw1]Dev Path=[/dev/hidraw1]
启动监视器返回2 编辑:
我看到的是,这个测试应用程序在使用2.6内核的旧x86平台上运行时接收到
remove
事件,而在使用3.10.66内核的新ARM平台上运行的相同代码没有接收到remove
事件。这可能是系统配置或内核问题吗 另外,在ARM板上运行
udevadm监视器时,将发送所需的remove
事件,如下所示。那么为什么libudev
不把它们转发给我的应用程序呢
box:/home/eng$ udevadm monitor
monitor will print the received events for:
UDEV - the event which udev sends out after rule processing
KERNEL - the kernel uevent
KERNEL[80296.266707] remove /devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb2/2-1/2-1.1/2-1.1:1.0/0003:0A70:0441.001D (hid)
KERNEL[80296.266864] remove /devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb2/2-1/2-1.1/2-1.1:1.0 (usb)
UDEV [80296.267553] remove /devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb2/2-1/2-1.1/2-1.1:1.0/0003:0A70:0441.001D (hid)
KERNEL[80296.267695] remove /devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb2/2-1/2-1.1 (usb)
UDEV [80296.268031] remove /devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb2/2-1/2-1.1/2-1.1:1.0 (usb)
UDEV [80296.268890] remove /devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb2/2-1/2-1.1 (usb)
KERNEL[80304.423516] add /devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb2/2-1/2-1.1 (usb)
KERNEL[80304.424514] add /devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb2/2-1/2-1.1/2-1.1:1.0 (usb)
KERNEL[80304.427211] add /devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb2/2-1/2-1.1/2-1.1:1.0/0003:0A70:0441.001E (hid)
KERNEL[80304.458031] add /devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb2/2-1/2-1.1/2-1.1:1.0/0003:0A70:0441.001E/hidraw/hidraw1 (hidraw)
UDEV [80304.460096] add /devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb2/2-1/2-1.1 (usb)
UDEV [80304.467105] add /devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb2/2-1/2-1.1/2-1.1:1.0 (usb)
UDEV [80304.472885] add /devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb2/2-1/2-1.1/2-1.1:1.0/0003:0A70:0441.001E (hid)
UDEV [80304.474903] add /devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb2/2-1/2-1.1/2-1.1:1.0/0003:0A70:0441.001E/hidraw/hidraw1 (hidraw)
测试代码:
/* Linux */
#include <linux/input.h>
#include <linux/hidraw.h>
#include <linux/fd.h>
/* Unix */
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <libudev.h>
#include <pthread.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
/* C */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <locale.h>
#include <stdbool.h>
#include <stdint.h>
#ifndef FALSE
#define FALSE 0
#define TRUE 1
#endif
struct udev *udev;
struct udev_monitor *udevMonitor;
int mon_fd = -1;
int fd = -1;
char sysPath[50];
char devPath[50];
enum { DEVICE_NO_CHANGE = 0, DEVICE_ADD, DEVICE_REMOVE, DEVICE_MOVED };
enum { OFFLINE = 0, ONLINE };
enum { ENABLED = 1, DISABLED };
enum { FAILED = 0, PENDING , ACTIVE };
void msSleep(int milliseconds);
void GetUGAMountPoints(void);
int StartUDEVMonitor(void);
int usb_check_device_status(void);
void GetUGAMountPoints(void)
{
struct udev_device *dev;
struct udev_enumerate *enumerate;
struct udev_list_entry *devices, *dev_list_entry;
strcpy( devPath, "/dev/hidraw" );
/* Create a list of the devices in the 'hidraw' subsystem. */
enumerate = udev_enumerate_new(udev);
udev_enumerate_add_match_subsystem(enumerate, "hidraw");
udev_enumerate_scan_devices(enumerate);
devices = udev_enumerate_get_list_entry(enumerate);
udev_list_entry_foreach(dev_list_entry, devices)
{
const char *path;
path = udev_list_entry_get_name(dev_list_entry);
dev = udev_device_new_from_syspath(udev, path);
dev = udev_device_get_parent_with_subsystem_devtype( dev, "usb", "usb_device");
if (!dev)
{
printf("Unable to find parent usb device.\n");
}
else
{
if( !strcmp(udev_device_get_sysattr_value(dev, "idVendor"), "0a70") &&
!strcmp(udev_device_get_sysattr_value(dev, "idProduct"), "0441") )
{
char num = path[ strlen(path) - 1 ];
devPath[ strlen(devPath) ] = num;
/* Yes I know this sprintf() is insecure and lazy
This code is just for testing and not going into
production in this form
*/
sprintf(sysPath, "/sys/class/hidraw/hidraw%c", num);
printf("Found UGA. SysPath=[%s] Dev Path=[%s]\n", sysPath, devPath);
udev_device_unref(dev);
break;
}
else
{
udev_device_unref(dev);
}
}
}
udev_enumerate_unref(enumerate);
return;
}
int StartUDEVMonitor(void)
{
int retCode = ACTIVE;
/* Create the udev object */
udev = udev_new();
if (!udev)
{
retCode = FAILED;
}
else
{
GetUGAMountPoints();
/* Set up a monitor to monitor hidraw devices */
udevMonitor = udev_monitor_new_from_netlink(udev, "kernel");
udev_monitor_filter_add_match_subsystem_devtype(udevMonitor, "hidraw", NULL);
udev_monitor_enable_receiving(udevMonitor);
mon_fd = udev_monitor_get_fd(udevMonitor);
fd = open(devPath, O_RDWR | O_NONBLOCK);
if (fd < 0)
{
retCode = PENDING;
}
}
return( retCode );
}
int usb_check_device_status(void)
{
struct udev_device *dev;
char action[25];
int retCode = DEVICE_NO_CHANGE;
fd_set fds;
struct timeval tv;
int ret;
FD_ZERO(&fds);
FD_SET(mon_fd, &fds);
tv.tv_sec = 0;
tv.tv_usec = 75000;
do
{
ret = select(mon_fd+1, &fds, NULL, NULL, &tv);
/* Check if our file descriptor has received data. */
if (ret > 0 && FD_ISSET(mon_fd, &fds))
{
FD_CLR(mon_fd, &fds);
/* Make the call to receive the device.
select() ensured that this will not block. */
dev = udev_monitor_receive_device(udevMonitor);
if (dev)
{
strcpy( action, udev_device_get_action(dev));
printf("usb_check_device_status()::[%s]\n", action);
if( !strcmp("remove",action))
{
printf("UGA removed....\n");
retCode = DEVICE_REMOVE;
}
else if( !strcmp("add",action))
{
printf("UGA added....\n");
retCode = DEVICE_ADD;
}
else if( !strcmp("move",action))
{
printf("UGA moved....\n");
retCode = DEVICE_MOVED;
}
udev_device_unref(dev);
}
}
}while( ret != 0 );
return( retCode );
}
void msSleep(int milliseconds)
{
usleep(milliseconds * 1000);
}
int main( int argc, char *argv[] )
{
int status = StartUDEVMonitor();
printf("Starting monitor returned %d\n",status);
if(status == ACTIVE )
{
while(1)
{
if( usb_check_device_status() != DEVICE_NO_CHANGE )
{
close(fd);
close(mon_fd);
udev_monitor_unref(udevMonitor);
udev_unref(udev);
StartUDEVMonitor();
printf("Starting monitor returned %d\n\n",status);
}
msSleep(75);
}
}
return( 1 );
}
/*Linux*/
#包括
#包括
#包括
/*Unix*/
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
/*C*/
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#ifndef FALSE
#定义FALSE 0
#定义真1
#恩迪夫
结构udev*udev;
结构udev_监视器*udevMonitor;
int mon_fd=-1;
int-fd=-1;
char sysPath[50];
char devPath[50];
枚举{DEVICE_NO_CHANGE=0,DEVICE_ADD,DEVICE_REMOVE,DEVICE_MOVED};
枚举{OFFLINE=0,ONLINE};
枚举{ENABLED=1,DISABLED};
枚举{FAILED=0,挂起,活动};
无效msSleep(整数毫秒);
无效点(无效);
int StartUDEVMonitor(无效);
int usb检查设备状态(无效);
无效点(无效)
{
结构udev_设备*dev;
结构udev_枚举*枚举;
结构udev_列表项*设备,*开发列表项;
strcpy(devPath,“/dev/hidraw”);
/*创建“hidraw”子系统中的设备列表*/
enumerate=udev\u enumerate\u new(udev);
udev_enumerate_add_match_子系统(enumerate,“hidraw”);
udev_枚举扫描_设备(枚举);
设备=udev_枚举_获取_列表_条目(枚举);
udev\u列表项\u foreach(开发列表项,设备)
{
常量字符*路径;
path=udev\u list\u entry\u get\u name(dev\u list\u entry);
dev=udev\u设备\u新\u来自\u系统路径(udev,路径);
dev=udev_device_get_parent_与_subsystem_devtype(dev,“usb”,“usb_device”);
如果(!dev)
{
printf(“找不到父usb设备。\n”);
}
其他的
{
如果(!strcmp(udev\u设备\u获取\u系统属性\u值(dev,“idVendor”),“0a70”)&&
!strcmp(udev\u设备\u获取\u系统属性值(dev,“idProduct”),“0441”))
{
char num=path[strlen(path)-1];
devPath[strlen(devPath)]=num;
/*是的,我知道这个sprintf()是不安全和懒惰的
此代码仅用于测试,不用于
以这种形式生产
*/
sprintf(sysPath,“/sys/class/hidraw/hidraw%c”,num);
printf(“找到的UGA.SysPath=[%s]开发路径=[%s]\n”,SysPath,devPath);
udev_设备unref(dev);
打破
}
其他的
{
udev_设备unref(dev);
}
}
}
udev_enumerate_unref(enumerate);
返回;
}
int StartUDEVMonitor(无效)
{
int retCode=激活;
/*创建udev对象*/
udev=udev_new();
如果(!udev)
{
retCode=失败;
}
其他的
{
getmountpoints();
/*设置监视器以监视hidraw设备*/
udevMonitor=udev_monitor_new_from_netlink(udev,“内核”);
udev_监视器_过滤器_添加_匹配_子系统_devtype(udevMonitor,“hidraw”,NULL);
udev_监视器启用接收(udevMonitor);
mon_fd=udev_monitor_get_fd(udevMonitor);
fd=打开(devPath,O|RDWR | O|unblock);
如果(fd<0)
{
retCode=PENDING;
}
}
返回(返回代码);
}
int usb检查设备状态(无效)
{
结构udev_设备*dev;
炭作用[25];
int retCode=设备无变化;
fd_集fds;
结构时间值电视;
int ret;
FD_零(&fds);
FD_集(mon_FD和fds);
tv.tv_sec=0;
tv.tv_usec=75000;
做
{
ret=select(mon_fd+1和fds、NULL、NULL和tv);
/*检查文件描述符是否接收到数据*/
如果(ret>0和&FD\u设置(mon\u FD和&fds))
{
FD_CLR(mon_FD和fds);
/*拨打电话以接收设备。
select()确保此操作不会阻塞*/
dev=udev_监视器_接收设备(udevMonitor);
如果(开发)
{
strcpy(动作,udev_设备获取动作(dev));
printf(“usb检查设备状态():[%s]\n”,操作);
box:/home/eng$ udevadm monitor
monitor will print the received events for:
UDEV - the event which udev sends out after rule processing
KERNEL - the kernel uevent
KERNEL[80296.266707] remove /devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb2/2-1/2-1.1/2-1.1:1.0/0003:0A70:0441.001D (hid)
KERNEL[80296.266864] remove /devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb2/2-1/2-1.1/2-1.1:1.0 (usb)
UDEV [80296.267553] remove /devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb2/2-1/2-1.1/2-1.1:1.0/0003:0A70:0441.001D (hid)
KERNEL[80296.267695] remove /devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb2/2-1/2-1.1 (usb)
UDEV [80296.268031] remove /devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb2/2-1/2-1.1/2-1.1:1.0 (usb)
UDEV [80296.268890] remove /devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb2/2-1/2-1.1 (usb)
KERNEL[80304.423516] add /devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb2/2-1/2-1.1 (usb)
KERNEL[80304.424514] add /devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb2/2-1/2-1.1/2-1.1:1.0 (usb)
KERNEL[80304.427211] add /devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb2/2-1/2-1.1/2-1.1:1.0/0003:0A70:0441.001E (hid)
KERNEL[80304.458031] add /devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb2/2-1/2-1.1/2-1.1:1.0/0003:0A70:0441.001E/hidraw/hidraw1 (hidraw)
UDEV [80304.460096] add /devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb2/2-1/2-1.1 (usb)
UDEV [80304.467105] add /devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb2/2-1/2-1.1/2-1.1:1.0 (usb)
UDEV [80304.472885] add /devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb2/2-1/2-1.1/2-1.1:1.0/0003:0A70:0441.001E (hid)
UDEV [80304.474903] add /devices/soc0/soc.1/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb2/2-1/2-1.1/2-1.1:1.0/0003:0A70:0441.001E/hidraw/hidraw1 (hidraw)
udev_monitor_filter_add_match_subsystem_devtype(udevMonitor, "hidraw", NULL);
udev_monitor_filter_add_match_subsystem_devtype(udevMonitor, "hid", NULL);