嵌入式linux下u盘升级的设计

2019-07-12 22:44发布

一.内核配置,配置使其支持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代码 [cpp] view plain copy
  1. #include   
  2. #include   
  3. #include   
  4. #include   
  5. #include   
  6. #include   
  7. #include   
  8.   
  9. unsigned char ch[8]={'a','b','c','d','e','f','g','h'}; //sda,sdb,sdc  
  10. int main(int argc,char **argv)  
  11. {  
  12.     int fd;  
  13.     unsigned char DEV[64];  //u盘等磁盘设备的设备文件路径  
  14.     unsigned char PATH[64]; //Update文件的路径  
  15.     unsigned char cmd[64];  //系统调用的命令  
  16.     int i=0;  
  17.     int j=0;      
  18.   
  19.     for(j=0;j<4;j++){    //最多支持4个分区  
  20.         for(i=0;i<8;i++){    //最多8个硬盘  
  21.             sprintf(PATH,"/media/sd%c%d/UpDate",ch[i],j); //"/media/sda1/UpDate","/media/sda2/UpDate"...  
  22.             sprintf(DEV,"/media/sd%c%d",ch[i],j);  //对应的设备文件路径"/media/sda1","/media/sda2"...  
  23.             fd=open(PATH,O_RDWR);    //打开文件全路径  
  24.             if(fd==-1){    //判断文件是否存在  
  25.                 //printf("can not open '%s' ",PATH);  
  26.                 continue;  //不存在继续扫描下一个分区     
  27.             }  
  28.             else{    //文件存在则跳出子循环  
  29.                 printf("open device '%s' ",PATH);  
  30.                 break;  
  31.             }  
  32.         }  
  33.         if(fd!=-1)    //判断文件是否存在  
  34.             break;   //存在则跳出第二个for循环,不存在则继续下一个磁盘扫描  
  35.     }  
  36.     if(fd==-1){ //判断文件是否存在  
  37.         printf("can not find any u pan!  ");  //这表示所有磁盘所有分区都没有UpDate文件  
  38.     }  
  39.     else{    //文件存在  
  40.         close(fd);  //关闭文件描述符  
  41.         sprintf(cmd,"sh %s %s",PATH,DEV);  //设计执行脚本命令,例如"sh /media/sda1/UpDate /media/sda1"  
  42.         system(cmd);   //执行该脚本  
  43.     }  
  44.     return 0;  
  45. }  
这里cmd将设备文件路径作为第一个参数传递给脚本 那么执行的脚本里面就可以通过$1获取DEV(/media/sda1) 可以写个简单的脚本测试[cpp] view plain copy
  1. #! /bin/sh  
  2. echo -e "update file!"  
  3. echo $1  
  4. ls -l $1  
  5. touch /opt/1234  
  6. echo -e "update file done!"  

 ok交叉编译应用程序update然后放在/bin下面吧 到这里可以在启动代码的执行脚本中执行/bin/update文件来执行u盘中UpDate更新程序了 但是事先必须先插上u盘才能在启动过程中执行启动脚本调用到update           --重启自动 或者只能插上u盘手工运行update来更新程序.                                                      --手动 三.下面来做不用重启的自动,也就是插上u盘自动运行update 先测试下u盘插入到识别的原理吧 3.1插入u盘打印 [cpp] view plain copy
  1. usb 1-1: new high speed USB device using musb-hdrc and address 5  
  2. usb 1-1: New USB device found, idVendor=0951, idProduct=1643  
  3. usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3  
  4. usb 1-1: Product: DataTraveler G3  
  5. usb 1-1: Manufacturer: Kingston  
  6. usb 1-1: SerialNumber: 001CC0EC34F1FB90F71729FF  
  7. scsi5 : usb-storage 1-1:1.0  
  8. scsi 5:0:0:0: Direct-Access     Kingston DataTraveler G3  1.00 PQ: 0 ANSI: 0 CCS  
  9. sd 5:0:0:0: Attached scsi generic sg0 type 0  
  10. sd 5:0:0:0: [sdb] 15644912 512-byte logical blocks: (8.01 GB/7.45 GiB)  
  11. sd 5:0:0:0: [sdb] Write Protect is off  
  12. sd 5:0:0:0: [sdb] Assuming drive cache: write through  
  13. sd 5:0:0:0: [sdb] Assuming drive cache: write through  
  14.  sdb: sdb1  
  15. sd 5:0:0:0: [sdb] Assuming drive cache: write through  
  16. sd 5:0:0:0: [sdb] Attached SCSI removable disk  
  17. FAT: invalid media value (0xb9)  
  18. VFS: Can't find a valid FAT filesystem on dev sdb.  
  19. EXT3-fs (sdb): error: can't find ext3 filesystem on dev sdb.  
  20. EXT2-fs (sdb): error: can't find an ext2 filesystem on dev sdb.  
  21. FAT: invalid media value (0xb9)  
  22. VFS: Can't find a valid FAT filesystem on dev sdb.  
  23. ISOFS: Unable to identify CD-ROM format.  

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盘 [cpp] view plain copy
  1. usb_stor_scan_thread  
  2.     scsi_scan_host  
  3.         do_scsi_scan_host  
  4.             scsi_scan_host_selected  
  5.                 scsi_scan_channel  
  6.                     __scsi_scan_target  
  7.                         scsi_probe_and_add_lun  
  8.                             scsi_add_lun  
  9.                             scsi_sysfs_add_sdev  

接着调用sisc总线scsi_bus_type的match方法,匹配接着sd_probe,接着sd_probe_async同步 接着调用/bin/mount创建设备节点 update的扫描是扫描设备节点,mount命令会调用系统调用sys_mount 所以我在sys_mount的方法中调用update sys_mount定义在fs/namespace.c中 [cpp] view plain copy
  1. SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,  
  2.         char __user *, type, unsigned long, flags, void __user *, data)  
  3. {