参考文献:【超全面】Linux嵌入式干货学习系列教程_嵌入式教程-CSDN博客
1 基础篇
1.1 常用命令
$ ls -R # 递归显示当前文件夹下所有文件(包括子文件夹文件)
# 示例
.:
CyanDB lc-regex lc-regex.cpp math run.sh
./CyanDB:
README.md test.cpp
./math:
logic.cpp logic.hpp main main.cpp polynomial.hpp test
./math/test:
test1.txt
$ cd - # 回到上一次工作目录(并且还会打印上一次工作目录)
$ cat <文件名> # 打印<文件名>内容
$ cat <文件名> -b # 非空行带行号打印
$ cat <文件名> -n # 所有行带行号打印
$ head <文件名> -n <行数> # 打印<文件名>前<行数>行
$ tail <文件名> -n <行数> # 打印<文件名>后<行数>行
$ cp -i <源文件> <目标文件> # 复制源文件到目标文件,覆盖文件时提示
$ cp -r <源文件夹> <目标文件夹> # 复制源文件夹到目标文件夹内
$ mv <源文件1>{ <源文件2> ...} <目标文件夹> # 移动一个或多个源文件到目标文件夹内
$ mv <源文件> <目标文件夹>/<源文件新名字> # 移动并重命名源文件(不能操作多个源文件)
$ rm -R <文件夹> # 删除一个文件夹
$ rm -i <文件名> # 删除时询问(注意,与-R配合时不会显示子文件)
1.2 包管理
1.2.1 deb包
Debian系列用.deb,Redhat系列用.rpm。命名:<包名>_<版本>-<修订版本>_<架构>.deb
deb包管理用dpkg,-i 安装,-P 移除并删配置文件,-l 列出所有已安装的包,-s 显示安装状态。
一般从网上下载.deb文件然后使用
sudo dpkg -i <包名>
进行安装
1.2.2 apt包
apt包管理用apt,常用的功能有
apt search <字符串> # 搜索包
sudo apt update # 获取仓库更新
sudo apt upgrade # 更新所有能更新的包
sudo apt install <包名> # 安装指定名称的包
sudo apt remove --purge <包名> # 删除指定名称的包
通过修改/etc/apt/sources.list可以改变apt源,即所获取的网上仓库的网址。
仓库分为四种:
- 核心 Main:官方维护的开源软件
- 公共 Universe:社区维护的开源软件
- 受限 Restricted:官方维护的非开源软件
- 多元化 Multiverse:社区维护的非开源软件
1.3 shell
1.3.1 正则表达式
file_*.txt # 可通配任何长度的字符串
file_?.txt # 可通配一个字符
file_[otr].txt # 可匹配o、t、r中任意一个字符
file_[^otr].txt # 可匹配除了o、t、r的所有字符
file_[a-z].txt # 可匹配a-z的所有字符
1.3.2 管道和重定向
<命令1> | <命令2> | ... # 把前一个命令的输出结果作为后一个命令的输入
<命令> > <文件> # 将命令的结果覆盖到文件
<命令> >> <文件> # 将命令的结果追加到文件
<命令> < <文件> # 以文件作为命令的输入
<命令> 2> <文件> # 将错误信息输入到文件,2>也可替换为&>
1.4 磁盘管理
df # disk free,获取磁盘剩余空间的大小;路径没什么用,只会显示路径所在整个磁盘的情况
df -h # --human-readable,用适当的单位呈现
du <路径> # disk usage,获取目录下所有文件占用的空间,缺省为/
1.5 用户管理
参考文献2:https://www.cnblogs.com/davis12/p/14373311.html
用户登录时,系统查询/etc/passwd进行验证。然而进去看到密码全是x,经过了加密。真正的密码放在/etc/shadow。
参考文献3:/etc/skel/目录-CSDN博客
/etc/skel里的东西用来初始化新用户,包括.bashrc这些,都是从这里复制过来的。修改这里就可以统一配置所有新用户。
添加新用户过程:
- 编辑/etc/passwd和/etc/shadow两个文件,定义用户账号
- 设置初始密码
- 为用户创建主目录,用chown和chmod给新用户
- 将/etc/skel中的默认配置文件复制到用户的主目录中
- 邮件之类的配置,基本用不到
常用命令:
adduser <username> # 添加用户
deluser [--remove-home] <username> # 删除用户(可以连主目录一并删除)
addgroup <group-name> # 添加用户组
delgroup <group-name> # 删除用户组
passwd <username> # 修改用户密码
usermod -l <newname> <username> # 修改用户名
usermod -aG <group-name> <username> # 添加用户到组
sudo usermd -aG sudo <username> # 添加用户到sudoer组
1.6 进程管理
1.6.1 管理工具
ps au比较常用,ps aux会显示一些没什么用的东西。
前后台管理:
- ./test & :把程序挂到后台运行
- fg:将后台进程拉到前台运行
- jobs显示后台进程(进程要被手动挂到后台才能在后台运行,并不是说任何没有显示在当前终端上的都是后台进程)
- Ctrl + Z:把当前运行的程序挂到后台并暂停
- bg:让暂停的程序在后台运行
参考文献4:https://linuxize.com/post/ps-command-in-linux/
会显示一堆参数,含义分别为
PID | %CPU | %MEM | VSZ | RSS | |
含义 | 进程编号 | CPU占用 | 内存占用 | 虚存分配量 | 内存实际使用量 |
TTY | STAT | START | TIME | COMMAND | |
含义 | 控制台名称 | 运行状态 | 开始时间 | CPU占用时间 | 启动进程的命令 |
其中TTY属性的值可能为pts/*(pseudo-terminal slave,伪终端,用于远程登录)或是hvc0(Xen虚拟控制台)等。物理机上用Ctrl+Alt+T打开的也是虚拟终端,有一些/lib/exec/...里的东西是用tty1跑的。
参考文献5:https://www.cnblogs.com/programmer-tlh/p/11593330.html
STAT状态字符含义分别为
D | R | S | T | X | Z | |
含义 | IO | 运行 | 休眠 | 停止 | 死亡 | 僵尸 |
< | N | L | s | l | + | |
含义 | 优先级高 | 优先级低 | 有页锁在内存 | 有子进程 | 克隆进程 | 后台 |
详细解释:
- D代表“无法中断的休眠”,大部分时候是IO,但并非全部。
- L表示有一些页被设定不能被交换到磁盘中。
要查看进程状态可以使用top命令,也可以安装htop,能看得更清晰一些。
这两个都是按q退出,按shift+<和shift+>翻页。
1.6.2 进程树
进程树用pstree查看,形如(以下是wsl2 ubuntu 23.04的输出结果)
# ubuntu 23.04上的输出
$ pstree
init(ubuntu-23.─┬─SessionLeader───Relay(12)───bash───pstree
├─SessionLeader───Relay(113)───bash───htop
├─init───{init}
└─{init(ubuntu-23.}
$ pstree -p # 显示pid
init(ubuntu-23.(1)─┬─SessionLeader(10)───Relay(12)(11)───bash(12)───pstree(278)
├─SessionLeader(111)───Relay(113)(112)───bash(113)───htop(275)
├─init(7)───{init}(8)
└─{init(ubuntu-23.}(9)
$ pstree -p # 开了vscode之后
init(ubuntu-23.(1)─┬─SessionLeader(10)───Relay(12)(11)───bash(12)───pstree(753)
├─SessionLeader(111)───Relay(113)(112)───bash(113)
├─SessionLeader(325)───Relay(327)(326)───sh(327)───sh(328)───sh(333)───node(337)─┬─node(360)─┬─{node+
│ │ ├─{node+
│ │ ├─{node+
│ │ ├─{node+
│ │ ├─{node+
│ │ ├─{node+
│ │ ├─{node+
│ │ ├─{node+
│ │ ├─{node+
│ │ ├─{node+
│ │ ├─{node+
│ │ └─{node+
│ ├─node(400)─┬─{node+
│ │ ├─{node+
│ │ ├─{node+
│ │ ├─{node+
│ │ ├─{node+
│ │ ├─{node+
│ │ ├─{node+
│ │ ├─{node+
│ │ ├─{node+
│ │ ├─{node+
│ │ └─{node+
│ ├─{node}(338)
│ ├─{node}(339)
│ ├─{node}(340)
│ ├─{node}(341)
│ ├─{node}(342)
│ ├─{node}(343)
│ ├─{node}(344)
│ ├─{node}(345)
│ ├─{node}(346)
│ └─{node}(347)
├─SessionLeader(348)───Relay(350)(349)───node(350)─┬─{node}(351)
│ ├─{node}(352)
│ ├─{node}(353)
│ ├─{node}(354)
│ ├─{node}(355)
│ └─{node}(356)
├─SessionLeader(389)───Relay(391)(390)───node(391)─┬─{node}(392)
│ ├─{node}(393)
│ ├─{node}(394)
│ ├─{node}(395)
│ ├─{node}(396)
│ └─{node}(397)
├─init(7)───{init}(8)
└─{init(ubuntu-23.}(9)
gpt解释:
- init是由内核启动的第一个进程,是其他所有进程的祖先,负责管理其他进程的生命周期。
- SessionLeader是init负责管理用户会话(登录、操作之类)的子进程。根据pstree -p的结果可以看出,每个session对应的SessionLeader都是独立的进程。
- Relay(xxx)没讲明白,但根据pstree -p的结果可以看出,Relay括号里的是其所管理的bash终端的pid。第二个示例中,我运行pstree和htop的是两个bash终端。第三个示例中,似乎不会出现一个SessionLeader对应多个Relay的情况。
- 比较诡异的是这四个init,其中init(ubuntu-23.(1)是根进程,init(7)据说是init的子进程。
- 加了花括号{}的据说是轻量级进程或线程,所以剩下两个init可以看出关系,但不知道含义。
根据参考文献1的解释:
- 进程组:进程集合,有一个组长,其进程ID为进程组ID(大概是Relay)
- 会话:进程组集合,有一个组长,其进程ID为会话ID(即SessionLeader)
- 控制进程:与终端相连接的组长就是控制进程(也即SessionLeader)
而在wsl2 ubuntu 20.04上就更抽象:
$ pstree -p
systemd(1)─┬─ModemManager(358)─┬─{ModemManager}(382)
│ ├─{ModemManager}(390)
│ └─{ModemManager}(398)
├─NetworkManager(304)─┬─{NetworkManager}(347)
│ ├─{NetworkManager}(354)
│ └─{NetworkManager}(357)
├─accounts-daemon(301)─┬─{accounts-daemon}(305)
│ ├─{accounts-daemon}(307)
│ └─{accounts-daemon}(352)
├─agetty(438)
├─atd(430)
├─avahi-daemon(302)───avahi-daemon(343)
├─cron(424)
├─dbus-daemon(303)
├─gdm3(440)─┬─{gdm3}(441)
│ ├─{gdm3}(442)
│ └─{gdm3}(449)
├─init-systemd(Ub(2)─┬─SessionLeader(661)───Relay(663)(662)───bash(663)───pstree(916)
│ ├─init(8)─┬─{init}(9)
│ │ └─{init}(913)
│ ├─login(664)───bash(853)
│ └─{init-systemd(Ub}(10)
├─networkd-dispat(310)
├─nm-dispatcher(413)─┬─{nm-dispatcher}(416)
│ └─{nm-dispatcher}(417)
├─polkitd(311)─┬─{polkitd}(323)
│ ├─{polkitd}(324)
│ └─{polkitd}(351)
├─rsyslogd(313)─┬─{rsyslogd}(344)
│ ├─{rsyslogd}(345)
│ └─{rsyslogd}(346)
├─rtkit-daemon(465)─┬─{rtkit-daemon}(468)
│ └─{rtkit-daemon}(469)
├─snapd(315)─┬─{snapd}(529)
│ ├─{snapd}(530)
│ ├─{snapd}(531)
│ ├─{snapd}(532)
│ ├─{snapd}(533)
│ ├─{snapd}(562)
│ ├─{snapd}(563)
│ ├─{snapd}(564)
│ ├─{snapd}(566)
│ ├─{snapd}(577)
│ ├─{snapd}(578)
│ ├─{snapd}(579)
│ ├─{snapd}(599)
│ ├─{snapd}(911)
│ └─{snapd}(912)
├─snapfuse(282)
├─snapfuse(283)
├─snapfuse(286)
├─snapfuse(289)
├─snapfuse(290)
├─switcheroo-cont(322)─┬─{switcheroo-cont}(349)
│ ├─{switcheroo-cont}(350)
│ └─{switcheroo-cont}(353)
├─systemd(451)─┬─(sd-pam)(452)
│ └─dbus-daemon(460)
├─systemd(845)───(sd-pam)(846)
├─systemd-hostnam(368)
├─systemd-journal(56)
├─systemd-logind(325)
├─systemd-network(83)
├─systemd-resolve(298)
├─systemd-timedat(603)
├─systemd-udevd(77)─┬─systemd-udevd(914)
│ └─systemd-udevd(915)
├─udisksd(327)─┬─{udisksd}(366)
│ ├─{udisksd}(371)
│ ├─{udisksd}(373)
│ ├─{udisksd}(379)
│ └─{udisksd}(418)
├─unattended-upgr(392)───{unattended-upgr}(448)
└─wpa_supplicant(328)
在这一输出中,systemd是第一个进程,而对应23.04的简洁进程树的部分,实际上是init-systemd(Ub(2)的子树。跨了三个大版本之后,两者的形式差别变得比较大。不过可能是ubuntu23.04的pstree输出中刻意隐去了用户无法触及的部分,以减小阅读输出的心智负担。
1.7 文件相关
1.7.1 文件权限
形如crw-rw-rw-的文件权限表示:
- 文件类型:
- d c b 含义 普通文件
(文本/数据)
目录 字符设备
(键盘/鼠标)
块设备
(硬盘、USB等)
l p s 含义 符号链接
(指向其他文件)
管道 套接字 - 文件所有者权限 / 文件所有者所在组权限 / 其他用户权限。
1.7.2 总体文件结构
一个典型的Linux根目录结构(参考文献1的基础4中缺少了一部分,我参考ubuntu20.04和23.04补了一些):
- bin:可执行二进制(binary)文件。
- boot:Linux内核镜像、initramfs和其他启动文件,包括grub等(但我的/boot是空的,可能因为是虚拟机的缘故)
- dev:设备(device)文件,类型比较复杂,单开一节。
- etc:配置文件(不知道为什么叫et cetera),一大堆杂七杂八,单开一节。
- home:用户主目录。
- init:一个可执行文件,用作容器或虚拟机入口(我用的是虚拟机,所以会有这个东西)
- initrd:存放启动时挂载的initrd.img,2010年左右就退环境了,取而代之的是initramfs
- initramfs:内核启动时使用的临时根文件系统,为内核提供基本的驱动和功能。其中的脚本会完成初始化工作。
- lib:存放库文件,用-lxxx就可以链接。
- lib32:32位库文件(64位系统可以运行32位程序,32位程序编译就要调lib32的库)
- lib64:64位库文件
- libx32:支持x32 ABI模式(64位地址空间 & 32位指令集)的64位库文件。据说在特定场景下性能比纯64位好。
- lost+found:存放fsck放置的零散文件。任何被fsck检查到有问题的文件都会被移进这里。
- fsck:file system check,用于检查和修复文件系统,启动时自动运行。
- media:自动挂载的设备都会挂到这里,开放权限,方便读取。
- mnt:临时挂载点(mount),需要修复根文件系统时,可以把系统挂载到/mnt,在不影响系统运行的情况下进行操作。
- opt:可选文件和程序,一般是第三方软件安装位置。
- proc:进程,通过进程号进行识别。然而里面不止有进程文件,还有一些杂七杂八的文件,在翻阅鸟哥的Linux教材时似乎看到过。单开一节分析一下。
- root:root的主目录。
- run:存放运行时文件,如套接字、PID、锁等,基于虚拟文件系统tmpfs。
- sbin:存放系统级二进制文件,而bin里是用户级的。普通用户运行sbin里的程序需要sudo。
- snap:snap包安装目录,此处只读。
- srv:存放本地服务相关文件。
- sys:存放系统硬件相关文件。
- tmp:存放临时文件,所有用户对其都有读写权。
- usr:存放与系统用户有关的文件,里面自己有一套bin、sbin、lib,与根目录不同的是还有include、src、local、libexec和share。
- include:C/C++头文件。
- local:用户自行安装范围区域。
- share:使用手册等共享数据。每个软件似乎都在里面放了一些对应的公开文件,比如eigen3放了一堆cmake。
- libexec:系统级辅助程序和库(用户一般不用)。
- src:内核源代码之类的东西。
- var:存放可变数据,比如系统日志、数据库和缓存文件。
- lock->/run/lock:放锁文件(设备锁、进程锁、程序锁)。
- crash:转储文件(dump file),内核崩溃时会把内存中关键数据保存到此,以供分析。
- lib:各种应用程序的状态信息、配置信息,以及应用程序数据文件(比如数据库的数据文件)。
- local:本地自定义数据,管理员自行维护,即使升级系统也不会受到影响。便于备份和恢复。
- log:各种日志。
- mail:应该没有什么人用了吧?
- opt:对应/opt中软件的配置、缓存、日志数据。
- run->/run:老程序把东西放在/var/run,新程序都放在/run
- snap:存放snap数据和配置文件。
- snap包支持多版本共存,所以安装新版不会卸载旧版。
- spool:各种队列,比如邮件、打印、cron任务队列。
- cron任务:自动化运行命令和脚本,用crontab来配置。
1.7.2.1 关于“挂载”
挂载这个东西非常玄学,单开一小节总结一下。
挂载的主体是一个文件系统,或者一个存储设备(除了U盘这种自带一个文件系统的,也有字符设备这种黑盒交互的东西)。
挂载主要是方便用户访问——虽然一般来说可以走/dev直接和没挂载的设备交互,但是很多设备的访问要拿管理权限,而且走/dev没法进入设备自身的文件系统。而镜像文件也必须挂载才能正常访问。
参考https://www.cnblogs.com/cangqinglang/p/12170828.html得知,挂载会让目录下原有文件隐藏,所以最好挂新建的空文件夹。
而挂载到一个位置,实际上是创建了一个独立的文件系统视图,一切操作都不会影响到其本体,于是可以实现将根文件系统挂载到/mnt进行修复而不影响系统运行的操作。
挂载后进行的修改,基本都会在卸载之后影响到本体。不过有几种特殊情况:
- 临时文件系统一卸载就会直接消失,所以修改也就不会保留。
- 修改文件系统元数据,如创建/删除文件或修改权限,可能会丢失。
- 非正常卸载。
当然,这些都是gpt说的。我要进行一些实验验证。
1.7.2.2 挂载实验
创建两个文件夹mount_test和test_mnt,尝试把mount_test挂载到test_mnt,报错说mount_test不是块设备。然而根文件系统显然也不是一个块设备。疑似要将根文件系统打包成镜像进行修改。那么所谓独立文件系统视图岂不是多此一举。【待续】
1.7.3 设备文件
参考:各种搜索引擎和AI(主要是gpt,Kimi高峰期频繁掉线+在线回答比较慢)。
- autofs:与自动挂载服务的通信设备,可以通过这个设备控制autofs守护进程,以及检查当前状态等。
- block:装有指向块设备的符号链接的文件夹。
- bsg:块设备后端接口(block storage generic),允许用户程序直接发送SCSI命令到块设备,可以绕过文件系统直接与块设备交互。
- btrfs-control:btrfs文件系统的控制设备,可以通过它管理btrfs系统。
- bus:装有总线控制设备文件的文件夹。
- console:向用户空间公开的内核控制台,可以打印错误和诊断信息。能不能用于控制内核?
- cpu_dma_latency:DMA延迟控制设备,可以获取当前DMA延迟和设置新的延迟目标值。
- cuse:用户空间字符设备(character device in user space),允许用户态程序自定义字符设备驱动。用户程序可以在其上打开一个文件描述符,并通过ioctl向内核注册一个自定义的字符设备驱动。内核会创建一个/dev/xxx供用户访问,并将所有对这个设备的访问转发给用户程序。
- 所谓“打开一个文件描述符”,就是直接open("/dev/cuse", O_RDWR)。
- dri:直接渲染接口(direct rendering interface),允许应用程序直接访问图形硬件加速功能的接口,包含文件
- card*:显卡设备
- renderD*:3D渲染设备
- fxg:显存(Framebuffer X Graphics)访问接口,允许直接操作显存,并进行图形操作(包括绘制等),嵌入式常用。
- fd -> /proc/self/fd:指向装有所有文件描述符的文件夹/proc/self/fd,于是访问/dev/fd/n等同于访问/proc/self/fd/n。这个self是进程号。
- full:一个永远写满的设备,写会返回ENOSPC,读会返回EOF,用于测试磁盘不足的处理机制。
- fuse:用户空间文件系统(filesystem in user space)的设备节点。通过这个节点可以在用户态使用ls、cat、grep、重定向等标准文件操作。
- hvc*:Hyper-V虚拟控制台设备。
- hd*:IDE(Integrated Drive Electronics)硬盘设备,很老。
- kmsg:读取内核日志信息。
- loop-control:管理循环设备,可以向其发送ioctl命令。
- loop*:伪设备,使得文件可以如同块设备一样被访问。可以用losetup为镜像文件分配loop设备,然后挂载loop设备实现对镜像文件的访问。
- mapper:装有由设备映射器创建的虚拟块设备文件的文件夹。
- mem:物理内存设备,仅允许root访问。
- net:网络设备文件夹,包含
- tun:虚拟网络接口,可以在用户态实现网络。
- udp:非标准socket API,跑得更快但更复杂。
- raw:原始套接字设备,允许应用程序直接访问数据链路层。
- packet:数据链路层套接字设备,可以收发数据帧(最低层)。
- null:黑洞设备,输入的一切都丢弃。
- nvram:非易失性RAM设备,结合了SRAM和DRAM的优点,且不受断电影响。
- ppp:Point-to-Point Protocol(数据链路层协议)接口,用来控制PPP连接。实现拨号上网,嵌入式PPP连接等。
- ptmx:pty伪终端的master,开fd后调grantpt()开权限,再调unlockpt()解锁从端,再调ptsname()获取从端名称,然后用read/write进行交互。
- ptp0:Precision Time Protocol接口,可以获取和设置精确时间,以及控制时间同步。联网同步时间。
- pts:里面装了一个ptmx(伪终端slave端的入口,用于获取一个pts),以及所有的pty slave。
- ram*:虚拟内存设备,可以用来临时存储和创建临时文件系统(如initramfs)。
- initramfs:内核启动时使用的临时根文件系统,为内核提供基本的驱动和功能。
- random:生成高熵随机数,若熵池耗尽则会阻塞等待熵增。
- rtc0:实时时钟接口,可以读取和设置时钟。不联网,只是内部同步时间。
- sda/b/c:SCSI/SATA硬盘设备。
- SCSI(small computer system interface):并行接口,最高可12Gbps,支持最多15个设备挂统一总线,一般服务器用。
- SATA(serial advanced technology attachment):串行接口,最高6Gbps,一个接口只能连一个设备,PC用。
- sg*:SCSI Generic设备。
- shm:共享内存文件系统,自动挂载,用于多进程共享内存,但断电丢失
- stderr -> /proc/self/fd/2 & stdin -> /proc/self/fd/0 & stdout -> /proc/self/fd/1:每个进程对应三个流。
- tty:正在使用的终端设备,进程调用会得到与当前进程相关联的终端设备。一切读写都会被重定向到真正的终端设备。
- 实验:echo "hello" > /dev/tty,终端会打印hello。
- tty0~63:文本模式终端。
- ttyS0~S31:串行终端。
- ttyUSB0~USB31:USB串行终端。
- ttyACM*(Abstract Control Model):遵循ACM协议的USB串行终端。
- urandom:不会因为熵池耗尽而停止输出的/dev/random
- vcs:访问当前活动的虚拟控制台屏幕缓冲区
- vcs1:编号为1的vcs
- vcsa:提供更多与屏幕布局和属性相关信息(也是当前)
- vcsa1:编号为1的vcsa
- vcsu:高分辨率
- vcsu1:编号为1的vcsu
- vfio:访问虚拟IO子系统,允许用户程序直接访问PCI设备。
- PCI(Peripheral Component Interconnect):总线上的外围设备,如显卡、网卡等。
- vhost-net:访问vhost-net子系统,用于优化网络虚拟化性能。利用内核的vhost子系统,将网络操作从内核空间搬到用户空间。
- vport0p*:访问Open vSwitch虚拟交换机端口的设备,每个端口对应一个设备,广泛用于软件定义网络(SDN)场景,可以在内核中提供灵活的网络功能。
- vsock:特殊套接字,允许虚拟机和宿主机直接通信,无需经过网络堆栈。
- 使用:socket(AF_VSOCK, SOCK_STREAM, 0);
- 网络堆栈:即五层结构,而vsock用的是DMA。
- zero:返回无限的0字节流。
1.7.4 配置文件
没有设备文件那么复杂的分类,大概讲一讲用途。
- systemd:系统和服务管理配置
- init.d:传统的系统初始化脚本
- NetwrokManager:高级网络管理配置
- resolv.conf:DNS配置文件
- netplan:基础网络配置管理(系统自带)
- udev:动态设备管理
- modprobe.d:内核模块配置
- fstab:文件系统挂载配置
- pam.d:可插入认证模块配置
- sudoers:sudo权限配置
- shadow:加密的密码文件
- rsyslog.conf:系统日志配置
- cron.d:定时任务配置
- sensors.d:硬件监控配置
- apt:apt包管理器
- dpkg:Debian包管理器
- passwd:用户账号信息
- group:用户组信息
- profile.d:用户环境配置
- dbus-1:消息总线服务配置
- X11:X Windows系统配置
- fonts:字体配置
1.7.5 进程文件
除了以进程id命名的文件夹之外,还有一些其他的文件。
- cmdline:当前系统启动时的命令行参数
- self:当前进程的/proc目录入口,是一个符号链接
- 关于Linux如何让每个进程看到不一样的符号链接?【待续】
- cpuinfo:CPU信息
- meminfo:内存信息
- vmstat:虚拟内存信息
- zoneinfo:系统内存管理区域信息(页面统计等)
- devices:已注册设备驱动信息
- dma:正在使用的dma通道信息
- ioports:IO端口信息
- interrupts:系统中断使用信息
- filesystems:系统支持的文件系统类型
- mounts:系统当前挂载情况
- partitions:系统所有已识别分区
- net:网络设备、协议栈、路由表等信息
- anycast6:管理ipv6 anycast路由
- icmp*:控制ICMP协议
- ip_vs*:管理IP虚拟服务器(IPVS)
- netlink:与内核网络通信
- router/rt_stats/rt_cache:路由表
- tcp*/udp*:控制TCP/UDP协议
- arp*:管理ARP表
- if_inet6:显示ipv6接口信息
- igmp6:控制IGMP
- ipconfig:配置ipv4/6接口
- ipv6_route:ipv6路由表
- mcfilter6:管理ipv6多播组过滤
- netfilter:管理内核网络过滤
- pnp:管理即插即用设备
- pppoe:管理PPPoE连接
- protocols:内核支持的网络协议
- raw*:管理raw套接字(可以直接访问网络层协议,如ICMP和IGMP)
- sctp:管理SCTP(流传输控制协议)
- unix:管理Unix域套接字(基于文件系统的进程间通信机制)
- psched:配置和监控内核数据包调度器
- snmp*:这是管理SNMP(简单网络管理协议)相关统计信息
- softnet_stat:显示softirq(内核处理网络中断的一种机制)处理程序相关的网络统计信息
- stat:显示网络统计数据?
- ptype:管理数据包分类器
- vlan:管理vlan接口
- sys:内核参数访问接口
- abi:应用程序二进制接口相关配置
- sunrpc:与SunRPC协议相关配置
- SunRPC:Sun Remote Procedure Call(Sun远程过程调用),分布式计算协议,可以实现客户端像调用本地函数一样调用远程过程。有一些Linux的NFS(Network File System)依赖于它。
- uptime:系统启动时间和平均负载
1.7.6 文件系统
分为磁盘文件系统(本地访问)、网络文件系统(远程访问)和虚拟文件系统(不驻留磁盘,即只存在于内存中)。
文件系统主要类别(来自gpt):
- ext4:Linux最常用,各种性能都比较好,带日志。
- XFS:性能很强,适应高吞吐量场景,估计是服务器集群用的。
- btrfs:B树文件系统,比较新,各种操作,适合备份,比较灵活。
- ZFS:比较先进,没听说过。
- FAT:很老,可以跨系统操作(Linux和Windows都支持),但大小受限,不支持高级功能。
- NTFS:New Technology File System(名字很nb),在Linux上需要第三方包支持。
交换分区(swapping,操作系统教材上一般叫“对换空间”),最小必须等于内存,但不等于也无所谓(我的64G内存挂的32G交换分区也能用)。之前搞树莓派的时候参考过
参考文献6:Linux 修改 Swap 分区大小_linux可以改变swap分区大小吗-CSDN博客
此处关系不大,不多赘述。
1.7.7 文件操作
file <filename> # 判断类型
mkdir <dirname> # 创建文件夹
mkdir -p <dirname>/<subdirname>/... # 嵌套创建文件夹
rmdir <dirname> # 删除文件夹
rm -r <dirname> # 删除文件夹
rmdir -p <dirname>/<subdirname>/... # 嵌套删除文件夹
链接分为:
- 硬链接(默认):直接指向文件物理编号(inode),不能跨越文件系统。
- 软链接:指向路径(通常使用绝对路径),所以挂载一下就可以跨。删掉文件新建一个同名文件,软链接依然有效。
ln [-s] <target> <link_name> # 创建一个指向target的link
压缩文件方法:
- gzip:压缩一个或多个文件,每个文件打一个.gz包。很多源文件都是打包成.tar.gz,因为一个.gz只能装一个文件,名字是被打包文件本身。
gzip <file1> <file2> ... # 分别打包为file1.gz, file2.gz, ...,替换原本的文件 gunzip <file1.gz> <file2.gz> ... # 解压多个文件,用filen替换filen.gz
- bzip2:比gzip压缩率更高,支持多线程压缩和解压,但占用。用法跟gzip一样。
- zip:把一系列文件打包到一个.zip文件中,方便Windows和Linux跨平台交换文件。
zip <file.zip> <file1> <file2> ... # 把file1, file2, ...压缩到file.zip中 unzip <file.zip> # 解压file.zip
- tar:与zip功能相似,但与其说是压缩,不如叫做打包或者归档,基本不怎么压缩。
参数 -t -x -u -c 含义 显示内容 拆包 更新 创建 参数 -v -f -j -z 含义 显示过程 指定名称 +bzip2压缩 +gzip压缩 tar -cf <file.tar> <file1> <file2> ... # 把一系列文件归档到file.tar # 其中-c表示创建归档文件,-f表示指定归档文件名 tar -tf <file.tar> # 显示归档文件内容 tar -xf <file.tar> # 拆开归档文件 tar -xzf <file.tar.gz> -C <dir> # 拆.tar.gz文件,并解压到指定目录 tar -czf xxx.tar.gz --listed-incremental=yyy.snar <file1> <file2> ... # 若没有快照文件yyy.snar,则生成;若有,则通过读取同名快照文件进行增量归档 tar -xzf xxx.tar.gz --listed-incremental=yyy.snar # 先拆包xxx.tar.gz,再根据yyy.snar把增量的部分也拆出来
其中,zip和tar的区别在于:
保留权限、所有者等元数据 | 增量备份 | 压缩率 | 内置加密 | 命令简单 | |
zip | × | × | 高 | √ | × |
tar | √ | √ | 低 | × | √ |
1.8 网络相关
网络配置要做的:修改网络配置文件。
IP地址要么手动设置,要么用DHCP(Dynamic Host Configuration Protocol)服务获取。
1.8.1 网络工具
- ifconfig:查看网络信息。
- ping <ip>:检查是否能连接到对应主机。
- ssh <user>@<ip>:ssh远程登录。
- nmtui:可视化配wifi,嵌入式开发板用得多。
- nslookup <域名>:查看DNS服务器地址。看不懂输出,查一下。【待续】
1.8.2 网络信息
我常使用ifconfig查看ip地址之类的信息,但对于其他显示的信息尚无清晰概念。
这是wsl2 ubuntu 20.04上的输出:
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.25.105.86 netmask 255.255.240.0 broadcast 172.25.111.255
inet6 fe80::215:5dff:febb:60ff prefixlen 64 scopeid 0x20<link>
ether 00:15:5d:bb:60:ff txqueuelen 1000 (Ethernet)
RX packets 3734 bytes 1214421 (1.2 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 248 bytes 31532 (31.5 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 9 bytes 1797 (1.7 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 9 bytes 1797 (1.7 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
根据gpt注释一下(此处需要一定的计网基础):
eth0【接口类型】: flags=4163<UP【处于激活状态】,BROADCAST【支持广播】,RUNNING【正在运行】,MULTICAST【支持多播】> mtu 1500【最大传输单元:1500字节】
inet 172.25.105.86【ipv4地址】 netmask 255.255.240.0【子网掩码】 broadcast 172.25.111.255【广播地址】
inet6 fe80::215:5dff:febb:60ff【ipv6地址】 prefixlen 64【前缀长度】 scopeid 0x20<link>【作用域为link层】
ether 00:15:5d:bb:60:ff【以太网MAC地址】 txqueuelen 1000【发送队列长度:1000】 (Ethernet)
RX packets 3734【收到数据包:3734个】 bytes 1214421 (1.2 MB)【总大小:1.2MB】
RX errors 0【无错误】 dropped 0【无丢包】 overruns 0【无溢出丢包】 frame 0【无帧错误】
TX packets 248【发送数据包:248个】 bytes 31532 (31.5 KB)
TX errors 0 dropped 0 overruns 0 carrier 0【未检测到载波信号】 collisions 0【无数据帧碰撞】
其中有几个不是很熟悉的概念(ipv6相关概念单独讲):
- 载波信号:建立物理层连接所需的信号。
- 数据帧碰撞:多个设备同时试图向在一个共享的传输介质(线缆或是电磁波)发送数据帧而导致的冲突。
- 以太网使用CSMA/CD(载波监听多路访问/碰撞检测)协议管理总线访问,但无法规避所有碰撞情况。
其他的(网络接口、网络协议、多播等)后面单独写一篇讲,这一篇已经太长了。