前言
我在工作的很多项目中用到了很多的sdk都是创建的只读的文件系统。只读的文件系统以为着我们不可以在系统上保存系统的配置文件。这样的感受是非常糟糕的。有没有办法让系统能够保存我们的配置文件呢?当然是可以的。
解决思路
- 首先我们要在nand flash或者nor flash中分隔出一块内存区域,用于专门存放我们的配置文件。
- 重新挂载该分区,挂载为可读可写的文件系统 / 不挂载该分区,使用dd命令直接操作。
在linux内核添加分区
网上有很多关于创建分区的文章,这里就不再提了。大家可以在网上找到对应的文章。写过驱动的小伙伴一看就懂。在这里给大家一个非常简单的方式。首先进入系统。查看分区信息
然后再linux内核代码或者设备树文件中查找关键字(boot+cfg+linux或者其他的相关的字段)。然后添加上即可
这里我添加的代码如下:
static struct mtd_partition rtl819x_parts[] = {
{
name: "boot+cfg+linux",
size: (CONFIG_RTL_ROOT_IMAGE_OFFSET-0),
offset: 0x00000000,
},
{
name: "rootfs",
#ifdef CONFIG_RTL_FLASH_DUAL_IMAGE_ENABLE
size: (CONFIG_RTL_FLASH_DUAL_IMAGE_OFFSET-CONFIG_RTL_ROOT_IMAGE_OFFSET),
#else
size: (RTK_FLASH_SIZE-CONFIG_RTL_ROOT_IMAGE_OFFSET),
#endif
offset: CONFIG_RTL_ROOT_IMAGE_OFFSET,
}
#if defined(CONFIG_BT_REPEATER_CONFIG)
#if CONFIG_RTL_BT_PARTITION_SIZE != 0x0
,
{
name: "bluetooth",
size: (CONFIG_RTL_BT_PARTITION_SIZE),
offset: RTK_FLASH_SIZE,
}
#endif
#endif
#if CONFIG_RTL_WAPI_PARTITION_SIZE != 0x0
,
{
name: "wapi",
size: (CONFIG_RTL_WAPI_PARTITION_SIZE),
offset: RTK_FLASH_SIZE,
}
#endif
#if CONFIG_RTL_1X_PARTITION_SIZE != 0x0
,
{
name: "1x",
size: (CONFIG_RTL_1X_PARTITION_SIZE),
offset: RTK_FLASH_SIZE,
}
#endif
#if CONFIG_RTL_HOMEKIT_PARTITION_SIZE != 0x0
,
{
name: "homekit",
size: (CONFIG_RTL_HOMEKIT_PARTITION_SIZE),
offset: RTK_FLASH_SIZE,
}
#endif
#if CONFIG_RTL_CWMP_TRANSFER_PARTITION_SIZE != 0x0
,
{
name: "cwmp transfer",
size: (CONFIG_RTL_CWMP_TRANSFER_PARTITION_SIZE),
offset: RTK_FLASH_SIZE,
}
#endif
#if CONFIG_RTL_CWMP_NOTIFICATION_PARTITION_SIZE != 0x0
,
{
name: "cwmp notification",
size: (CONFIG_RTL_CWMP_NOTIFICATION_PARTITION_SIZE),
offset: RTK_FLASH_SIZE,
}
#endif
#if CONFIG_RTL_CWMP_CACERT_PARTITION_SIZE != 0x0
,
{
name: "cwmp cacert",
size: (CONFIG_RTL_CWMP_CACERT_PARTITION_SIZE),
offset: RTK_FLASH_SIZE,
}
#endif
#if CONFIG_RTL_JFFS2_FILE_PARTITION_SIZE != 0x0
,
{
name: "jffs2 file",
size: (CONFIG_RTL_JFFS2_FILE_PARTITION_SIZE),
offset: RTK_FLASH_SIZE,
}
#endif
#if 0//defined(MTD_PARTITION_TEST)
,
{
name: "mtd_test",
size: (MTD_PARTITION_TEST_SIZE),
offset: RTK_FLASH_SIZE,
}
#endif
#if defined(MTD_PARTITION_CONFIG)
,
{
name: "zhongheng",
size: (MTD_PARTITION_CONFIG_SIZE),
offset: RTK_FLASH_SIZE,
}
#endif
// dual image support
#if defined(CONFIG_RTL_FLASH_DUAL_IMAGE_ENABLE)
,
{
name: "boot+cfg+linux2",
size: (CONFIG_RTL_ROOT_IMAGE_OFFSET-0),
offset: 0x00000000+CONFIG_RTL_FLASH_DUAL_IMAGE_OFFSET,
}
,
{
name: "rootfs2",
size: (RTK_FLASH_SIZE-CONFIG_RTL_FLASH_DUAL_IMAGE_OFFSET-CONFIG_RTL_ROOT_IMAGE_OFFSET),
offset: CONFIG_RTL_ROOT_IMAGE_OFFSET+CONFIG_RTL_FLASH_DUAL_IMAGE_OFFSET,
}
#if CONFIG_RTL_WAPI_PARTITION_SIZE != 0x0
,
{
name: "wapi2",
size: (CONFIG_RTL_WAPI_PARTITION_SIZE),
offset: RTK_FLASH_SIZE,
}
#endif
#if CONFIG_RTL_1X_PARTITION_SIZE != 0x0
,
{
name: "1x2",
size: (CONFIG_RTL_1X_PARTITION_SIZE),
offset: RTK_FLASH_SIZE,
}
#endif
#if CONFIG_RTL_HOMEKIT_PARTITION_SIZE != 0x0
,
{
name: "homekit2",
size: (CONFIG_RTL_HOMEKIT_PARTITION_SIZE),
offset: RTK_FLASH_SIZE,
}
#endif
#if CONFIG_RTL_CWMP_TRANSFER_PARTITION_SIZE != 0x0
,
{
name: "cwmp transfer2",
size: (CONFIG_RTL_CWMP_TRANSFER_PARTITION_SIZE),
offset: RTK_FLASH_SIZE,
}
#endif
#if CONFIG_RTL_CWMP_NOTIFICATION_PARTITION_SIZE != 0x0
,
{
name: "cwmp notification2",
size: (CONFIG_RTL_CWMP_NOTIFICATION_PARTITION_SIZE),
offset: RTK_FLASH_SIZE,
}
#endif
#if CONFIG_RTL_CWMP_CACERT_PARTITION_SIZE != 0x0
,
{
name: "cwmp cacert2",
size: (CONFIG_RTL_CWMP_CACERT_PARTITION_SIZE),
offset: RTK_FLASH_SIZE,
}
#endif
#if CONFIG_RTL_JFFS2_FILE_PARTITION_SIZE != 0x0
,
{
name: "jffs2 file2",
size: (CONFIG_RTL_JFFS2_FILE_PARTITION_SIZE),
offset: RTK_FLASH_SIZE,
}
#endif
#endif
};
#endif
zhongheng分区就是新创建的分区。name填写上中衡即可。size为分区的大小。offset是地址的偏移。
如果分区添加成功,则可以通过cat /proc/mtd看到该分区的信息。
分区的操作
挂载分区的方式
首先第一种方式就是挂载分区到指定的目录。当然这里挂载的文件系统必须是可读可写的文件系统。比如yaffs或者yaffs2或者jffs2。具体的步骤如下
- 在系统代码中创建初始化的路径,比如我在根目录下创建的zhongheng目录。(关于这一块大家理解意思即可,每个sdk都是不一样的。但是因为是只读文件系统,所以系统启动起来之后的目录一定是在代码中创建的。而我们的目的就是找到这个地方即可)
- 挂载分区:分区的挂载肯定是使用mout命令。我使用的命令如下:mount -t jffs2 /dev/mtdblock2 /zhongheng 这里的mtdblock2是mtd的编号。也可以通过df查看(cat /proc/mtd也可以看到)
最后我们就可以愉快的对该文件夹进行读写了。
不挂载分区
有些时候我们系统的分区执行挂载命令的时候会报错。挂载不上去。我这里提供一种通用的,万无一失的方案(使用dd命令)。将所有的配置文件打包,然后使用dd写入我们创建的分区中(保存配置文件)。开机的时候使用dd命令从分区中读取文件到我们指定的目录(比如tmp,当然也可以将已经存在的不可写的目录挂载为ramfs。将dd读取到的文件加压即可)。下面给出一些例子
mkdir -p /tmp/etc
cp -ap /etc/* /tmp/etc/
mount ramfs /etc -t ramfs
cp -ap /tmp/etc/* /etc/
rm -fr /tmp/etc
mkdir -p /etc/zhongheng/config
这样就将etc挂载为ramfs的文件系统,变为可读可写。并且创建了我们的配置文件的路径zhongheng/config
接着我们来看看dd命令的使用
#!/bin/sh
. /usr/sbin/config.inc
case $1 in
"get")
dd if=/dev/mtdblock2 of=/tmp/config.tgz bs=100k count=1
tar -xvf /tmp/config.tgz -C /etc/zhongheng/
rm -f /tmp/config.tgz
;;
"set")
tar -cvf /tmp/config.tgz /etc/zhongheng/config >/dev/null 2>/dev/null
dd if=/tmp/config.tgz of=/dev/mtdblock2 bs=100k count=1 >/dev/null 2>/dev/null
rm -f /tmp/config.tgz
;;
esac
我们可以看到,保存文件和读取文件都是使用dd命令直接写入分区。这是一个通用的方案。优先选择第一种方案,如果第一种方案不行,可以选择第二种。