1、mount bind用法

mount命令的标准格式如下:

mount -t type -o options device dir
  • device: 要挂载的设备(必填)。有些文件系统不需要指定具体的设备,这里可以随便填一个字符串

  • dir: 挂载到哪个目录(必填)

  • type: 文件系统类型(可选)。大部分情况下都不用指定该参数,系统都会自动检测到设备上的文件系统类型

  • options: 挂载参数(可选)。
    options一般分为两类,一类是Linux VFS所提供的通用参数,就是每个文件系统都可以使用这类参数,详情请参考“FILESYSTEM-INDEPENDENT MOUNT OPTIONS”。另一类是每个文件系统自己支持的特有参数,这个需要参考每个文件系统的文档,如btrfs支持的参数可以在这里找到。

proc、tmpfs、sysfs、devpts等都是Linux内核映射到用户空间的虚拟文件系统,他们不和具体的物理设备关联,但他们具有普通文件系统的特征,应用层程序可以像访问普通文件系统一样来访问他们。

这里只是示例一下怎么挂载他们,不对他们具体的功能做详细介绍。

#将内核的proc文件系统挂载到/mnt,
#这样就可以在/mnt目录下看到系统当前运行的所有进程的信息,
#由于proc是内核虚拟的一个文件系统,并没有对应的设备,
#所以这里-t参数必须要指定,不然mount就不知道要挂载啥了。
#由于没有对应的源设备,这里none可以是任意字符串,
#取个有意义的名字就可以了,因为用mount命令查看挂载点信息时第一列显示的就是这个字符串。
u@lb:~$ sudo mount -t proc none /mnt

#在内存中创建一个64M的tmpfs文件系统,并挂载到/mnt下,
#这样所有写到/mnt目录下的文件都存储在内存中,速度非常快,
#不过要注意,由于数据存储在内存中,所以断电后数据会丢失掉
u@lb:~$ sudo mount -t tmpfs -o size=64m tmpfs /mnt

挂载 loop device

在Linux中,硬盘、光盘、软盘等都是常见的块设备,他们在Linux下的目录一般是/dev/hda1, /dev/cdrom, /dev/sda1,/dev/fd0这样的。而loop device是虚拟的块设备,主要目的是让用户可以像访问上述块设备那样访问一个文件。 loop device设备的路径一般是/dev/loop0, dev/loop1, ...等,具体的个数跟内核的配置有关,Ubuntu16.04下面默认是8个,如果8个都被占用了,那么就需要修改内核参数来增加loop device的个数。

#利用mkisofs构建一个用于测试的iso文件
u@lb:~$ mkdir -p iso/subdir01
u@lb:~$ mkisofs -o ./test.iso ./iso

#mount ISO 到目录 /mnt
u@lb:~$ sudo mount ./test.iso /mnt
mount: /dev/loop0 is write-protected, mounting read-only

#mount成功,能看到里面的文件夹
u@lb:~$ ls /mnt
subdir01

#通过losetup命令可以看到占用了loop0设备
u@lb:~$ losetup -a
/dev/loop0: []: (/home/dev/test.iso)

虚拟硬盘

loop device另一种常用的用法是虚拟一个硬盘,比如我想尝试下btrfs这个文件系统,但系统中目前的所有分区都已经用了,里面都是有用的数据,不想格式化他们,这时虚拟硬盘就有用武之地了,示例如下:

#因为btrfs对分区的大小有最小要求,所以利用dd命令创建一个128M的文件
u@lb:~$ dd if=/dev/zero bs=1M count=128 of=./vdisk.img

#在这个文件里面创建btrfs文件系统
#有些同学可能会想,硬盘一般不都是先分区再创建文件系统的吗?
#是的,分区是为了方便磁盘的管理,
#但对于文件系统来说,他一点都不关心分区的概念,你给他多大的空间,他就用多大的空间,
#当然这里也可以先用fdisk在vdisk.img中创建分区,然后再在分区上创建文件系统,
#只是这里的虚拟硬盘不需要用作其他的用途,为了方便,我就把整个硬盘全部给btrfs文件系统,
u@ubuntu:~$ mkfs.btrfs ./vdisk.img
#这里会输出一些信息,提示创建成功

#mount虚拟硬盘
u@lb:~$ sudo mount ./vdisk.img /mnt/

#在虚拟硬盘中创建文件成功
u@lb:~$ sudo touch /mnt/aaaaaa
u@lb:~$ ls /mnt/
aaaaaa

#加上刚才上面mount的iso文件,我们已经用了两个loop device了
u@lb:~$ losetup -a
/dev/loop0: []: (/home/dev/test.iso)
/dev/loop1: []: (/home/dev/vdisk.img)

挂载多个设备到一个文件夹

在上面的例子中,将test.iso和vdisk.img都mount到了/mnt目录下,这个在Linux下是支持的,默认会用后面的mount覆盖掉前面的mount,只有当umount后面的device后,原来的device才看的到。 看下面的例子:

#先umount上面的iso和vdisk.img
u@lb:~$ sudo umount ./test.iso
u@lb:~$ sudo umount ./vdisk.img

#在/mnt目录下先创建一个空的test文件夹
u@lb:~$ sudo mkdir /mnt/test
u@lb:~$ ls /mnt/
test

#mount iso文件
u@lb:~$ sudo mount ./test.iso /mnt
#再看/mnt里面的内容,已经被iso里面的内容给覆盖掉了
u@lb:~$ ls /mnt/
subdir01

#再mount vdisk.img
u@lb:~$ sudo mount ./vdisk.img /mnt/
#再看/mnt里面的内容,已经被vdisk.img里面的内容给覆盖掉了
u@lb:~$ ls /mnt/
aaaaaa

#通过mount命令可以看出,test.iso和vdisk.img都mount在了/mnt
#但我们在/mnt下只能看到最后一个mount的设备里的东西
u@lb:~$ mount|grep /mnt
/home/dev/test.iso on /mnt type iso9660 (ro,relatime)
/home/dev/vdisk.img on /mnt type btrfs (rw,relatime,space_cache,subvolid=5,subvol=/)

#umount /mnt,这里也可以用命令sudo umount ./vdisk.img,一样的效果
u@lb:~$ sudo umount /mnt
#test.iso文件里面的东西再次出现了
u@lb:~$ ls /mnt/
subdir01

#再次umount /mnt,这里也可以用命令sudo umount ./test.iso,一样的效果
u@lb:~$ sudo umount /mnt
#最开始/mnt目录里面的文件可以看到了
u@lb:~$ ls /mnt/
test

有了这个功能,平时挂载设备的时候就不用专门去创建空目录了,随便找个暂时不用的目录挂上去就可以了。

挂载一个设备到多个目录

当然我们也可以把一个设备mount到多个文件夹,这样在多个文件夹中都可以访问该设备中的内容。

#新建两目录用于挂载点
u@lb:~$ sudo mkdir /mnt/disk1 /mnt/disk2
#将vdisk.img依次挂载到disk1和disk2
u@lb:~$ sudo mount ./vdisk.img /mnt/disk1
u@lb:~$ sudo mount ./vdisk.img /mnt/disk2

#这样在disk1下和disk2下面都能看到相同的内容
u@lb:~$ tree /mnt
/mnt
├── disk1
│   └── aaaaaa
└── disk2
    └── aaaaaa

#在disk1下创建一个新文件
u@lb:~$ sudo touch /mnt/disk1/bbbbbb
#这个文件在disk2下面也能看到
u@lb:~$ tree /mnt
/mnt
├── disk1
│   ├── aaaaaa
│   └── bbbbbb
└── disk2
    ├── aaaaaa
    └── bbbbbb

回归正题................

mount bind可为当前挂载点绑定一个新的挂载点。比如执行如下命令,可创建foo目录的一个镜像目录bar,它们已经绑定在一起:

mkdir foo bar
mount --bind foo bar

mount bind绑定后的两个目录类似于硬链接,无论读写bar还是读写foo,都会反应在另一方,内核在底层所操作的都是同一个物理位置。

echo 1 >foo/a.txt
cat bar/a.txt      # 输出1

将bar卸载后,bar目录回归原始空目录状态,期间所执行的修改都保留在foo目录下:

$ sudo umount bar
$ ls foo
a.txt
$ ls bar    # 空

mount bind除了可以绑定两个普通目录,还可以绑定挂载点。

假设/mnt/foo是一个挂载点,执行如下命令:

mount --bind /mnt/foo /mnt/bar

这将使得/mnt/bar成为/mnt/foo的一个镜像挂载点,读写/mnt/bar和读写/mnt/foo是等价的,且无论卸载哪一方,另一方都依旧可用。

如果bind在一起的两个目录下的子目录再挂载了设备的话,他们之间还能相互看到子目录里挂载的内容吗? 比如在第一个目录下的子目录里面再mount了一个设备,那么在另一个目录下面能看到这个mount的设备里面的东西吗?答案是要看bind mount的propagation type(扩展类型)。那什么是propagation type呢?

peer group和propagation type都是随着shared subtrees一起被引入的概念,下面分别对他们做一个介绍。

peer group

peer group就是一个或多个挂载点的集合,他们之间可以共享挂载信息。目前在下面两种情况下会使两个挂载点属于同一个peer group(前提条件是挂载点的propagation type是shared)

  • 利用mount --bind命令,将会使源和目的挂载点属于同一个peer group,当然前提条件是‘源’必须要是一个挂载点。

  • 当创建新的mount namespace时,新namespace会拷贝一份老namespace的挂载点信息,于是新的和老的namespace里面的相同挂载点就会属于同一个peer group。

propagation type

每个挂载点都有一个propagation type标志, 由它来决定当一个挂载点的下面创建和移除挂载点的时候,是否会传播到属于相同peer group的其他挂载点下去,也即同一个peer group里的其他的挂载点下面是不是也会创建和移除相应的挂载点.现在有4种不同类型的propagation type:

  • MS_SHARED: 从名字就可以看出,挂载信息会在同一个peer group的不同挂载点之间共享传播. 当一个挂载点下面添加或者删除挂载点的时候,同一个peer group里的其他挂载点下面也会挂载和卸载同样的挂载点

  • MS_PRIVATE: 跟上面的刚好相反,挂载信息根本就不共享,也即private的挂载点不会属于任何peer group

  • MS_SLAVE: 跟名字一样,信息的传播是单向的,在同一个peer group里面,master的挂载点下面发生变化的时候,slave的挂载点下面也跟着变化,但反之则不然,slave下发生变化的时候不会通知master,master不会发生变化。

  • MS_UNBINDABLE: 这个和MS_PRIVATE相同,只是这种类型的挂载点不能作为bind mount的源,主要用来防止递归嵌套情况的出现。这种类型不常见,本篇将不介绍这种类型,有兴趣的同学请参考这里的例子

还有一些概念需要澄清一下:

  • propagation type是挂载点的属性,每个挂载点都是独立的

  • 挂载点是有父子关系的,比如挂载点/和/mnt/cdrom,/mnt/cdrom都是‘/’的子挂载点,‘/’是/mnt/cdrom的父挂载点

  • 默认情况下,如果父挂载点是MS_SHARED,那么子挂载点也是MS_SHARED的,否则子挂载点将会是MS_PRIVATE,跟爷爷挂载点没有关系

查看propagation type和peer group

默认情况下,子挂载点会继承父挂载点的propagation type

创建目录

#准备4个虚拟的disk,并在上面创建ext2文件系统,用于后续的mount测试
u@lb:~$ mkdir disks && cd disks
u@lb:~/disks$ dd if=/dev/zero bs=1M count=32 of=./disk1.img
u@lb:~/disks$ dd if=/dev/zero bs=1M count=32 of=./disk2.img
u@lb:~/disks$ dd if=/dev/zero bs=1M count=32 of=./disk3.img
u@lb:~/disks$ dd if=/dev/zero bs=1M count=32 of=./disk4.img
u@lb:~/disks$ mkfs.ext2 ./disk1.img
u@lb:~/disks$ mkfs.ext2 ./disk2.img
u@lb:~/disks$ mkfs.ext2 ./disk3.img
u@lb:~/disks$ mkfs.ext2 ./disk4.img
#准备两个目录用于挂载上面创建的disk
u@lb:~/disks$ mkdir disk1 disk2
u@lb:~/disks$ ls
disk1  disk1.img  disk2  disk2.img  disk3.img  disk4.img

#确保根目录的propagation type是shared,
#这一步是为了保证大家的操作结果和示例中的一样
u@lb:~/disks$ sudo mount --make-shared /
#显式的以shared方式挂载disk1
u@lb:~/disks$ sudo mount --make-shared ./disk1.img ./disk1
#显式的以private方式挂载disk2
u@lb:~/disks$ sudo mount --make-private ./disk2.img ./disk2

#mountinfo比mounts文件包含有更多的关于挂载点的信息
#这里sed主要用来过滤掉跟当前主题无关的信息
#shared:105表示挂载点/home/dev/disks/disk1是以shared方式挂载,且peer group id为105
#而挂载点/home/dev/disks/disk2没有相关信息,表示是以private方式挂载
u@lb:~/disks$ cat /proc/self/mountinfo |grep disk | sed 's/ - .*//'
164 24 7:1 / /home/dev/disks/disk1 rw,relatime shared:105
173 24 7:2 / /home/dev/disks/disk2 rw,relatime

#分别在disk1和disk2目录下创建目录disk3和disk4,然后挂载disk3,disk4到这两个目录
u@lb:~/disks$ sudo mkdir ./disk1/disk3 ./disk2/disk4
u@lb:~/disks$ sudo mount ./disk3.img ./disk1/disk3
u@lb:~/disks$ sudo mount ./disk4.img ./disk2/disk4

#查看挂载信息,第一列的数字是挂载点ID,第二例是父挂载点ID,
#从结果来看,176和164的类型都是shared,而179和173的类型都是private的,
#说明在默认mount的情况下,子挂载点会继承父挂载点的propagation type
u@lb:~/disks$ cat /proc/self/mountinfo |grep disk| sed 's/ - .*//'
164 24 7:1 / /home/dev/disks/disk1 rw,relatime shared:105 
173 24 7:2 / /home/dev/disks/disk2 rw,relatime 
176 164 7:3 / /home/dev/disks/disk1/disk3 rw,relatime shared:107 
179 173 7:4 / /home/dev/disks/disk2/disk4 rw,relatime 

2、shared subtrees

Shared subtrees就是一种控制子挂载点能否在其他地方被看到的技术,它只会在bind mount和mount namespace中用到,属于不怎么常用的功能。

对于挂载点/mnt/foo,执行如下命令:

mount --bind /mnt/foo /mnt/bar

bind绑定了这两个挂载点/mnt/foo和/mnt/bar,使得操作/mnt/foo和操作/mnt/bar的效果是一样的。如果不是简单的读写这两个挂载点,而是在这两个挂载点下新增或移除子挂载点,结论还有待进一步商榷。Linux的每个挂载点都具有一个决定该挂载点是否共享子挂载点的属性,称为shared subtrees(注:这是挂载点的属性,就像是否只读一样的属性)。该属性用于决定某挂载点之下新增或移除子挂载点时,是否同步影响bind另一端的挂载点。

shared subtrees有四种属性值,它们的设置方式分别为:

# 挂载前直接设置shared subtrees属性
mount --make-private    --bind <olddir> <newdir>
mount --make-shared     --bind <olddir> <newdir>
mount --make-slave      --bind <olddir> <newdir>
mount --make-unbindable --bind <olddir> <newdir>

# 或者挂载后设置挂载点属性
mount --bind <olddir> <newdir>
mount --make-private    <newdir>
mount --make-shared     <newdir> 
mount --make-slave      <newdir>
mount --make-unbindable <newdir>

对于shared subtrees这几种属性值,以mount --bind foo bar为例:

  • private属性:表示在foo或bar下新增、移除子挂载点,不会体现在另一方,即foo <-x-> bar
  • shared属性:表示在foo或bar下新增、移除子挂载点,都会体现在另一方,即foo <--> bar
  • slave属性:类似shared,但只是单向的,foo下新增或移除子挂载点会体现在bar中,但bar中新增或移除子挂载点不会影响foo,即,即foo --> bar, bar -x-> foo
  • unbindable属性:表示挂载点bar目录将无法执行bind操作关联到其它挂载点3

shared 和 private mount

#umount掉disk3和disk4,创建两个新的目录bind1和bind2用于bind测试
u@lb:~/disks$ sudo umount /home/dev/disks/disk1/disk3
u@lb:~/disks$ sudo umount /home/dev/disks/disk2/disk4
u@lb:~/disks$ mkdir bind1 bind2

#bind的方式挂载disk1到bind1,disk2到bind2
u@lb:~/disks$ sudo mount --bind ./disk1 ./bind1
u@lb:~/disks$ sudo mount --bind ./disk2 ./bind2

#查看挂载信息,显然默认情况下bind1和bind2的propagation type继承自父挂载点24(/),都是shared。
#由于bind2的源挂载点disk2是private的,所以bind2没有和disk2在同一个peer group里面,
#而是重新创建了一个新的peer group,这个group里面就只有它一个。
#因为164和176都是shared类型且是通过bind方式mount在一起的,所以他们属于同一个peer group 105。
u@lb:~/disks$ cat /proc/self/mountinfo |grep disk| sed 's/ - .*//'
164 24 7:1 / /home/dev/disks/disk1 rw,relatime shared:105 
173 24 7:2 / /home/dev/disks/disk2 rw,relatime 
176 24 7:1 / /home/dev/disks/bind1 rw,relatime shared:105 
179 24 7:2 / /home/dev/disks/bind2 rw,relatime shared:109 

#ID为24的挂载点为根目录的挂载点
u@lb:~/disks$ cat /proc/self/mountinfo |grep ^24| sed 's/ - .*//'
24 0 252:0 / / rw,relatime shared:1

#这时disk3和disk4目录都是空的
u@lb:~/disks$ ls bind1/disk3/
u@lb:~/disks$ ls bind2/disk4/
u@lb:~/disks$ ls disk1/disk3/
u@lb:~/disks$ ls disk2/disk4/

#重新挂载disk3和disk4
u@lb:~/disks$ sudo mount ./disk3.img ./disk1/disk3
u@lb:~/disks$ sudo mount ./disk4.img ./disk2/disk4

#由于disk1/和bind1/属于同一个peer group,
#所以在挂载了disk3后,在两个目录下都能看到disk3下的内容
u@lb:~/disks$ ls disk1/disk3/
lost+found
u@lb:~/disks$ ls bind1/disk3/
lost+found

#而disk2/是private类型的,所以在他下面挂载disk4不会通知bind2,
#于是bind2下的disk4目录是空的
u@lb:~/disks$ ls disk2/disk4/
lost+found
u@lb:~/disks$ ls bind2/disk4/
u@lb:~/disks$

#再看看disk3,虽然182和183的父挂载点不一样,但由于他们父挂载点属于同一个peer group,
#且disk3是以默认方式挂载的,所以他们属于同一个peer group
u@lb:~/disks$ cat /proc/self/mountinfo |egrep "disk3"| sed 's/ - .*//'
182 164 7:3 / /home/dev/disks/disk1/disk3 rw,relatime shared:111 
183 176 7:3 / /home/dev/disks/bind1/disk3 rw,relatime shared:111 

#umount bind1/disk3后,disk1/disk3也相应的自动umount掉了
u@lb:~/disks$ sudo umount bind1/disk3
u@lb:~/disks$ cat /proc/self/mountinfo |grep disk3

slave mount

#umount除disk1的所有其他挂载点
u@lb:~/disks$ sudo umount ./disk2/disk4
u@lb:~/disks$ sudo umount /home/dev/disks/bind1
u@lb:~/disks$ sudo umount /home/dev/disks/bind2
u@lb:~/disks$ sudo umount /home/dev/disks/disk2
#确认只剩disk1
u@lb:~/disks$ cat /proc/self/mountinfo |grep disk| sed 's/ - .*//'
164 24 7:1 / /home/dev/disks/disk1 rw,relatime shared:105 

#分别显式的用shared和slave的方式bind disk1
u@lb:~/disks$ sudo mount --bind --make-shared ./disk1 ./bind1
u@lb:~/disks$ sudo mount --bind --make-slave ./bind1 ./bind2

#164、173和176都属于同一个peer group,
#master:105表示/home/dev/disks/bind2是peer group 105的slave
u@lb:~/disks$ cat /proc/self/mountinfo |grep disk| sed 's/ - .*//'
164 24 7:1 / /home/dev/disks/disk1 rw,relatime shared:105 
173 24 7:1 / /home/dev/disks/bind1 rw,relatime shared:105 
176 24 7:1 / /home/dev/disks/bind2 rw,relatime master:105 

#mount disk3到disk1的子目录disk3下
u@lb:~/disks$ sudo mount ./disk3.img ./disk1/disk3/
#其他两个目录bin1和bind2里面也挂载成功,说明master发生变化的时候,slave会跟着变化
u@lb:~/disks$ cat /proc/self/mountinfo |grep disk| sed 's/ - .*//'
164 24 7:1 / /home/dev/disks/disk1 rw,relatime shared:105 
173 24 7:1 / /home/dev/disks/bind1 rw,relatime shared:105 
176 24 7:1 / /home/dev/disks/bind2 rw,relatime master:105 
179 164 7:2 / /home/dev/disks/disk1/disk3 rw,relatime shared:109 
181 176 7:2 / /home/dev/disks/bind2/disk3 rw,relatime master:109 
180 173 7:2 / /home/dev/disks/bind1/disk3 rw,relatime shared:109 

#umount disk3,然后mount disk3到bind2目录下
u@lb:~/disks$ sudo umount ./disk1/disk3/
u@lb:~/disks$ sudo mount ./disk3.img ./bind2/disk3/

#由于bind2的propagation type是slave,所以disk1和bind1两个挂载点下面不会挂载disk3
#从179的类型可以看出,当父挂载点176是slave类型时,默认情况下其子挂载点179是private类型
u@lb:~/disks$ cat /proc/self/mountinfo |grep disk| sed 's/ - .*//'
164 24 7:1 / /home/dev/disks/disk1 rw,relatime shared:105 
173 24 7:1 / /home/dev/disks/bind1 rw,relatime shared:105 
176 24 7:1 / /home/dev/disks/bind2 rw,relatime master:105 
179 176 7:2 / /home/dev/disks/bind2/disk3 rw,relatime -

unbindable类型

unbindable类型主要是为了避免【将父辈或祖先挂载点挂载在子孙挂载点上】时出现的大量递归挂载的问题。

例如,当前有如下挂载信息:

/dev/sda1 on /
/dev/sdb6 on /mntX
/dev/sdb7 on /mntY

 

如果执行:

# --rbind类似于bind,但会递归bind当前挂载点上已有的子挂载点
mount --rbind / /home/lb/

将得到如下挂载信息:

/dev/sda1 on /
/dev/sdb6 on /mntX
/dev/sdb7 on /mntY
/dev/sda1 on /home/lb
/dev/sdb6 on /home/lb/mntX
/dev/sdb7 on /home/lb/mntY

如果再执行:

mount --rbind / /home/lz

将得到如下挂载信息:

/dev/sda1 on /
/dev/sdb6 on /mntX
/dev/sdb7 on /mntY
/dev/sda1 on /home/lb
/dev/sdb6 on /home/lb/mntX
/dev/sdb7 on /home/lb/mntY
/dev/sda1 on /home/lz
/dev/sdb6 on /home/lz/mntX
/dev/sdb7 on /home/lz/mntY
/dev/sda1 on /home/lz/home/lb
/dev/sdb6 on /home/lz/home/lb/mntX
/dev/sdb7 on /home/lz/home/lb/mntY

使用--unbindable属性,可避免该问题:

$ sudo mount --make-unbindable --bind foo bar

现在foo和bar绑定了,bar作为挂载点,它将不能再bind到其他路径:

$ sudo mount --bind bar baz
mount: /home/longshuai/fs/baz: wrong fs type, bad option, bad superblock on /home/longshuai/fs/bar, missing codepage or helper program, or other error.

如果是--rbind,假如当前有如下挂载点信息:

/dev/sda1 on /
/dev/sdb6 on /mntX
/dev/sdb7 on /mntY

执行如下操作:

mount --rbind --make-unbindable / /home/lb

将得到如下挂载点信息:

/dev/sda1 on /
/dev/sdb6 on /mntX
/dev/sdb7 on /mntY
/dev/sda1 on /home/lz
/dev/sdb6 on /home/lz/mntX
/dev/sdb7 on /home/lz/mntY

再执行如下操作:

mount --rbind --make-unbindable / /home/lz

最终得到如下挂载点信息:

/dev/sda1 on /
/dev/sdb6 on /mntX
/dev/sdb7 on /mntY
/dev/sda1 on /home/lb
/dev/sdb6 on /home/lb/mntX
/dev/sdb7 on /home/lb/mntY
/dev/sda1 on /home/lz
/dev/sdb6 on /home/lz/mntX
/dev/sdb7 on /home/lz/mntY

如果bind时不指定--make-*,它默认的shared subtrees属性是什么呢?这个问题有点复杂。

首先要理解父子挂载点对shared subtrees属性的继承规则。

如果父挂载点当前的属性为shared,则子挂载点的默认属性也将为shared
只要父挂载点当前属性不是shared,子挂载点的属性均为private
注意,内核默认的shared subtrees属性为private,所以root挂载点/的属性默认是private,这将使得挂载在/之下的所有挂载点的默认属性都是private。但是,/的属性设置为shared会更方便也更符合实际需求。

所以,systemd系统在初始化内核过程中,在挂载/时,会将其设置为shared属性。

$ grep '/ / ' /proc/self/mountinfo 
29 1 8:5 / / rw,relatime shared:1

目前主流Linux大多数都使用systemd系统,由于此时/被设置为shared,使得挂载在/之下的所有挂载点的默认属性都是shared。

$ grep -E '/ / |foo' /proc/self/mountinfo 
29 1 8:5 / / rw,relatime shared:1
622 29 8:5 foo bar rw,relatime shared:1

更多学习命令:https://segmentfault.com/t/linux

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐