以前學習了下Udev,就隨便作了個測試小程序.....設計什麼的也沒考慮,就實現了一個基本功能,插入U盤,識別,循環檢測到有特定文件後,就而後往U盤裏面寫數據,插拔屢次,都能正常工做。node
裏面的warning和不規範的寫法請本身修改。linux
#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <stddef.h> #include <string.h> #include <errno.h> #include <getopt.h> #include <fcntl.h> #include <errno.h> #include <signal.h> #include <getopt.h> #include <sys/time.h> #include <sys/socket.h> #include <sys/un.h> #include <sys/select.h> #include <linux/types.h> #include <linux/netlink.h> #include <sys/types.h> #include <libudev.h> #include <iostream> #include <pthread.h> #include <sys/mount.h> #include <sys/stat.h> #include <dirent.h> #include <time.h> using namespace std; static std::string record_path=""; static bool FindRecord=false; void File_Opreation(); void GetUsbFolderLocation(char *basePath); void MountTheSystem(char *basePath); static bool NeedToCheck=false; int ListDevice() { udev *udev; struct udev_enumerate *enumerate; struct udev_list_entry *devices, *dev_list_entry; struct udev_device *dev; /* Create the udev object */ udev = udev_new(); if (!udev) { printf("Can't create udev\n"); exit(1); } /* Create a list of the devices in the 'hidraw' subsystem. */ enumerate = udev_enumerate_new(udev); udev_enumerate_add_match_subsystem(enumerate, "block"); udev_enumerate_scan_devices(enumerate); devices = udev_enumerate_get_list_entry(enumerate); /* For each item enumerated, print out its information. udev_list_entry_foreach is a macro which expands to a loop. The loop will be executed for each member in devices, setting dev_list_entry to a list entry which contains the device's path in /sys. */ udev_list_entry_foreach(dev_list_entry, devices) { const char *path; /* Get the filename of the /sys entry for the device and create a udev_device object (dev) representing it */ path = udev_list_entry_get_name(dev_list_entry); dev = udev_device_new_from_syspath(udev, path); /* usb_device_get_devnode() returns the path to the device node itself in /dev. */ printf("Device Node Path: %s\n", udev_device_get_devnode(dev)); /* The device pointed to by dev contains information about the hidraw device. In order to get information about the USB device, get the parent device with the subsystem/devtype pair of "usb"/"usb_device". This will be several levels up the tree, but the function will find it.*/ dev = udev_device_get_parent_with_subsystem_devtype( dev, "usb", "usb_device"); if (!dev) { cout<<"Unable to find parent usb device"<<endl; exit(1); } /* From here, we can call get_sysattr_value() for each file in the device's /sys entry. The strings passed into these functions (idProduct, idVendor, serial, etc.) correspond directly to the files in the directory which represents the USB device. Note that USB strings are Unicode, UCS2 encoded, but the strings returned from udev_device_get_sysattr_value() are UTF-8 encoded. */ printf(" VID/PID: %s %s\n", udev_device_get_sysattr_value(dev,"idVendor"), udev_device_get_sysattr_value(dev, "idProduct")); printf(" %s\n %s\n", udev_device_get_sysattr_value(dev,"manufacturer"), udev_device_get_sysattr_value(dev,"product")); printf(" serial: %s\n", udev_device_get_sysattr_value(dev, "serial")); udev_device_unref(dev); } /* Free the enumerator object */ udev_enumerate_unref(enumerate); udev_unref(udev); return 0; } void Udev_Enumrate() { struct udev* udev_ancestor=NULL; struct udev_enumerate* udev_enum=NULL; struct udev_list_entry* device_fistentry=NULL; struct udev_list_entry *dev_list_entry=NULL; //entry to store the current position struct udev_device *dev=NULL; udev_ancestor=udev_new(); udev_enum=udev_enumerate_new(udev_ancestor); if(udev_enumerate_add_match_subsystem (udev_enum, "block")==0) { cout<<"add block device to match subsystem successful"<<endl; } if(udev_enumerate_add_match_subsystem (udev_enum, "usb")==0) { cout<<"add usb device to match subsystem successful"<<endl; } if(udev_enumerate_add_match_subsystem (udev_enum, "scsi")==0) { cout<<"add scsi device to match subsystem successful"<<endl; } //Scan the system under /sys/ udev_enumerate_scan_devices(udev_enum); //get the first entry of the device list device_fistentry=udev_enumerate_get_list_entry(udev_enum); /* For each item enumerated, print out its information. udev_list_entry_foreach is a macro which expands to a loop. The loop will be executed for each member in devices, setting dev_list_entry to a list entry which contains the device's path in /sys. */ udev_list_entry_foreach(dev_list_entry, device_fistentry) { const char *path; /* Get the filename of the /sys entry for the device and create a udev_device object (dev) representing it */ path = udev_list_entry_get_name(dev_list_entry); dev = udev_device_new_from_syspath(udev_ancestor, path); /* usb_device_get_devnode() returns the path to the device node itself in /dev. */ printf("Test Device Node Path: %s\n", udev_device_get_devnode(dev)); /* The device pointed to by dev contains information about the hidraw device. In order to get information about the USB device, get the parent device with the subsystem/devtype pair of "usb"/"usb_device". This will be several levels up the tree, but the function will find it.*/ dev = udev_device_get_parent_with_subsystem_devtype( dev, "usb", "usb_device"); if (!dev) { cout<<"Test Unable to find parent usb device"<<endl; //exit(1); } else { printf(" VID/PID: %s %s\n",udev_device_get_sysattr_value(dev,"idVendor"), udev_device_get_sysattr_value(dev, "idProduct")); printf(" %s\n %s\n",udev_device_get_sysattr_value(dev,"manufacturer"), udev_device_get_sysattr_value(dev,"product")); printf(" serial: %s\n",udev_device_get_sysattr_value(dev, "serial")); } udev_device_unref(dev); } udev_enumerate_unref(udev_enum); udev_unref(udev_ancestor); } void* udev_Monitor(void*) { struct udev* udev=NULL; struct udev_monitor * mon=NULL; struct udev_device *dev; int fd; fd_set fds; struct timeval tv; static int flag=0; udev=udev_new(); mon=udev_monitor_new_from_netlink(udev,"udev"); udev_monitor_filter_add_match_subsystem_devtype(mon, "sound", "usb_device"); udev_monitor_filter_add_match_subsystem_devtype(mon, "usb", "usb_device"); udev_monitor_filter_add_match_subsystem_devtype(mon, "block", "disk"); udev_monitor_filter_add_match_subsystem_devtype(mon, "block", "partition"); udev_monitor_filter_add_match_subsystem_devtype(mon, "usb", "usb_interface"); udev_monitor_enable_receiving(mon); fd = udev_monitor_get_fd(mon); while(1) { fd_set fds; struct timeval tv; int ret; FD_ZERO(&fds); FD_SET(fd, &fds); tv.tv_sec = 0; tv.tv_usec = 0; ret = select(fd+1, &fds, NULL, NULL, &tv); //ret means there's an event fd_isset means fd is readable if(ret>0 & FD_ISSET(fd,&fds)) { //cout<<"There's a change with Num="<<flag<<endl; //flag++; /* Make the call to receive the device. select() ensured that this will not block. */ dev = udev_monitor_receive_device(mon); if (dev) { const char* sysPath = udev_device_get_syspath(dev); const char* action = udev_device_get_action(dev); const char* subsystem = udev_device_get_subsystem(dev); const char* devType = udev_device_get_devtype(dev); if (0 == strncmp(action, "add", strlen("add"))) { const char* devClass = udev_device_get_sysattr_value(dev, "bDeviceClass"); const char* devInterfaceClass = udev_device_get_sysattr_value(dev, "bInterfaceClass"); cout<<"The devClass: "<<devClass<<endl; cout<<"The devInterfaceClass:"<<devInterfaceClass<<endl; NeedToCheck=true; } printf("Got Device\n"); printf(" Node: %s\n", udev_device_get_devnode(dev)); printf(" Subsystem: %s\n", udev_device_get_subsystem(dev)); printf(" Devtype: %s\n", udev_device_get_devtype(dev)); printf(" Action: %s\n",udev_device_get_action(dev)); printf(" Path: %s\n",udev_device_get_syspath(dev)); udev_device_unref(dev); } else { printf("No Device from receive_device(). An error occured.\n"); } } } } int LoopileList(char *basePath) { DIR *dir; struct dirent *ptr; char base[1000]; if ((dir=opendir(basePath)) == NULL) { perror("Open dir error..."); exit(1); } while ((ptr=readdir(dir)) != NULL) { if(strcmp(ptr->d_name,".")==0 || strcmp(ptr->d_name,"..")==0) ///current dir OR parrent dir { continue; } else if(ptr->d_type == 8) ///file { printf("d_name:%s/%s\n",basePath,ptr->d_name); } else if(ptr->d_type == 10) ///link file { printf("d_name:%s/%s\n",basePath,ptr->d_name); } else if(ptr->d_type == 4) ///dir { memset(base,'\0',sizeof(base)); strcpy(base,basePath); strcat(base,"/"); strcat(base,ptr->d_name); LoopileList(base); } } closedir(dir); return 1; } static bool stopLoopflag=false; void GetUsbFolderLocation(char *basePath) { bool ret=false; DIR *dir; struct dirent *ptr; char base[1000]; MountTheSystem(basePath); //cout<<"Loop check file "<<basePath<<endl; if ((dir=opendir(basePath)) == NULL) { //perror("Open dir error..."); //exit(1); } else { while ((ptr=readdir(dir)) != NULL && !stopLoopflag) { if(strcmp(ptr->d_name,".")==0 || strcmp(ptr->d_name,"..")==0) ///current dir OR parrent dir { continue; } else if(ptr->d_type == 8) ///file { if(strcmp(ptr->d_name,"Record_HFC")==0) { record_path=basePath; printf("File :%s/%s\n",basePath,ptr->d_name); strcat(basePath,"/"); record_path=basePath; cout<<"Record Path is="<<record_path<<endl; FindRecord=true; stopLoopflag=true; break; } } else if(ptr->d_type == 10) ///link file { printf("Link:%s/%s\n",basePath,ptr->d_name); } else if(ptr->d_type == 4) ///dir { memset(base,'\0',sizeof(base)); strcpy(base,basePath); strcat(base,"/"); strcat(base,ptr->d_name); GetUsbFolderLocation(base); } } if(dir!=NULL) { closedir(dir); } } } string GetLocalTime() { //string str="/usr/bin/sgm/Conn/tmp/out_"; string str=""; time_t rawtime; struct tm* timeinfo; char timE[25]; time(&rawtime); timeinfo=localtime(&rawtime); strftime(timE,sizeof(timE),"%Y_%m_%d_%I_%M_%S",timeinfo); printf("%s",timE); str=str+timE; return str; } void MountTheSystem(char *basePath) { //cout<<"mount"<<record_path<<endl; //mount(NULL, record_path.c_str(), NULL, MS_REMOUNT, "-o, rw"); //cout<<"mount"<<record_path<<endl; mount(NULL, basePath, NULL, MS_REMOUNT, "-o, rw"); } void WriteFileToUSB() { record_path=record_path+"test.txt"; FILE* fusb_Ubuntu=NULL; fusb_Ubuntu=fopen(record_path.c_str(),"w+"); cout<<"path is="<<record_path<<endl; if(fusb_Ubuntu==NULL) { cout<<"cant't write"<<endl; } else { cout<<"start write"<<endl; std::string str_Ubuntu="This is test"; str_Ubuntu=str_Ubuntu+GetLocalTime(); char* arr_Ubuntu=new char[str_Ubuntu.length()+1]; for(int i=0;i<str_Ubuntu.length();i++) { arr_Ubuntu[i]=str_Ubuntu[i]; } cout<<str_Ubuntu<<endl; fwrite(arr_Ubuntu,str_Ubuntu.length(),sizeof(char),fusb_Ubuntu); fclose(fusb_Ubuntu); record_path=""; NeedToCheck=false; stopLoopflag=false; delete []arr_Ubuntu; arr_Ubuntu=NULL; } } void File_Opreation() { cout<<"start to do file operation"<<endl; } void* writeFile(void*) { while(1) { if(NeedToCheck) { char* path="/media"; GetUsbFolderLocation(path); if(FindRecord) { WriteFileToUSB(); } } else { cout<<"sleep for 5s"<<endl; usleep(5000*1000); } } } //int main(int argc, char *argv[]) int main() { #if 0 char* path="/media"; GetUsbFolderLocation(path); if(FindRecord) { File_Opreation(); } #endif pthread_t monitor_thread=0; pthread_t write_thread=0; int err=0; err=pthread_create(&monitor_thread, NULL,udev_Monitor, NULL); if(err!=0) { cout<<"create thread error"<<endl; } else { cout<<"create thread monitor success "<<endl; } err=pthread_create(&write_thread, NULL,writeFile, NULL); if(err!=0) { cout<<"create thread error"<<endl; } else { cout<<"create thread writeFile success "<<endl; } if(monitor_thread!=0) { pthread_join(monitor_thread,NULL); } if(write_thread!=0) { pthread_join(write_thread,NULL); } return 0; }
Linux 下運行,若是要在ARM下運行就編一個arm版本的。ios
Makefile小程序
# specify the compiler CC=/usr/bin/g++ # specify library INCFLAGS=-I ./ # specify library LIBFLAGS=-l pthread -l udev # specify additional compile flags FLAGS= -lm -g -Wall -Wextra # List of files specific SRC:= Udev_Monitor.cpp testapp: ${CC} -o Udev_Monitor ${SRC} ${LIBFLAGS} ${INCFLAGS} ${FLAGS} clean: rm -f Udev_Monitor
只是基本的識別插拔U盤,檢測特定的文件,檢測到後往U盤裏面寫數據,能夠用來幫助cp或者記錄log文件。app
雖然個人blog也沒人會看,可是仍是但願能幫到和我同樣的菜鳥。socket