linux下 USB动态监测 hotplug事件监测

来源:互联网 发布:ubuntu挂载硬盘到data 编辑:程序博客网 时间:2024/05/01 00:18

From: http://blog.csdn.net/qwyang/article/details/6425555


总体规划:

使用netlink接口向内核注册hotplug事件通知,获取事件通知后进行相关动作如(Action==add)挂载或(action==remove)卸载,使用Socket IPC机制向需要响应USB热拔插事件的应用程序报告。

功能包括:

1、获取usb卷标

2、挂载、卸载usb

3、动态监测usb热拔插事件

4、使用socket向应用程序报告热拔插事件

函数接口说明:

int reportToIplayer(USBEvent event,const char *servername);
向应用程序IPlayer报告热拔插事件

void check();
程序启动开始先检查当前u盘状态(空或者已存在)

int getDevPath(const char *buf,char *path,int size);
从热拔插事件的Diagram消息即buf中获得usb的设备路径存放到path,size为path缓冲大小

int rm_dir(const char *path);
删除挂载时建立的空目录

int make_dir(const char *devPath,const char *dstPath);
挂载钱建立一个空目录dstPath,dstPath为挂载目录

int get_label(const char *dev,char *buf,int size);
获取u盘卷标

int recordDstPath(int no,const char *dstPath);
记录下挂载路径,便于rm_dir查询

int init_hotplug_sock(void);

向内核注册hotplug事件

#include <stdio.h>#include <unistd.h>#include <fcntl.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include <sys/un.h>#include <sys/ioctl.h>#include <sys/socket.h>#include <linux/netlink.h>#include <errno.h>#include <sys/stat.h>#include <sys/types.h>#include <dirent.h>#include <stddef.h>typedef struct USBEvent{int event;char path[30];}USBEvent;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 get 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(0>retval){printf("bind failed:%s",strerror(errno));close(hotplug_sock);hotplug_sock = -1;return -1;}return hotplug_sock;}char dstPathTable[8][30];int recordDstPath(int no,const char *dstPath){if(strlen(dstPath) >= 30 || no>8){printf("pathname = %s,no = %d",dstPath,no);return -1;}strcpy(dstPathTable[no-1],dstPath);printf("%s has been recorded",dstPathTable[no-1]);return 0;}const char *LABEL = "label_tmp";void trim(char *buf){int i = strlen(buf)-1;while(i == '\n' || i == ' '){--i;printf("true/n");}buf[i+1] = 0;}int get_label(const char *dev,char *buf,int size){static int noLabel = 0;int ret,fd;char comm[200] = {0};sprintf(comm,"vol_id -l %s | sed -n '$p' > %s",dev,LABEL);system(comm);printf("get_label\n");fd = open(LABEL,O_RDONLY);if(fd == -1){perror("open in get_label");goto error;}ret = read(fd,buf,size-1);if(-1 == ret){perror("read in get_label");goto error;}close(fd);buf[ret-1] = 0;printf("get_label:%s,%d",buf,strlen(buf));if(strlen(buf) <= 1){++noLabel;sprintf(buf,"usb%d",noLabel);}return 0;error:++noLabel;sprintf(buf,"use%d",noLabel);return -1;}int make_dir(const char *devPath,const char *dstPath){mode_t dMode = S_IRWXU|S_IRWXG|S_IRWXO;int ret;int no = devPath[strlen(devPath)-1]-'0';ret = mkdir(dstPath,dMode);if(ret == -1){perror("make_dir");return ret;}return recordDstPath(no,dstPath);}int rm_dir(const char *path){int no = path[strlen(path)-1]-'0';printf("rmdir:%s\n",dstPathTable[no-1]);int ret = rmdir(dstPathTable[no-1]);if(ret == -1)perror("rm_dir");dstPathTable[no-1][0] = 0;return 0;}int getDevPath(const char *buf,char *path,int size){int i;char tmp[20];for(i = 1;i <= 8;++i){sprintf(tmp,"/sdb%d",i);if(strstr(buf,tmp)){strcpy(path,"/dev");strcat(path,tmp);printf("getDevPath:%s\n",path);return 0;}}printf("getDevPath:null\n");path[0] = 0;return -1;}const int ADD_EVENT = 0;const int REMOVE_EVENT = 1;void check(){char devPath[20];char label[21];char dstPath[30];char comm[100];char tmp[30];int i,ret;struct stat sb;struct dirent *file;USBEvent event;memset(&event,0,sizeof(event));for(i = 1;i<9;++i){sprintf(devPath,"/dev/sdb%d",i);sprintf(comm,"umount %s",devPath);// umount /dev/sdb1-8system(comm);}DIR *dir = opendir("/media/usb");while((file = readdir(dir)) != NULL){sprintf(tmp,"/media/usb/%s",file->d_name);ret = rmdir(tmp);if(0 == ret)printf("%s has been deleted!",tmp);}closedir(dir);for(i = 0;i<9;++i){sprintf(devPath,O_RDONLY);// what?????if(-1 != ret){close(ret);printf("%s found\n",devPath);get_label(devPath,label,21);printf(dstPath,"/media/usb/%s",label);make_dir(devPath,dstPath);sprintf(comm,"mount -t auto -o utf8,rw %s %s",devPath,dstPath);ret = system(comm);event.event = ADD_EVENT;strcpy(event.path,dstPath);reportTolplayer(event,"server.socket");printf("ret:%s\n",ret);}}printf("check exit\n");}int reportTolplayer(USBEvent event,const char *servername){const char *CLIENT_PATH = "/tmp/cli";struct sockaddr_un un;int ret,fd,size,i;unlink(CLIENT_PATH);memset(&un,0,sizeof(un));un.sun_family = AF_UNIX;sprintf(un.sun_path,"%s%5d",CLIENT_PATH,getpid());size = offsetof(struct sockaddr_un,sun_path)+strlen(un.sun_path);fd = socket(AF_UNIX,SOCK_STREAM,0);if(-1 == fd){perror("socket error");return -1;}unlink(un.sun_path);ret = bind(fd,(struct sockaddr *)&un,size);if(-1 == ret){perror("bind error");return -1;}memset(&un,0,sizeof(un));un.sun_family = AF_UNIX;strcpy(un.sun_path,servername);ret = connect(fd,(struct sockaddr *)&un,size);if(-1 == ret){perror("connect error");return -1;}ret = write(fd,&event,sizeof(event));if(-1 == ret){perror("write error");return -1;}ret = close(fd);if(-1 == ret){perror("close error");return -1;}}void splitString(char *buf, char *seps){if(buf && seps){char *p = buf;p = strtok(buf, seps);while(p){printf("p=[%s]\n", p);p = strtok(NULL, seps);}printf("\n");}}int getConsoleOutput(char *command, char *mode, char *out, int maxLen){FILE *p = popen(command, mode);if(p == NULL){perror("popen");return 0;}fread(out, 1, maxLen, p);return ferror(p) == 0;}int main(int argc,char **argv){char buf[1024] = {0};char comm[200] = {0};char dstPath[30] = {0};char devPath[30] = {0};char vol[21] = {0};int hotplug_sock;int sum,size;char *str;USBEvent event;memset(&event,0,sizeof(event));check();hotplug_sock = init_hotplug_sock();while(1){sum = 0;size = recv(hotplug_sock,buf,sizeof(buf),0);printf("size=%d, buf=[%s], strlen(buf)=%d\n", size, buf, strlen(buf));while(sum < size){str = buf + sum;sum += strlen(str);buf[sum] = '\n';}buf[sum] = 0;//printf("buf=[%s]\n\n", buf);splitString(buf, "\n");if(strstr(buf,"ACTION=add")){printf("ACTION=add\n");if(getDevPath(buf,devPath,30) == 0){get_label(devPath,vol,21);sprintf(dstPath,"/media/usb/%s",vol);make_dir(devPath,dstPath);sprintf(comm,"mount -t auto -o utf8,rw %s %s",devPath,dstPath);system(comm);event.event = ADD_EVENT;strcpy(event.path,dstPath);reportTolplayer(event,"server.socket");}}if(strstr(buf,"ACTION=remove")){printf("ACTION = remove\n");if(getDevPath(buf,devPath,30) == 0){sprintf(comm,"umount %s",devPath);system(comm);rm_dir(devPath);event.event = REMOVE_EVENT;reportTolplayer(event,"server.socket");}}}return 0;}



原创粉丝点击