现在的位置: 首页 > 综合 > 正文

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

2018年04月03日 ⁄ 综合 ⁄ 共 6290字 ⁄ 字号 评论关闭

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-8
		system(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;
}

抱歉!评论已关闭.