嵌入式Linux学习笔记(一)

参考文献:【超全面】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源,即所获取的网上仓库的网址。

仓库分为四种:

  1. 核心 Main:官方维护的开源软件
  2. 公共 Universe:社区维护的开源软件
  3. 受限 Restricted:官方维护的非开源软件
  4. 多元化 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这些,都是从这里复制过来的。修改这里就可以统一配置所有新用户。

添加新用户过程:

  1. 编辑/etc/passwd和/etc/shadow两个文件,定义用户账号
  2. 设置初始密码
  3. 为用户创建主目录,用chown和chmod给新用户
  4. 将/etc/skel中的默认配置文件复制到用户的主目录中
  5. 邮件之类的配置,基本用不到

常用命令:

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%MEMVSZRSS
含义进程编号CPU占用内存占用虚存分配量内存实际使用量
TTYSTATSTARTTIMECOMMAND
含义控制台名称运行状态开始时间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状态字符含义分别为

DRSTXZ
含义IO运行休眠停止死亡僵尸
<NLsl+
含义优先级高优先级低有页锁在内存有子进程克隆进程后台

详细解释:

  1. D代表“无法中断的休眠”,大部分时候是IO,但并非全部。
  2. 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解释:

  1. init是由内核启动的第一个进程,是其他所有进程的祖先,负责管理其他进程的生命周期。
  2. SessionLeader是init负责管理用户会话(登录、操作之类)的子进程。根据pstree -p的结果可以看出,每个session对应的SessionLeader都是独立的进程。
  3. Relay(xxx)没讲明白,但根据pstree -p的结果可以看出,Relay括号里的是其所管理的bash终端的pid。第二个示例中,我运行pstree和htop的是两个bash终端。第三个示例中,似乎不会出现一个SessionLeader对应多个Relay的情况。
  4. 比较诡异的是这四个init,其中init(ubuntu-23.(1)是根进程,init(7)据说是init的子进程。
  5. 加了花括号{}的据说是轻量级进程或线程,所以剩下两个init可以看出关系,但不知道含义。

根据参考文献1的解释:

  1. 进程组:进程集合,有一个组长,其进程ID为进程组ID(大概是Relay)
  2. 会话:进程组集合,有一个组长,其进程ID为会话ID(即SessionLeader)
  3. 控制进程:与终端相连接的组长就是控制进程(也即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-的文件权限表示:

  1. 文件类型:
    -dcb
    含义

    普通文件

    (文本/数据)

    目录

    字符设备

    (键盘/鼠标)

    块设备

    (硬盘、USB等)

    lps
    含义

    符号链接

    (指向其他文件)

    管道套接字
  2. 文件所有者权限 / 文件所有者所在组权限 / 其他用户权限。

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进行修复而不影响系统运行的操作。

挂载后进行的修改,基本都会在卸载之后影响到本体。不过有几种特殊情况:

  1. 临时文件系统一卸载就会直接消失,所以修改也就不会保留。
  2. 修改文件系统元数据,如创建/删除文件或修改权限,可能会丢失。
  3. 非正常卸载。

当然,这些都是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):

  1. ext4:Linux最常用,各种性能都比较好,带日志。
  2. XFS:性能很强,适应高吞吐量场景,估计是服务器集群用的。
  3. btrfs:B树文件系统,比较新,各种操作,适合备份,比较灵活。
  4. ZFS:比较先进,没听说过。
  5. FAT:很老,可以跨系统操作(Linux和Windows都支持),但大小受限,不支持高级功能。
  6. 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>/... # 嵌套删除文件夹

链接分为:

  1. 硬链接(默认):直接指向文件物理编号(inode),不能跨越文件系统。
  2. 软链接:指向路径(通常使用绝对路径),所以挂载一下就可以跨。删掉文件新建一个同名文件,软链接依然有效。
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(载波监听多路访问/碰撞检测)协议管理总线访问,但无法规避所有碰撞情况。

其他的(网络接口、网络协议、多播等)后面单独写一篇讲,这一篇已经太长了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值