usb更新文件

一.内核配置,配置使其支持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代码

<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>
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值