Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
文件系统学习营
文件系统学习 + Eric + rt1052文件系统-从romfs中将tar文件解压
发布于 2018-07-28 12:36:41 浏览:3052
订阅该版
[tocm] # 软硬件准备工具 - rtthread最新源码,建议从github上下载 - evn工具,全功能版(0.7.0版本) - 硬件板卡:野火rt0152 mini # 制作romfs 1. 进入rt-thread\components\dfs\filesystems omfs目录下,创建一个romfs目录 ![14.png](/uploads/201807/28/123503u5a8flz1a8a8o8nq.png) 2. 在我们创建的romfs中,创建一个文件夹sdcard,用于挂载我们的sd卡,同时在里面创建一个文件,使用英文命名,并添加一些内容。 ![15.png](/uploads/201807/28/123503up7371bcpc7b9fz1.png) 注意:如果不添加这个文件,会在之后的程序编译遇到一下错误: ``` compiling romfs.c... ..\..\components\dfs\filesystems omfs omfs.c(7): error: #29: expected an expression }; ..\..\components\dfs\filesystems omfs omfs.c(5): error: #1514: an empty initializer is invalid for an array with unspecified bound static const struct romfs_dirent _romfs_root_sdcard[] = { ..\..\components\dfs\filesystems omfs omfs.c(14): error: #44: expression must have pointer type { OMFS_DIRENT_DIR, "sdcard", (rt_uint8_t *)_romfs_root_sdcard, sizeof(_romfs_root_sdcard)/sizeof(_romfs_root_sdcard[0])}, ..\..\components\dfs\filesystems omfs omfs.c(19): error: #44: expression must have pointer type OMFS_DIRENT_DIR, "/", (rt_uint8_t *)_romfs_root, sizeof(_romfs_root)/sizeof(_romfs_root[0]) ..\..\components\dfs\filesystems omfs omfs.c: 0 warnings, 4 errors ``` ![image](D:\workspace tthread\week_2\picture\16.png) ![16.png](/uploads/201807/28/123504smqo0f8vfgqgfxfu.png) 3. 返回我们之前的目录rt-thread\components\dfs\filesystems omfs下,使用env调用如下命令,制作我们的romfs.c ![17.png](/uploads/201807/28/123504sgerzqt86e7z26gh.png) # 来到bsp中,使用menuconfig配置工程,配置完成后,使用scons生成mdk5工程 ![18.png](/uploads/201807/28/123505wln2z9ry22jzukgo.png) # 修改我们的main.c,挂在romfs ``` result = mmcsd_wait_cd_changed(RT_TICK_PER_SECOND); if (result == MMCSD_HOST_PLUGED) { if (dfs_mount(RT_NULL, "/", "rom", 0, &(romfs_root)) == 0) rt_kprintf("ROM System initialized!
"); else rt_kprintf("ROM System init failed!
"); /* mount sd card fat partition 1 as root directory */ if (dfs_mount("sd0", "/sdcard", "elm", 0, 0) == 0) rt_kprintf("File System initialized!
"); else rt_kprintf("File System init failed!
"); } else { rt_kprintf("sdcard init fail or timeout: %d!
", result); } ``` 运行程序能看到如下: ![19.png](/uploads/201807/28/123505lbzfndgghh9kk7bq.png) romfs挂载成功 # 进入正题,了解tar文件格式,更详细内容,请自行百度 tar格式的设计最初是为了在磁带上归档一堆文件。 一个tar文件由一个个文件块构成,每个文件块都是一个原本文件的封装。 文件块顺序摆放,在末尾加上一个全0的512字节标志。但是实际上这个标志不一定存在(例如我拿到的一个tar文件就么有这512个0),因此打开tar文件的时候不能依赖这个标志,而要依赖文件结尾来判断tar文件的结束。 每个文件块由一个个block(512字节)构成,这也是结束标志是512字节的原因所在。 每个文件块的开头第一个block是一个header,是tar格式的封装信息。其余block是将原文件按照512字节分块之后,依次存储下来的,末尾补0以对其到512字节。如果文件刚好是512字节的倍数,那就不用补0了,因此文件大小和tar打包之后占用的block数的计算是 Block数 = (文件字节数 + 511)/ 512 header的结构如下: ``` struct header { char name[100]; char mode[8]; char uid[8]; char gid[8]; char size[12]; char mtime[12]; char chksum[8]; char linkflag; char linkname[100]; char magic[8]; char uname[32]; char gname[32]; char devmajor[8]; char devminor[8]; char prefix[155] char padding[12]; }; ``` 所有字节都被解释为了ascii字符,因此每个字段以 '\0'结尾。 其中 size和checksum是8进制数。 mtime使用 “Unix时间”。 linkflag是'5'表示这个文件是目录,那么这个文件块将没有数据,下一个block就是下一个文件块。其余情况还有“符号链接”等等,这里暂时不深入讨论,可以参考:http://www.moon-soft.com/program/FORMAT/comm/tar.htm magic是一个字符串"ustar",用于标示这是一个tar文件(头)。 # 代码编写,解压tar ``` struct tar_header { char name[100]; char mode[8]; char uid[8]; char gid[8]; char size[12]; char mtime[12]; char chksum[8]; char typeflag; char linkname[100]; char magic[6]; char version[2]; char uname[32]; char gname[32]; char devmajor[8]; char devminor[8]; char prefix[155]; char padding[12]; }tsTarHeader; #define UNTAR_TARGET_DIR "/sdcard/" #define TAR_FILE_BLOCK_SIZE 512 #define TAR_FILE_TYPE_FILE '0' #define TAR_FILE_TYPE_DIR '5' //八进制转十进制 int convertOctalToDecimal(int octalNumber) { int decimalNumber = 0, i = 0; while(octalNumber != 0) { decimalNumber += (octalNumber%10) * pow(8,i); ++i; octalNumber/=10; } return decimalNumber; } int main(void) { rt_uint32_t result; int tar_fd, size, block_num = 0, i, j, k; struct stat buf; struct tar_header tar_file_header; char target_dir[128] = {0}, file_dir[128] = {0}; rt_uint8_t block_data[TAR_FILE_BLOCK_SIZE]; int file_total_size; //dump_clock(); dump_cc_info(); dump_link_info(); rt_kprintf("build time: %s %s
", __DATE__, __TIME__); #if defined(RT_USING_DFS) && defined(RT_USING_SDIO) result = mmcsd_wait_cd_changed(RT_TICK_PER_SECOND); if (result == MMCSD_HOST_PLUGED) { if (dfs_mount(RT_NULL, "/", "rom", 0, &(romfs_root)) == 0) rt_kprintf("ROM System initialized!
"); else rt_kprintf("ROM System init failed!
"); /* mount sd card fat partition 1 as root directory */ if (dfs_mount("sd0", "/sdcard", "elm", 0, 0) == 0) rt_kprintf("File System initialized!
"); else rt_kprintf("File System init failed!
"); } else { rt_kprintf("sdcard init fail or timeout: %d!
", result); } #endif stat("/untar_test.tar", &buf); rt_kprintf("untar_test.tar file size = %d block %d
", buf.st_size, buf.st_size/512); rt_kprintf("tar_header size %d
", sizeof(struct tar_header)); block_num = buf.st_size/512; fd = open("/untar_test.tar", O_RDONLY); if (fd < 0) { rt_kprintf("Failed to open %s
", "untar_test.tar"); } for(i = 0; i < block_num; i++) { size = read(fd, &tar_file_header, sizeof(struct tar_header)); if((size == TAR_FILE_BLOCK_SIZE) && !(strcmp(tar_file_header.magic, "ustar"))) { //rt_kprintf("block:%d name:%s typeflag:%c
", i, tar_file_header.name, tar_file_header.typeflag); if(tar_file_header.typeflag == TAR_FILE_TYPE_DIR) { //将读到的目录创建出来 memset(target_dir, 0, sizeof(target_dir)); strcat(target_dir, UNTAR_TARGET_DIR); strcat(target_dir, tar_file_header.name); mkdir(target_dir, 0x777); } else if(tar_file_header.typeflag == TAR_FILE_TYPE_FILE) { //先创建文件目录 memset(file_dir, 0, sizeof(file_dir)); strcat(file_dir, UNTAR_TARGET_DIR); strcat(file_dir, tar_file_header.name); for(j=(rt_strlen(file_dir)-1); j--; j>0) if(file_dir[j] == '/') file_dir[j+1] = 0; //截断 mkdir(file_dir, 0x777); //在开始创建文件 memset(file_dir, 0, sizeof(file_dir)); strcat(file_dir, UNTAR_TARGET_DIR); strcat(file_dir, tar_file_header.name); tar_fd = open(file_dir, O_RDWR | O_CREAT | O_APPEND, 0); if(tar_fd < 0) rt_kprintf("open %s failed
", tar_file_header.name); file_total_size = convertOctalToDecimal(atoi(tar_file_header.size)); j = 0; } } else { memcpy(block_data, &tar_file_header, TAR_FILE_BLOCK_SIZE); k = 0; for( k = 0; k
= file_total_size) close(tar_fd); } } } close(fd); while (1) { rt_thread_delay(RT_TICK_PER_SECOND); } } ``` 编译运行如下: ![20.png](/uploads/201807/28/123506hk4sok4oy70h4ho0.png) ==bingo!!!== # 注意 - 制作romfs,添加一个非空文件在sdcard目录下,报错的原因我觉得应该是编译器导致的,我使用其他编译器,没有这个情况。 - menuconfig配置记得如上 - 根目录下是不能创建文件的,需要在sdcard中创建文件 - tar读取文件数据的时候,记得判断文件结束
查看更多
0
个回答
默认排序
按发布时间排序
暂无答案,快来添加答案吧
撰写答案
登录
注册新账号
关注者
0
被浏览
3.1k
关于作者
EricYYG
这家伙很懒,什么也没写!
提问
13
回答
9
被采纳
0
关注TA
发私信
相关问题
1
【文件系统学习】+DMY+任务1sample例程
2
【文件系统学习】skawu的文件系统跑起来了
3
【文件系统学习】bin5219在qemu-vexpress-a9 中运行一个.c
4
【文件系统学习】skawu之文件匹配学习
5
【文件系统学习】+海中陆地+成功运行文件系统,并运行文...
6
【文件系统学习】+清石+运行文件系统sample例程
7
【文件系统学习】+小燕+运行文件系统sample例程
8
【文件系统学习】+阿暖+运行文件系统 sample 例程
9
【文件系统学习】+小燕+一系列文件中找出指定文件
10
【文件系统学习】+小燕+文件数据替换
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
如何在master上的BSP中添加配置yml文件
2
使用百度AI助手辅助编写一个rt-thread下的ONVIF设备发现功能的功能代码
3
RT-Thread 发布 EtherKit开源以太网硬件!
4
rt-thread使用cherryusb实现虚拟串口
5
《C++20 图形界面程序:速度与渲染效率的双重优化秘籍》
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
UART
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
keil_MDK
rt_mq_消息队列_msg_queue
ulog
C++_cpp
at_device
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
a1012112796
14
个答案
2
次被采纳
张世争
9
个答案
2
次被采纳
rv666
5
个答案
2
次被采纳
用户名由3_15位
13
个答案
1
次被采纳
本月文章贡献
程序员阿伟
9
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
大龄码农
1
篇文章
5
次点赞
RTT_逍遥
1
篇文章
2
次点赞
ThinkCode
1
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部