☰
IMX6ULL嵌入式Linux学习:文件目录结构、命令与实操笔记
2026/10/12 8:18:16 网站建设 项目流程

开始学习一块新开发板时,很多人第一件事是去翻原理图、点亮LED,我反而是先把Linux文件系统完整摸了一遍。IMX6ULL这块板子看起来是硬件主导,实际上后面所有驱动、应用、交叉编译,每一步都绕不开文件目录的操作。这篇笔记是IMX6ULL学习系列的第一篇,就聚焦在Linux的文件目录结构、目录相关命令,以及我在板子上实际操作时碰到的各种情况。适合刚拿到板子、还没理清Linux目录逻辑,或者对嵌入式Linux环境下目录使用还比较模糊的朋友。

1. 嵌入式开发为什么先要啃文件目录这套东西

1.1 IMX6ULL开发环境里的目录,不只是“放文件的地方”

IMX6ULL板子上跑的是精简过的Linux系统,文件目录比Ubuntu桌面版少很多,但骨架是完整的。所谓“骨架”,指的是/bin、/usr、/etc、/dev、/proc、/sys这些一级目录都在,只是里面的内容被裁剪过。嵌入式系统最终要烧进SD卡或者EMMC,文件系统就是整个系统的“住处”。驱动要加载、应用要运行、配置要读取,全都靠目录去定位。

很多初学者会问:我直接操作ARM芯片寄存器不就行了?实际操作中,裸机开发确实可以直接操作地址,但一旦上了Linux,你写App也好,写驱动也好,最后都会落到“某个文件”上。Linux的设计哲学就是“一切皆文件”,GPIO是文件、串口是文件、内存映射也是文件。你如果不理解目录这一层,后面看设备树、看驱动框架代码的时候会非常别扭。

我自己的体会是,嵌入式开发过程中大约有七成时间不是在写代码,而是在跟命令行打交道,而命令行有一半操作是在处理目录和路径。这条基本功打不牢,后面做NFS挂载、交叉编译、启动脚本调试,每一步都会被卡一下。

1.2 从Windows思维切换过来的三个关键差异

Windows用盘符C:、D:来分门别类,每个盘有自己的根;Linux只有一个根,就是“/”。这不是细节差异,是整套路径逻辑的起点。你在IMX6ULL板子上看到的所有目录,都挂在这个“/”下面;外部存储设备比如U盘、SD卡、网络文件系统,也不是像Windows那样自动成为新盘符,而是通过“挂载”这个动作接到根目录下的某个子目录里。

第二个差异是大小写敏感。IMX6ULL的开发环境在Linux上,目录名区分大小写,/etc和/ETC是两个完全不同的地方。在Windows上习惯了随便大小写的人,初期经常在这上面翻车,配置文件写错路径,服务起不来,查了半天发现大小写不对。

第三个差异是路径的表示方式。Windows用反斜杠“\”,Linux用正斜杠“/”。在命令行里输入路径时要用/,这个看起来无所谓,真敲命令的时候却能省下不少麻烦。还有一点很实际:Windows下相对路径和绝对路径的概念比较弱,大多数人打开“我的电脑”点进某个文件夹;而在Linux下,你在哪个目录、用什么路径去定位目标文件,直接决定了命令能不能执行成功。

2. Linux文件目录结构拆解:嵌入式版

2.1 标准目录树与IMX6ULL精简后的差别

标准的Linux文件系统遵循FHS(Filesystem Hierarchy Standard)规范,也就是文件系统目录结构标准。桌面发行版为了通用性和多用户场景,目录会非常齐全;IMX6ULL这种嵌入式板子,一般是用BusyBox配合Buildroot或者Yocto生成的rootfs,裁剪力度很大。

一个完整的Ubuntu系统顶层大概会有20多个目录,而IMX6ULL板子上的顶层目录通常更精简。我拿手头这块正点原子IMX6ULL板子上的文件系统举例,开机后进入Shell执行“ls /”看到的目录大概是下面这些:

bin dev etc home lib linuxrc mnt proc root run sbin sys tmp usr var

对比一下Ubuntu,少了boot、media、opt、srv这些目录。这很正常,嵌入式rootfs不需要通用性,能跑起来、空间占用尽量小是首要目标。启动文件、内核镜像都放在单独的分区,不一定挂在根文件系统上。

以下是我整理的标准目录和嵌入式开发中各自的作用:

目录标准作用IMX6ULL场景中的实际意义
/bin基础用户命令存放BusyBox里的基本工具,比如ls、cp、mv
/sbin系统管理命令启动、文件系统修复等管理员工具
/etc系统配置文件网络、启动脚本inittab、fstab都在这
/dev设备文件GPIO、LED、串口等硬件对应的操作入口
/proc内核运行时信息查看CPU、内存、内核参数
/sys内核设备模型操作GPIO、PWM等,后面驱动开发高频使用
/usr用户程序与库应用装这里,但嵌入式下经常和根目录合并
/lib共享库存放C库和驱动模块需要的依赖库
/tmp临时文件掉电不保留、重启清空
/var可变数据日志、缓存,嵌入式下经常是tmpfs

2.2 /dev、/proc、/sys这三个目录要单独拎出来讲

这三个目录对于嵌入式开发特别重要,因为它们不是一个“存放静态文件”的普通目录,而是一个动态生成、与内核交互的窗口。

/dev是设备文件目录。在Linux下,应用程序操作一个硬件设备,就是打开/dev下面的某个文件节点,然后做读写。IMX6ULL上有串口设备/dev/ttyS0、/dev/ttymxc0,LED可能有/dev/leds,按键可能注册成/dev/key。嵌入式板子启动过程中,如果/dev下面某个设备节点不存在,对应的硬件功能基本就废了。老式的做法是手动mknod创建设备节点,现在一般靠devtmpfs启动时自动生成,或者驱动加载后注册。

/proc是一个“虚拟文件系统”,里面的内容不是磁盘上的文件,而是内核运行时的数据。比如/proc/cpuinfo能直接读到CPU信息,/proc/meminfo能读内存使用情况,/proc/modules能看当前加载了哪些驱动模块。在IMX6ULL上调驱动时,我最常用的操作之一就是“cat /proc/interrupts”看中断有没有触发。

/sys是另一个虚拟文件系统,但内容更偏向设备和驱动模型。比如/sys/class/leds下面会列出所有LED设备,进去之后有brightness文件,往里面写1就是点亮,写0就是熄灭。后续做GPIO控制实验时,很多人不直接写驱动,先通过/sys/class/gpio来操作引脚,就是这个道理。

2.3 嵌入式文件系统的“只读”思维

嵌入式设备上,根文件系统有时候是只读的,比如做成squashfs这种压缩只读文件系统,出厂后防止用户乱改。这在IMX6ULL上很常见,产品固件不希望被误删,就把根文件系统设置为只读,读写区域单独挂到/var或者/data这样的分区上。

这个习惯直接影响你用目录的方式:你不能想往哪个目录写就往哪个目录写。比如/tmp通常是可写的,因为它本质是内存文件系统tmpfs,重启后清空;/var也可能是tmpfs;但/bin、/usr这种目录很可能没有写权限。所以碰到“Permission denied”时,先别急着怪系统,先想想这个目录的设计定位是什么,只有可写目录才会给你写入机会。

3. 目录相关命令实操要点

3.1 定位当前目录:pwd 与 cd

pwd(print working directory)是最基础的命令,作用是显示当前所在目录的绝对路径。嵌入式项目里,你经常需要知道“我现在在哪”,尤其是通过串口登录板子后,Shell默认落在/root或者/home/root,如果你之前执行过cd,很容易迷失路径。

root@imx6ull:~# pwd /root

cd(change directory)是切换目录的命令。最常用的几种写法:

cd / # 切换到根目录 cd .. # 回到上一级目录 cd ~ # 回到当前用户的 home 目录 cd - # 切换到上一次所在的目录

我特别提一下“cd -”,这个在板子上调试时非常实用。你从/app目录临时去/etc看个配置,看完想回/app继续编译,直接输“cd -”就回去了,不用重新打一长串路径。

3.2 查看目录内容:ls 的常见组合

ls是最常打的命令,没有之一。单独敲ls只能看到当前目录下的非隐藏文件,信息量太少,实际工作中基本都是组合参数用:

ls -l # 长格式显示,含权限、属主、大小、修改时间 ls -a # 显示隐藏文件(以.开头的文件) ls -lh # 人类可读大小,比如显示20K而不是20480 ls -lt # 按修改时间排序,最新排前面

-l输出的第一列是权限字符串,比如“drwxr-xr-x”,第一位d表示是目录,后面9位分成三组,分别对应所有者、所属组、其他人的读/写/执行权限。看懂这个,后面遇到权限问题能快速定位。

在IMX6ULL板子上,文件系统里的很多目录内容不多,用ls -l一眼就能看到关键信息。比如查看/dev下面的设备节点,ls -l /dev/ | grep ttymxc,能直接看到串口设备对应的主设备号和次设备号。

3.3 创建和删除目录:mkdir 与 rmdir

mkdir就是make directory,创建目录。最实用的参数是-p,可以一次性创建多级目录:

mkdir /home/project/drivers mkdir -p /home/project/drivers/platform

第二条命令会把drivers和platform两级目录都建出来,如果drivers已经存在也不会报错。嵌入式开发中经常需要一次性创建一整套项目目录结构,-p参数能少敲很多命令,还能避免“目录不存在”的报错。

rmdir用于删除空目录,只能删除空目录,目录里有文件就会报“Directory not empty”。因为实际工作中很少只删空目录,所以rmdir用得不多,更常用的是“rm -r”。但这里要特别提醒,rm -r是删除目录及其全部内容,没有后悔药,板子上的目录删错了,经常只能重新刷机。新手阶段我建议先用rmdir,它逼着你确认这个目录确实是空的,不那么容易误删。

3.4 移动、复制目录:mv 与 cp

把文件或者目录从一处搬到另一处,用mv。它同时承担“重命名”的功能,因为Linux下的重命名本质就是把这个路径移到另一个路径下:

mv old_dir new_dir # 重命名目录 mv /src/dir /dest/dir # 移动目录 mv -f source target # 强制覆盖

cp复制目录时,必须加-r参数才能递归复制:

cp -r /app /backup/app_backup

很多从Windows转过来的人第一次复制目录,直接“cp 目录A 目录B”,结果报错“omitting directory”。这就是因为没加-r导致的。嵌入式系统中,需要备份整个rootfs或者把交叉编译好的库复制到/lib目录下时,cp -r是高频操作。

3.5 查找目录和文件:find、tree、du

find是Linux查找命令里最强大的一个,基本格式是:

find [查找路径] [匹配条件] [动作]

在IMX6ULL开发中使用频率最高的是按名字查找:

find / -name "*.ko" # 在根目录查找所有内核驱动模块 find /etc -name "inittab" # 查找指定的配置文件 find /sys -type d -name "leds" # 查找类型为目录且名为leds的路径

-name支持通配符,*表示任意字符,?表示单个字符。我第一次在板子上找驱动模块时,就是靠这条命令找到编译生成的.ko文件是不是已经放进/lib/modules下的正确位置。

tree命令是树状展示目录结构,但嵌入式板子的BusyBox默认不一定带这个命令,Ubuntu交叉编译环境里通常需要apt install tree。它的价值主要在项目规划阶段,比如你要搭一个应用工程目录,先列出树状图,再对照创建。

du命令用于统计目录大小,排查空间不足时很有用:

du -sh /var/log # 查看某个目录总大小 du -h --max-depth=1 /usr # 只统计一层子目录的大小

嵌入式板子的Flash或者SD卡空间有限,经常出现“No space left on device”。用du找到占用最大的目录,然后决定清理,这是排查磁盘问题的基础路子。

4. 在IMX6ULL开发板上实操:从开机到目录漫游

4.1 连接板子的两种方式与初始环境

IMX6ULL板子到手后,最常用的连接方式是串口终端和SSH网络登录。串口连接用USB转串口线,Windows下用MobaXterm或者SecureCRT,Linux下用minicom或者picocom。波特率一般是115200,8N1。接好线、上电,串口终端里就能看到Bootloader日志和文件系统启动信息。SSH则需要板子和电脑在同一网段,板子上开启SSH服务后,用MobaXterm或者命令行直接“ssh root@板子IP”登录。

登录成功后,Shell提示符一般是:

root@imx6ull:~#

root表示当前用户,imx6ull是主机名,~表示当前在root用户的home目录,就是/root。这个提示符里其实已经把“当前路径”告诉你了,后面实操过程中,每敲一条命令之前,习惯性看一眼提示符,能少走很多弯路。

4.2 做一个完整的目录探索实操

我在板子上做了一次完整的目录探索,目的是把前面讲的一级目录都看一遍,并理解它的实际内容。整个过程记录在下面,这个可以作为你拿到板子后照做的“第一课”。

先看当前路径:

root@imx6ull:~# pwd /root

查看根目录下的所有一级目录:

root@imx6ull:~# ls -l / total 184 drwxr-xr-x 2 root root 4096 Jan 1 00:00 bin drwxr-xr-x 3 root root 4096 Jan 1 00:00 dev drwxr-xr-x 4 root root 4096 Jan 1 00:05 etc drwxr-xr-x 3 root root 4096 Jan 1 00:00 home ...

Jan 1 00:00这个时间戳很有意思,说明文件系统镜像是在制作时固化的,不是实时生成。嵌入式板子在没联网校时之前,文件时间经常是这种“出厂时间”。

进入/etc目录看启动配置:

root@imx6ull:~# cd /etc root@imx6ull:/etc# ls -l

/etc目录里会有inittab、fstab、init.d这些文件。inittab是BusyBox init进程的启动配置,定义了系统启动后要跑哪些程序;fstab是文件系统挂载表,规定了哪些设备要挂到哪些目录。嵌入式系统开机流程调试,基本都是围绕这两个文件展开。

再切到/sys目录下操作一个硬件:

root@imx6ull:/sys/class/leds# ls -l

在这个目录下会看到板载LED的设备项,比如“red”或者“sys-led”。进入对应目录,查看brightness文件,往里面写入1会让LED点亮:

root@imx6ull:/sys/class/leds/sys-led# echo 1 > brightness

这个操作虽然简单,却是“目录+设备文件”理念的极致体现——你用操作普通文本文件的方式,完成了一次硬件控制。

4.3 交叉编译环境下的三套目录:Windows侧、Linux侧、板子侧

IMX6ULL开发过程中,你往往同时面对三套路径:Windows上放代码的目录、Ubuntu交叉编译环境下的目录、板子上的目标目录。这三者不能搞混,否则就会出现“我在Windows能看到文件,编译却说找不到”的尴尬。

我自己的习惯是在Ubuntu下建一个专门的workspace目录,用来存放所有工程代码,比如“/home/用户名/work/imx6ull”,然后把Ubuntu的该目录通过NFS共享给板子挂载,这样板子和开发机共享一份代码。好处是板子上修改代码,Ubuntu侧立即同步;否则每次都要通过TFTP或者U盘拷贝,效率极低还容易版本混乱。

这其中的核心思想就是目录是“逻辑组织”,不是“物理边界”。同一个工程,在Windows上看是E:盘某个目录,在Ubuntu上是/home/work目录,在板子是/mnt/nfs目录,本质是同一份东西的不同视图。你的心智模型里如果建立了“目录就是路径别名”的概念,处理起这三套目录来就不会乱。

5. 常见问题与排查技巧实录

5.1 常见报错速查表

以下是我在IMX6ULL目录操作中遇到的典型问题,以及对应的处理方式:

问题现象根本原因解决方式
Permission denied当前用户没有目标目录写权限切换root用户,检查目录权限
No such file or directory路径写错,或符号链接断裂用pwd确认当前位置,用ls检查各级路径
Not a directory把文件当目录用cd进入用ls -l确认目标类型
Directory not emptyrmdir删除非空目录改用rm -r,或者先清空内部文件
No space left on deviceFlash或内存满了用du找出大目录,清理tmp或日志
Too many open files打开了太多文件句柄检查是否重复打开设备节点,调高ulimit

5.2 断掉的软链接:嵌入式镜像里的隐藏炸弹

符号链接在嵌入式系统里用得非常频繁,例如/bin/sh可能是指向busybox的软链接,/lib可能指向/usr/lib。制作rootfs镜像时,如果软链接指向的目标路径不存在,或者链接本身没打包进镜像,就会出现“No such file or directory”的诡异报错。

排查方法是先看文件类型:

ls -l /bin/sh

输出结果里会显示“/bin/sh -> busybox”这样的信息。如果箭头后面的目标带深红色,通常说明链接断裂。嵌入式环境里我遇到过编译好的应用放在/app下,它依赖libm.so.6,而板子上的/lib目录里没有这个软链接,结果程序一启动就报“file not found”。解决方式就是找到交叉编译器自带的库目录,把libm.so.6软链接复制到板子的/lib下。

5.3 相对路径与绝对路径的切换陷阱

写嵌入式应用的启动脚本时,最坑的一个坑是工作目录不确定。用绝对路径写的脚本,无论从哪个目录启动都稳定;用相对路径写的脚本,在rcS里启动和在命令行手动启动,结果可能是两回事。

我踩过的一个实际例子:板子开机自动启动某个QT应用,脚本里写的是“./app”,开机后应用起不来,日志显示找不到程序。排查后发现,init进程启动脚本时的工作目录是根目录“/”,脚本里“./app”实际指向“/app”,但这个应用其实被放在了“/usr/bin/app”。改成绝对路径或者先cd到目标目录再执行,问题就解决了。

在脚本里稳妥的做法是先执行cd:

cd /home/root/myapp ./app &

这就避免了猜当前工作目录的问题,脚本从哪里执行都不会出错。

5.4 误用rm -rf的补救与预防

嵌入式板子上没有回收站,rm -rf误删之后基本等于需要重新刷机。我在Ubuntu交叉编译环境里有一次想清掉一个旧的build目录,本来要打“rm -rf build-old”,结果打成了“rm -rf build”,把正在用的源码目录直接删了,连带几个写好的驱动源文件一起没了。还好有git提交记录,不然那一天的活就白干了。

这个教训引发的习惯是:删除目录之前,先“ls -ld”看一下完整路径,确认路径末尾确实是你想删的那个目录名;再配合“find 路径 -maxdepth 0”确认路径存在。养成打完整绝对路径的习惯,少用那种比较模糊的“build”字样。另外,重要源代码务必纳入版本管理,板子上的编译产物就算误删,至少可以从代码里重新生成。

6. 关于下一步的一些实践建议

IMX6ULL的Linux学习,目录这块是地基,但不要停留在地基上。建议你在完成上述目录探索后,马上干两件事:一是把/etc/inittab和/etc/fstab这两个文件完整读一遍,不认识的配置项就去查,这两个文件能让你理解系统“启动之后凭什么挂载这些目录”;二是尝试在板子上的/tmp目录写一个临时脚本,练习用vim编辑、用bash执行的过程,把目录操作和命令使用串起来。

还有一个小操作值得练习:把一个SD卡插入IMX6ULL板子后,观察它自动挂载到了哪个目录(通常是/media或者/mnt),再用mount命令手动卸载、重新挂载到自定义目录。这个实验能把“挂载”这个概念完全吃透,之后做NFS调试、调试U盘启动系统都会顺利很多。

文件目录本身没什么高深技术,但它决定了你之后写驱动、调应用时“站在哪里看系统”的视角。IMX6ULL这块板子的优势在于,它把Linux内核、驱动和硬件的关系压缩在一块小小的开发板上,你看到的每个目录背后都有对应的硬件逻辑,这种“看得见摸得着”的学习路径,是纯软件环境给不了的。下一篇我会继续写Linux文件操作命令和Vim的使用,毕竟在板子上改配置、写脚本、编译代码,这三样是每天的必修课。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询