在学习资料满天飞的大环境下,知识变得非常零散,体系化的知识并不多,这就导致很多人每天都努力学习到感动自己,最终却收效甚微,甚至放弃学习。我的使命就是过滤掉大量的垃圾信息,将知识体系化,以短平快的方式直达问题本质,把大家从大海捞针的痛苦中解脱出来。
1 制作jffs2根文件系统镜像
1.1 制作jffs2工具
由于jffs2文件系统具有压缩功能,所以制作jffs2工具时需要zlib压缩库。
- 安装zlib动态库
# 在ubuntu系统中操作
albert@ubuntu:/work/jffs2 $ tar xzvf zlib-1.2.3.tar.gz #解压缩源码
albert@ubuntu:/work/jffs2/zlib-1.2.3 $ ./configure --shared #配置:需要生成动态库
albert@ubuntu:/work/jffs2/zlib-1.2.3 $ make #编译
albert@ubuntu:/work/jffs2/zlib-1.2.3 $ sudo make install #安装
albert@ubuntu:/work/jffs2/zlib-1.2.3 $ ls /usr/local/lib #查看发现安装成功(libz开头的三个动态库)
libz.so libz.so.1 libz.so.1.2.3 python2.7 python3.4 site_ruby
- 安装jffs2工具
# 在ubuntu系统中操作
albert@ubuntu:/work/jffs2 $ tar xjvf mtd-utils-05.07.23.tar.bz2 #解压缩源码
albert@ubuntu:/work/jffs2/mtd-utils-05.07.23/util $ make #编译
albert@ubuntu:/work/jffs2/mtd-utils-05.07.23/util $ sudo make install #安装
albert@ubuntu:/work/jffs2/mtd-utils-05.07.23/util $ mkfs<按tab> #查看发现安装成功(mkfs.jffs2)
mkfs mkfs.cramfs mkfs.ext3 mkfs.ext4dev mkfs.jffs mkfs.minix mkfs.ntfs
mkfs.bfs mkfs.ext2 mkfs.ext4 mkfs.fat mkfs.jffs2 mkfs.msdos mkfs.vfat
1.2 制作jffs2根文件系统镜像
在上两篇中我们已经准备好了根文件系统的内容,下面只需要使用mkfs.jffs2工具制作成镜像即可。
# 在ubuntu系统中操作
albert@ubuntu:/work/nfsroot $ mkfs.jffs2<然后回车> #这样可以查看该工具的使用说明(各个参数的含义)。
...
albert@ubuntu:/work/nfsroot $ mkfs.jffs2 -d minifs -o minifs.jffs2 -s 2048 -e 128KiB -n #制作镜像
albert@ubuntu:/work/nfsroot $ ls -al #制作镜像成功,发现minifs.jffs2比minifs.yaffs2的一半还要小
-rw-r--r-- 1 albert albert 4128688 Nov 2 22:18 minifs.jffs2
-rw------- 1 albert albert 8872512 Oct 31 23:19 minifs.yaffs2
1.3 配置uboot启动参数
下载我们刚刚制作的minifs.jffs2到嵌入式设备启动后报下述错误:
# S3C2440启动过程中的控制台打印
yaffs: dev is 32505859 name is "mtdblock3"
yaffs: passed flags ""
yaffs: Attempting MTD mount on 31.3, "mtdblock3"
yaffs: auto selecting yaffs2 #这里默认挂载的根文件系统类型是yaffs2
block 649 is bad
block 1335 is bad
block 1991 is bad
VFS: Mounted root (yaffs filesystem).
Freeing init memory: 140K
Warning: unable to open an initial console. #所以这里找不到/dev/console设备节点文件
Failed to execute /linuxrc. Attempting defaults... #也找不到/linuxrc文件
Kernel panic - not syncing: No init found. Try passing init= option to kernel. #init进程初始化失败
产生上述错误主要是内核默认情况下认为根文件系统的类型就是yaffs2。现在我们换成了jffs2,要通过某种方式告诉内核。这种方式就是配置uboot的启动参数。
修改前:bootargs=noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0,115200。
修改后:bootargs=noinitrd root=/dev/mtdblock3 rootfstype=jffs2 init=/linuxrc console=ttySAC0,115200
修改过程如下:
# 在S3C2440嵌入式设备中修改
# 使用uboot指令修改uboot启动参数
OpenJTAG> set bootargs noinitrd root=/dev/mtdblock3 rootfstype=jffs2 init=/linuxrc console=ttySAC0,115200 #设置启动参数
OpenJTAG> print bootargs #查看设置结果(此时只是修改了内存)
bootargs=noinitrd root=/dev/mtdblock3 rootfstype=jffs2 init=/linuxrc console=ttySAC0,115200
OpenJTAG> saveenv #保存修改结果到nand flash
Saving Environment to NAND...
Erasing Nand...Writing to Nand... done
修改uboot启动参数之后重新启动系统成功。
2 配置nfs根文件系统
接下来,我们搞一个非常有意思的东西——让嵌入式设备直接从你电脑硬盘启动。这样,每次修改完根文件系统的代码或者应用程序代码,编译完直接放到指定目录就可以被嵌入式设备看到了。开发效率杠杠滴!!!
话不多说,我们马上开始。
2.1 保证嵌入式开发板可以ping通电脑
先简单说一下流程。首先要找一根网线连接嵌入式设备和电脑(我使用的是Ubuntu系统,不建议使用windows系统,否则还要装nfs服务器)。在电脑上(如果使用了虚拟机,记得网络访问使用桥接模式)配置一个静态调试IP(比如172.27.45.101),在嵌入式设备上配置同一网段的静态IP(比如172.27.45.250)。然后就能相互ping通了(说起来好轻松啊,鄙视的表情)。
这个过程中可能(或者说一定)会遇到些小问题,如果你装的是windows,在windows中装了一个虚拟机,然后在虚拟机中装的Ubuntu系统,那么恭喜你,你必须要花时间搞清楚两个问题:如何配置桥接模式并指定物理网卡;如何在Ubuntu系统中配置静态IP地址。(由于篇幅问题,这里就不展开了,相信你能搞定滴,实在不行可以留言或私信我~)
另外一个,就是在嵌入式设备上配置静态IP,这个我刚好写过博客,链接如下:
https://blog.csdn.net/weixin_44873133/article/details/105938190
ping通后的效果如下图:
2.2 开启nfs服务器
我们以Ubuntu系统为例说明如何开启nfs服务器。
先说一下nfs是个啥。nfs全拼net file system,所谓网络文件系统和我们接触过的yaffs2、jffs2有什么不同呢?最大的不同就是文件的内容是通过网络加载到内存中的,而flash类型的文件系统是通过读flash加载到内存中的。先理解到这里就可以了,抓住 主要矛盾 ,细节上的差异等研究文件系统实现的时候再 逐步 深入。
所以,开启nfs服务也就很好理解了,就是将nfs程序运行起来,并且指定一个目录允许别人通过网络访问而已。
下面具体操作一下。
- 修改/etc/exports配置文件
# 在Ubuntu系统内操作
albert@ubuntu:/etc $ sudo vi exports #注意需要使用root权限
# 在/etc/exports(Unbunt目录)文件中把允许挂载的路径添加进去
/work/nfsroot/minifs *(rw,sync,no_root_squash) #no_root_squash indicate the user has root authority
- 重启nfs服务器
# 在Ubuntu系统内操作
albert@ubuntu:/etc/init.d $ sudo ./nfs-kernel-server restart #重启nfs服务器
- 检查是否启动成功
# 在Ubuntu系统内操作(自己mount自己)
albert@ubuntu:~ $ sudo mount -t nfs 172.27.45.101:/work/nfsroot/minifs /mnt
albert@ubuntu:~ $ ls /mnt #自己mount自己成功
bin dev etc lib linuxrc proc sbin sys test usr
# 在嵌入式设备终端上操作
/ # mount -t nfs 172.27.45.101:/work/nfsroot/minifs /mnt -o nolock #注意不要使用文件锁,否则会失败
/ # ls /mnt #已经成功mount到宿主机的路径
bin etc linuxrc sbin test
dev lib proc sys usr
2.3 配置uboot启动参数
修改前:bootargs=noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0,115200
修改后:bootargs=noinitrd root=/dev/nfs nfsroot=172.27.45.101:/work/nfsroot/minifs ip=172.27.45.250:172.27.45.101:172.27.45.1:255.255.255.0:albert:eth0:off init=/linuxrc console=ttySAC0,115200
修改过程如下:
# 在S3C2440嵌入式设备中修改
# 使用uboot指令修改uboot启动参数
OpenJTAG> set noinitrd root=/dev/nfs nfsroot=172.27.45.101:/work/nfsroot/minifs ip=172.27.45.250:172.27.45.101:172.27.45.1:255.255.255.0:albert:eth0:off init=/linuxrc console=ttySAC0,115200 #设置启动参数
OpenJTAG> saveenv #保存修改结果到nand flash
Saving Environment to NAND...
Erasing Nand...Writing to Nand... done
下面对参数格式作一个说明(参考内核源码中/Documentation/nfsroot.txt)。
参数项 | 参数格式 | 说明 |
---|---|---|
root | root=/dev/nfs | 只是告诉内核使用nfs虚拟文件系统,其实并不存在/dev/nfs。 |
nfsroot | nfsroot=[<server-ip>:]<root-dir>[,<nfs-options>] | 用来指定nfs服务器ip和根文件系统路径。nfs-options可以省略。 |
ip | ip=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf> | 主要作用是配置客户端(本地)的网卡和ip。我们是用网线直连,gw-ip填多少无所谓。hostname随便起,也可以空着。device一定要填对,是网卡名。autoconf自动配置选项关闭就可以了。 |
重新启动嵌入式设备,设备成功挂载nfs根文件系统并启动,如下图:
根文件系统的制作/移植就告一段落了,是不是还回味无穷呢~
恭喜你又坚持看完了一篇博客,又进步了一点点!如果感觉还不错就点个赞再走吧,你的点赞和关注将是我持续输出的哒哒哒动力~~