在Linux系统中,系统自动挂载了以下挂载点:
/: xfs文件系统,根文件系统, 所有其他文件系统的挂载点。
/sys: sysfs文件系统,提供内核对象的信息和接口。
/proc: proc文件系统,提供进程和系统信息。
/dev: devtmpfs文件系统,设备文件的挂载点,包含特殊文件或设备节点。
/run: tmpfs文件系统,临时文件系统,存储系统运行时数据。
/tmp: tmpfs文件系统,临时文件的存储位置。
/boot: ext4文件系统,包含启动加载器和启动时需要的文件。
/dev/shm: tmpfs文件系统,用于共享内存的临时文件系统。
/dev/pts: devpts文件系统,伪终端设备的挂载点。
/dev/mqueue: mqueue文件系统,POSIX消息队列的挂载点。
/dev/hugepages: hugetlbfs文件系统,大页内存的挂载点。
/sys/kernel/security: securityfs文件系统,安全文件系统,提供安全模块信息。
/sys/kernel/debug: debugfs文件系统,调试文件系统,提供内核调试信息。
/sys/kernel/config: configfs文件系统,内核配置文件系统,用于动态内核配置。
/sys/fs/cgroup: tmpfs文件系统,控制组(cgroups)的挂载点,用于资源管理。
/sys/fs/pstore: pstore文件系统,持久存储文件系统,用于存储崩溃信息。
/sys/fs/bpf: bpf文件系统,BPF(Berkeley Packet Filter)虚拟文件系统。
/sys/fs/cgroup/net_cls,net_prio: cgroup文件系统,控制组网络分类和优先级管理。
/sys/fs/cgroup/freezer: cgroup文件系统,控制组冻结和解冻任务。
/sys/fs/cgroup/memory: cgroup文件系统,控制组内存资源管理。
/sys/fs/cgroup/rdma: cgroup文件系统,控制组远程直接内存访问管理。
/sys/fs/cgroup/blkio: cgroup文件系统,控制组块设备I/O管理。
/sys/fs/cgroup/hugetlb: cgroup文件系统,控制组大页内存管理。
/sys/fs/cgroup/pids: cgroup文件系统,控制组进程号管理。
/sys/fs/cgroup/perf_event: cgroup文件系统,控制组性能事件监控。
/sys/fs/cgroup/cpu,cpuacct: cgroup文件系统,控制组CPU资源管理和计费。
/sys/fs/cgroup/devices: cgroup文件系统,控制组设备访问管理。
/sys/fs/cgroup/cpuset: cgroup文件系统,控制组CPU和内存节点分配。
/var/log/rtlog: tmpfs文件系统,可能是某些特定服务的日志挂载点。
他们的手动挂载方式如下:
# 根文件系统通常在启动时已经挂载,这里是重新挂载为只读的示例
在systemd存在的环境下,根文件系统一般被挂载为共享模式,在docker启动时一般会重新挂载为私有模式:
mount --make-rprivate /
# mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL)
# mount("","/", NULL, MS_PRIVATE,"")
# 挂载boot分区,这里假设分区为/dev/sda1,文件系统类型为ext4
mount -t ext4 /dev/sda1 /boot
# mount("/dev/sda1", "/boot", "ext4", 0, NULL)
# 挂载sysfs文件系统到/sys
mount -t sysfs sysfs /sys
# mount("sysfs", "/sys", "sysfs", 0, NULL)
# 挂载proc文件系统到/proc
mount -t proc proc /proc
# mount("proc", "/proc", "proc", 0, NULL)
# 挂载devtmpfs文件系统到/dev
mount -t devtmpfs devtmpfs /dev
# mount("devtmpfs", "/dev", "devtmpfs", MS_NOSUID|MS_STRICTATIME, NULL)
# 挂载tmpfs文件系统到/run
mount -t tmpfs tmpfs /run
# mount("tmpfs", "/run", "tmpfs", 0, NULL)
# 挂载tmpfs文件系统到/tmp
mount -t tmpfs tmpfs /tmp
# mount("tmpfs", "/tmp", "tmpfs", 0, NULL)
# 挂载tmpfs文件系统到/dev/shm
mount -t tmpfs tmpfs /dev/shm
# mount("tmpfs", "/dev/shm", "tmpfs", 0, NULL)
# 挂载devpts文件系统到/dev/pts
mount -t devpts devpts /dev/pts
# mount("devpts", "/dev/pts", "devpts", 0, NULL)
# 挂载securityfs文件系统到/sys/kernel/security
mount -t securityfs securityfs /sys/kernel/security
# mount("securityfs", "/sys/kernel/security", "securityfs", 0, NULL)
# 挂载configfs文件系统到/sys/kernel/config
mount -t configfs configfs /sys/kernel/config
# 挂载debugfs文件系统到/sys/kernel/debug
mount -t debugfs debugfs /sys/kernel/debug
# 挂载mqueue (POSIX消息队列) 文件系统到/dev/mqueue
mount -t mqueue mqueue /dev/mqueue
# 挂载hugetlbfs文件系统到/dev/hugepages
mount -t hugetlbfs hugetlbfs /dev/hugepages
# 挂载pstore文件系统到/sys/fs/pstore
mount -t pstore pstore /sys/fs/pstore
# 挂载bpf文件系统到/sys/fs/bpf
mount -t bpf bpf /sys/fs/bpf
对于以上虚机文件系统,不存在相对应的设备,那么挂载源可以是相应的文件系统名称,也可以是none字符串,但是出于一致性或者可读性考虑,一般用文件系统名称。
在Linux系统中,cgroup子系统是用来管理和限制进程组使用的资源。每个cgroup子系统都关注于特定类型的资源管理。以下是对应的cgroup子系统及其挂载方式的列表:
# net_cls,net_prio 子系统
mount -t cgroup -o net_cls,net_prio cgroup /sys/fs/cgroup/net_cls,net_prio
# freezer 子系统
mount -t cgroup -o freezer cgroup /sys/fs/cgroup/freezer
# memory 子系统
mount -t cgroup -o memory cgroup /sys/fs/cgroup/memory
# rdma 子系统
mount -t cgroup -o rdma cgroup /sys/fs/cgroup/rdma
# blkio 子系统
mount -t cgroup -o blkio cgroup /sys/fs/cgroup/blkio
# hugetlb 子系统
mount -t cgroup -o hugetlb cgroup /sys/fs/cgroup/hugetlb
# pids 子系统
mount -t cgroup -o pids cgroup /sys/fs/cgroup/pids
# perf_event 子系统
mount -t cgroup -o perf_event cgroup /sys/fs/cgroup/perf_event
# cpu,cpuacct 子系统
mount -t cgroup -o cpu,cpuacct cgroup /sys/fs/cgroup/cpu,cpuacct
# devices 子系统
mount -t cgroup -o devices cgroup /sys/fs/cgroup/devices
# cpuset 子系统
mount -t cgroup -o cpuset cgroup /sys/fs/cgroup/cpuset
# cgroup 根目录,通常挂载为cgroup2(如果使用的是cgroup v2)
mount -t cgroup2 none /sys/fs/cgroup
# mount("none", "/sys/fs/cgroup", "cgroup2", 0, NULL)
# 挂载cgroup文件系统到/sys/fs/cgroup (如果使用的是cgroup v1)
mount -t cgroup cgroup /sys/fs/cgroup
# systemd 子系统,特别用于systemd管理的cgroup
mount -t cgroup -o none,name=systemd cgroup /sys/fs/cgroup/systemd
以下是cgroup v1的C语言挂载方式:
#define _GNU_SOURCE
#include <sys/mount.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
int mount_cgroup_subsystem(const char *subsystem, const char *target) {
// 创建挂载点目录
mkdir(target, 0755);
// 挂载cgroup子系统
if (mount("cgroup", target, "cgroup", 0, subsystem)) {
fprintf(stderr, "Mount failed for %s: %s\n", subsystem, strerror(errno));
return -1;
}
printf("Mounted cgroup subsystem %s to %s\n", subsystem, target);
return 0;
}
int main() {
// 挂载各个cgroup子系统
mount_cgroup_subsystem("net_cls,net_prio", "/sys/fs/cgroup/net_cls,net_prio");
mount_cgroup_subsystem("freezer", "/sys/fs/cgroup/freezer");
mount_cgroup_subsystem("memory", "/sys/fs/cgroup/memory");
mount_cgroup_subsystem("rdma", "/sys/fs/cgroup/rdma");
mount_cgroup_subsystem("blkio", "/sys/fs/cgroup/blkio");
mount_cgroup_subsystem("hugetlb", "/sys/fs/cgroup/hugetlb");
mount_cgroup_subsystem("pids", "/sys/fs/cgroup/pids");
mount_cgroup_subsystem("perf_event", "/sys/fs/cgroup/perf_event");
mount_cgroup_subsystem("cpu,cpuacct", "/sys/fs/cgroup/cpu,cpuacct");
mount_cgroup_subsystem("devices", "/sys/fs/cgroup/devices");
mount_cgroup_subsystem("cpuset", "/sys/fs/cgroup/cpuset");
// 挂载cgroup v2文件系统到/sys/fs/cgroup
if (mount("none", "/sys/fs/cgroup", "cgroup2", 0, NULL)) {
fprintf(stderr, "Mount failed for cgroup2: %s\n", strerror(errno));
return -1;
}
// 挂载systemd专用的cgroup子系统
mount_cgroup_subsystem("none,name=systemd", "/sys/fs/cgroup/systemd");
return 0;
}
请注意,上述命令需要以root权限执行。此外,实际的挂载参数可能会根据你的系统和cgroup版本(v1或v2)有所不同。在cgroup v2中,所有的资源控制都通过单一的层级来管理,而不是像cgroup v1那样有多个层级。
在现代Linux系统中,这些挂载通常是由系统的初始化过程(如systemd)自动完成的,而不需要手动执行。如果你的系统已经使用了systemd,它可能已经为你配置了cgroup,并且可能使用的是cgroup v2。在这种情况下,你应该遵循系统的配置而不是手动挂载。
判断cgroup v1还是v2,执行以下命令来检查/sys/fs/cgroup目录的挂载情况:
mount | grep cgroup
如果输出显示type cgroup2,则表示系统使用的是cgroup v2。例如:
none on /sys/fs/cgroup type cgroup2 (rw,nosuid,nodev,noexec,relatime)
如果输出显示多个cgroup挂载点,每个都有不同的子系统, 如:
type cgroup (rw,nosuid,nodev,noexec,relatime,cpuacct,cpu
则表示系统使用的是cgroup v1。
在docker容器中,挂载文件系统一般如下:
mount -t overlay overlay -o lowerdir=lower1:lower2,upperdir=upper,workdir=work merged
#mount("overlay","merged","overlay",0,"upperdir=upper,lowerdir=lower1:lower2,workdir=work")
上面命令中:
lowerdir:表示镜像层,只读
upper: 表示容器层,可读可写
workdir: 表示文件系统的工作目录,用以文件系统合并文件时作为临时空间
merged: 表示挂载点
注:workdir必须是一个空目录,并且和upperdir是mount在同一个文件系统下, 而lower不是必须的;如果没有upperdir, merged是只读的;lowerdir中越右边的层级越低
如果需要在/etc/fstab中添加overlay的自动挂载,命令如下:
overlay /merged overlay noauto,x-systemd.automount,lowerdir=/lower1:/lower2:/lower3,upperdir=/upper,workdir=/work 0 0
如果是aufs文件系统,命令则是如下:
mount -t aufs -o dirs=upperdir:lowerdir1:lowerdir2 none merged
其中:
dirs 就是需要挂载的目录,只有第一个是可读可写的,其他的都是只读的
一般容器中还会挂载以下内容:
mount("conf/hosts", "rootfs/etc/hosts", "none", MS_BIND, NULL)
mount("conf/hostname", "rootfs/etc/hostname", "none", MS_BIND, NULL)
mount("conf/resolv.conf", "rootfs/etc/resolv.conf", "none", MS_BIND, NULL)
附mount函数option参数含义:
MS_BIND:建立绑定挂载,如果指定了该标志,那么 mount()会忽略fstype、 data 参数,以及 mountflags 中除 MS_REC 之外的标志。
MS_DIRSYNC:同步更新路径,该标志的效果类似于 open()的 O_SYNC 标志,但只针对路径。
MS_MANDLOCK:允许对该文件系统中的文件强行锁定记录;
MS_MOVE:将由 source 指定的现有挂载点移到由 target 指定的新位置,令整个动作为一原子操作,不可分割;一旦使用了这一标志,那么 mount()将忽略 fstype、 data 参数 以及 mountflags 中的其他标志。
MS_NOATIME:不更新最后访问时间(使用该标志意在消除额外的磁盘访问,避免每次访问时都更新文件i节点,可提高性能)
MS_NODEV:不允许访问此文件系统上的块设备和字符设备。设计这一特性的目的是为了保障系统安全,规避如下情况:假设用户插入了可移动磁盘,而磁盘中又包含了可随意访问系统的设备 专有文件。
MS_NODIRATIME:不更新目录的最后访问时间。
MS_NOEXEC:不允许在此文件系统上执行程序或脚本,该标志用于文件系统包含非 Linux 可执行文件的场景。
MS_NOSUID:禁用set-user-ID和set-group-ID,这属于安全特性,意在防止用户从 可移动磁盘上运行 set-user-ID 和 set-group-ID 程序。
MS_RDONLY:以只读方式挂载文件系统,在此文件系统上不能创建和修改文件;
MS_REC:该标志与其他标志(比如, MS_BIND)结合使用,以递归方式将挂载动作施之于子树下的所有挂载。
MS_RELATIME :只有当文件最后访问时间戳的当前值(上次更新时间)小于或等于最后一次修改或状态更新的时间戳时,才对其进行更新;
MS_REMOUNT :针对已经挂载的文件系统,改变其mountflag和data使用该标志时, source 和 target 参数应该与最初用于 mount()系统调用的参数相同,而对 fstype 参数则予以忽略。使用该标志可以避免对磁盘进行卸载和重新挂载,在某些场合中,这是不可能做到的。
MS_STRICTATIME:只要访问文件,就总是更新文件的最后访问时间戳;
MS_SYNCHRONOUS:对文件系统上的所有文件和目录保持同步更新;