usb更新文件
2016-03-02 11:18
148 查看
一.内核配置,配置使其支持u盘
make menu_config
Device Drivers --->
[*]USB support -->
<*> USB Mass Storage support
u盘底层依赖scsi,所以scsi的配置也要配置好
二.设计更新代码
我是这么设计的:写个应用程序存放在文件系统的/bin目录下,取名update,执行这个程序会遍历 /dev/sd[drive][partition],
执行里面定义好的脚本文件,文件名约定为UpDate,脚本文件就可以调用busybox的通用linux命令,rm,mkdir,cp,touch等命令
将u盘上的新二进制或其他文件替换掉旧的文件系统的文件.
2.1 update代码
这里cmd将设备文件路径作为第一个参数传递给脚本
那么执行的脚本里面就可以通过$1获取DEV(/media/sda1)
可以写个简单的脚本测试下
ok交叉编译应用程序update然后放在/bin下面吧
到这里可以在启动代码的执行脚本中执行/bin/update文件来执行u盘中UpDate更新程序了
但是事先必须先插上u盘才能在启动过程中执行启动脚本调用到update --重启自动
或者只能插上u盘手工运行update来更新程序. --手动
三.下面来做不用重启的自动,也就是插上u盘自动运行update
先测试下u盘插入到识别的原理吧
3.1插入u盘打印
hub_thread守护线程[khubd]检测到hub状态变化,根hub枚举新的usb设备,获取新的usb设备信息,创建usb_device(usb设备),调用usb_bus_type的match方法,找到对应的usb驱动(usb_driver),这里就是usb_storage_driver.匹配之后调用usb_storage_driver的probe方法storage_probe,接着usb_stor_probe2函数,接着创建一个usb_stor_scan_thread线程来扫描u盘
接着调用sisc总线scsi_bus_type的match方法,匹配接着sd_probe,接着sd_probe_async同步
接着调用/bin/mount创建设备节点
update的扫描是扫描设备节点,mount命令会调用系统调用sys_mount
所以我在sys_mount的方法中调用update
sys_mount定义在fs/namespace.c中
make menu_config
Device Drivers --->
[*]USB support -->
<*> USB Mass Storage support
u盘底层依赖scsi,所以scsi的配置也要配置好
二.设计更新代码
我是这么设计的:写个应用程序存放在文件系统的/bin目录下,取名update,执行这个程序会遍历 /dev/sd[drive][partition],
执行里面定义好的脚本文件,文件名约定为UpDate,脚本文件就可以调用busybox的通用linux命令,rm,mkdir,cp,touch等命令
将u盘上的新二进制或其他文件替换掉旧的文件系统的文件.
2.1 update代码
<span style="background-color: rgb(255, 255, 255);">#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <string.h> unsigned char ch[8]={'a','b','c','d','e','f','g','h'}; //sda,sdb,sdc int main(int argc,char **argv) { int fd; unsigned char DEV[64]; //u盘等磁盘设备的设备文件路径 unsigned char PATH[64]; //Update文件的路径 unsigned char cmd[64]; //系统调用的命令 int i=0; int j=0; for(j=0;j<4;j++){ //最多支持4个分区 for(i=0;i<8;i++){ //最多8个硬盘 sprintf(PATH,"/media/sd%c%d/UpDate",ch[i],j); //"/media/sda1/UpDate","/media/sda2/UpDate"... sprintf(DEV,"/media/sd%c%d",ch[i],j); //对应的设备文件路径"/media/sda1","/media/sda2"... fd=open(PATH,O_RDWR); //打开文件全路径 if(fd==-1){ //判断文件是否存在 //printf("can not open '%s'\n",PATH); continue; //不存在继续扫描下一个分区 } else{ //文件存在则跳出子循环 printf("open device '%s'\n",PATH); break; } } if(fd!=-1) //判断文件是否存在 break; //存在则跳出第二个for循环,不存在则继续下一个磁盘扫描 } if(fd==-1){ //判断文件是否存在 printf("can not find any u pan!\n "); //这表示所有磁盘所有分区都没有UpDate文件 } else{ //文件存在 close(fd); //关闭文件描述符 sprintf(cmd,"sh %s %s",PATH,DEV); //设计执行脚本命令,例如"sh /media/sda1/UpDate /media/sda1" system(cmd); //执行该脚本 } return 0; }</span>
这里cmd将设备文件路径作为第一个参数传递给脚本
那么执行的脚本里面就可以通过$1获取DEV(/media/sda1)
可以写个简单的脚本测试下
<span style="background-color: rgb(255, 255, 255);">#! /bin/sh echo -e "update file!" echo $1 ls -l $1 touch /opt/1234 echo -e "update file done!"</span>
ok交叉编译应用程序update然后放在/bin下面吧
到这里可以在启动代码的执行脚本中执行/bin/update文件来执行u盘中UpDate更新程序了
但是事先必须先插上u盘才能在启动过程中执行启动脚本调用到update --重启自动
或者只能插上u盘手工运行update来更新程序. --手动
三.下面来做不用重启的自动,也就是插上u盘自动运行update
先测试下u盘插入到识别的原理吧
3.1插入u盘打印
<span style="background-color: rgb(255, 255, 255);">usb 1-1: new high speed USB device using musb-hdrc and address 5 usb 1-1: New USB device found, idVendor=0951, idProduct=1643 usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3 usb 1-1: Product: DataTraveler G3 usb 1-1: Manufacturer: Kingston usb 1-1: SerialNumber: 001CC0EC34F1FB90F71729FF scsi5 : usb-storage 1-1:1.0 scsi 5:0:0:0: Direct-Access Kingston DataTraveler G3 1.00 PQ: 0 ANSI: 0 CCS sd 5:0:0:0: Attached scsi generic sg0 type 0 sd 5:0:0:0: [sdb] 15644912 512-byte logical blocks: (8.01 GB/7.45 GiB) sd 5:0:0:0: [sdb] Write Protect is off sd 5:0:0:0: [sdb] Assuming drive cache: write through sd 5:0:0:0: [sdb] Assuming drive cache: write through sdb: sdb1 sd 5:0:0:0: [sdb] Assuming drive cache: write through sd 5:0:0:0: [sdb] Attached SCSI removable disk FAT: invalid media value (0xb9) VFS: Can't find a valid FAT filesystem on dev sdb. EXT3-fs (sdb): error: can't find ext3 filesystem on dev sdb. EXT2-fs (sdb): error: can't find an ext2 filesystem on dev sdb. FAT: invalid media value (0xb9) VFS: Can't find a valid FAT filesystem on dev sdb. ISOFS: Unable to identify CD-ROM format.</span>
hub_thread守护线程[khubd]检测到hub状态变化,根hub枚举新的usb设备,获取新的usb设备信息,创建usb_device(usb设备),调用usb_bus_type的match方法,找到对应的usb驱动(usb_driver),这里就是usb_storage_driver.匹配之后调用usb_storage_driver的probe方法storage_probe,接着usb_stor_probe2函数,接着创建一个usb_stor_scan_thread线程来扫描u盘
<span style="background-color: rgb(255, 255, 255);">usb_stor_scan_thread scsi_scan_host do_scsi_scan_host scsi_scan_host_selected scsi_scan_channel __scsi_scan_target scsi_probe_and_add_lun scsi_add_lun scsi_sysfs_add_sdev</span>
接着调用sisc总线scsi_bus_type的match方法,匹配接着sd_probe,接着sd_probe_async同步
接着调用/bin/mount创建设备节点
update的扫描是扫描设备节点,mount命令会调用系统调用sys_mount
所以我在sys_mount的方法中调用update
sys_mount定义在fs/namespace.c中
<span style="background-color: rgb(255, 255, 255);">SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name, char __user *, type, unsigned long, flags, void __user *, data) { int ret; char *kernel_type; char *kernel_dir; char *kernel_dev; unsigned long data_page; ret = copy_mount_string(type, &kernel_type); if (ret < 0) goto out_type; kernel_dir = getname(dir_name); if (IS_ERR(kernel_dir)) { ret = PTR_ERR(kernel_dir); goto out_dir; } ret = copy_mount_string(dev_name, &kernel_dev); if (ret < 0) goto out_dev; ret = copy_mount_options(data, &data_page); if (ret < 0) goto out_data; ret = do_mount(kernel_dev, kernel_dir, kernel_type, flags, (void *) data_page); call_usermodehelper ("/bin/update", NULL, NULL, 1); //MHB update ---就加了这句ok free_page(data_page); out_data: kfree(kernel_dev); out_dev: putname(kernel_dir); out_dir: kfree(kernel_type); out_type: return ret; }</span>
相关文章推荐
- noitatoNhsiloPesreveRetaulavE.150
- 排序算法之归并排序
- JSP默认HTML4改为HTML5
- android studio1.4新建工程运行出错
- 二叉树的构建以及先中后序遍历
- ArcGIS教程:设置地理处理环境
- 1059. Prime Factors (25)
- discuzX 3.1/2 如何重新安装
- QtGui继承关系树
- c++ 思考
- Spring/SpringMvc 配置文件常用标签解释
- android点点滴滴
- deepin linux系统 图像处理及机器学习开发环境配置方法
- 根据图片名获取ID
- mybatis-config.xml配置文件及sql分页查询的实现
- jquery在线引用地址
- 二维数组的查找
- 文章标题
- java对时间操作的常用总结
- Android系统架构