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

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;
}



本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/405603.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

android选择头像弹窗,Android App开发常用功能之用户头像选择-Go语言中文社区

前言现在的APP基本都有个人资料的填写&#xff0c;基本的都有头像的选择&#xff0c;支持拍照和从本地相册选择&#xff0c;剪切圆形头像的功能&#xff0c;现在用个小demo实现以下。下面看一下效果图上代码&#xff1a;主界面代码package com.example.androidpersonal_icon;im…

CentOS7 (64位) 下QT5.5 连接MySQL数据库(driver not loaded)

用qt连接MySQL需要共享库 libqsqlmysql.so的驱动&#xff0c;路径在plugin/sqldrivers目录下&#xff0c;乍看已经可用了&#xff0c;其实不然。 用ldd命令分析一下&#xff0c;libmysqlclient_r.so.16 > not found ,后明显libmysqlclient_r.so.16 缺少另一个共享库&#xf…

linux dhcp 服务(转)

大多数的情况下Linux作为DHCP服务器而windows 95/98作为DHCP客户。Linux也可以作为DHCP客户&#xff0c;即你要安装dhcpcd rpm 软件包 &#xff0c;Linux作为DHCP服务器&#xff0c;只需要安装dhcpd rpm 包。一.DHCP服务器工作的前提条件为了使DHCP服务器为windows机器服务&…

java jdk1.8.0_221 安装步骤

一、下载jdk Oracle JDK下载 官网 https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 下载jdk1.8.0_221. 需要注册账号登陆才能下载。 下载完成&#xff0c;双击jdk-8u221-windows-x64.exe&#xff0c;进行安装。 二、安装jdk 安装前…

gsoap使用心得!

From: http://www.cppblog.com/qiujian5628/archive/2008/06/19/54019.html 完整源码下载 最近换了个工作环境&#xff0c;现在在大望路这边上班&#xff0c;呵&#xff0c;刚上班接到的任务就是熟悉gsoap&#xff01;废话少说&#xff0c;现在开始gSoap学习&#xff01;gSOAP…

android tabhost 多个activity,Android:TabHost中Activity的生命周期问题

用过TabHost制作多个activity的分页效果的朋友应该知道&#xff0c;tabhost中镶嵌的activity的onCreate和onDestroy是和tabhost关联的&#xff0c;在创建了tabhost之后&#xff0c;第一次访问某个activity会执行这个activity的oncreate事件&#xff0c;以后切回来时只会执行onR…

网站决策分析软件WebBI

为了提高网站的访问量、黏合度&#xff0c;网站的管理者投入大量的精力于市场推广、内容发布、网站业务改进等&#xff0c;而对于如何评估推广效果、如何了解网民的行为以提高网站的吸引力和服务质量很多网站都显的无力可施。经过互联网多年的发展&#xff0c;互联网网站之间的…

eclipse启动报错No java virtual machine was found after seearching the locations:XXXXX

一、问题描述 卸载之前的老版本JDK后&#xff0c;重新安装了JDK&#xff0c;再次打开eclipse出现以下问题&#xff1a;在指定的目录中找不到JDK虚拟机。 二、解决办法 eclipse启动时会根据eclipse.ini配置文件来找javaw.exe 启动ecplise GUI。 在eclipse安装的根目录中找到e…

网卡配置

网卡配置文件 &#xff08;1&#xff09;/etc/sysconfig/network-scripts/ifcfg-interface-name 配置文件ifcfg-interface-name包含了初始化接口所需的大部分详细信息。其中interface-name将根据网卡的类型和排序而不同&#xff0c;一般其名字为eth0、eth1、ppp0等&#xff0c…

linux ace platform_linux.gnu,Linux下配置和使用ACE笔记

1. 下载 ACE 5.7.从 http://download.dre.vanderbilt.edu/ 下载 ACETAOCIAO-5.7.tar.gz包。2. 解压将压缩包copy到linux目录/data/ACE里&#xff0c;然后解压, tar -zxvf ACETAOCIAO-5.7.tar.gz。解压后的目录是 /data/ACE_wrappers.3. 配置config.h和platform_macros.GNU。…

Linux 查看磁盘分区、文件系统、使用情况的命令和相关工具介绍

From: http://fedora.linuxsir.org/main/?qnode/41 作者&#xff1a;北南南北 来自&#xff1a;LinuxSir.Org 提要&#xff1a;Linux 磁盘分区表、文件系统的查看、统计的工具很多&#xff0c;有些工具是多功能的&#xff0c;不仅仅是查看磁盘的分区表&#xff0c;而且也能进行…

Android 机顶盒手势、数据分页演示DEMO

上篇讲了一篇机顶盒的一个封装类《GridView》&#xff0c;利用这个封装的GridView 可以实现一些例如移动、位移图标等基础组件“GridView”无法实现的一些功能。本篇将会提出一部分可供运行的代码演示一个分页、手势换屏的DEMO版本&#xff0c;供大家学习。 DEMO 的工程目录如下…

Java jdk中的部分工具javac javaw javaws javadoc javah javap jar jdb jps的作用

一、JDK 工具和实用程序 JDK提供的标准工具和程序 基本工具&#xff1a;javac, java, javadoc, apt, appletviewer, jar, jdb, javah, javap, extcheck安全工具&#xff1a;keytool, jarsigner, policytool, kinit, klist, ktab国际化工具&#xff1a;native2ascii远程方法调…

firefox android 去更新,Android版Firefox Beta发布更新

就在谷歌I/O大会前夕&#xff0c;Android版Firefox Beta悄悄的发布了一次更新。更新内容包括&#xff1a;Flash支持(虽然事实上在上个月的更新中就已经支持了)以及日常bug修复及稳定性提升等&#xff0c;不过依然没有加入复制和粘贴功能。此外Firefox Beta的UI界面也被重新设计…

Linux/UNIX的scp命令用法详解

From: http://www.ha97.com/4169.html PS&#xff1a;偶很喜欢用scp这个命令来传输数据。scp命令跟cp命令类似&#xff0c;只不过cp命令是在同一台机器上用的&#xff0c;scp是在两台机器上复制传输数据的命令。scp实质相当于利用SSH协议来传输数据的cp命令。 用法举例&#xf…

React开发(230):ant design table固定表头

固定表头 方便一页内展示大量数据。需要指定 column 的 width 属性&#xff0c;否则列头和内容可能不对齐。 如果指定 width 不生效或出现白色垂直空隙&#xff0c; 请尝试建议留一列不设宽度以适应弹性布局&#xff0c;或者检查是否有超长连续字段破坏布局。

安装ARM交叉编译工具

1. 下载交叉编译工具链。 可到如下两个网站下载&#xff1a; http://ftp.arm.linux.org.uk/pub/armlinux/toolchain/ http://www.uushare.com/user/zyh006814/file/1434053 2. 安装 # mkdir /usr/local/arm # cd /usr/local/arm # 解压下载的工具链 # 添加环境变量&#xff0c…

Linux下获得线程ID syscall(224)

From: http://blog.163.com/onx0320126/blog/static/164736436201252574720314/ 对于Linux线程&#xff0c;也许大家并不陌生&#xff0c;而我们通常所说的线程是指基于POSIX标准的线程&#xff0c;而Linux下除了兼容POSIX标准&#xff0c;而且提供线程在内核级的支持。早在Lin…