mount 订阅
mount是Linux下的一个命令,它可以将分区挂接到Linux的一个文件夹下,从而将分区和该目录联系起来,因此我们只要访问这个文件夹,就相当于访问该分区了。 目前mount已经不仅仅局限于Linux了。在Windows系统下的应用也越来越广了,多用在虚拟光驱类软件上,比如Clone CD,Daemon tool,WinMount等。 展开全文
mount是Linux下的一个命令,它可以将分区挂接到Linux的一个文件夹下,从而将分区和该目录联系起来,因此我们只要访问这个文件夹,就相当于访问该分区了。 目前mount已经不仅仅局限于Linux了。在Windows系统下的应用也越来越广了,多用在虚拟光驱类软件上,比如Clone CD,Daemon tool,WinMount等。
信息
简    介
是Linux下的一个命令
外文名
mount
用    途
用在虚拟光驱类软件上
中文名
挂载
mount定义
当然,mount命令也变成了一种图形化的界面,用户不需要再去记住那些复杂的mount命令,只需选择文件并点击mount按钮就可以完成操作。mount在Windows系统下的含义是:挂载文件到一个虚拟盘或一个虚拟文件夹中,通过访问这个虚拟盘或文件夹使用整个文件。
收起全文
精华内容
下载资源
问答
  • mount
    千次阅读
    2022-04-05 11:57:11

    mount系统调用剖析

    开篇

    ​ 对于mount系统调用,在linux内核代码中同样也会使用到,特别是在linux内核的启动部分的源码中,她换了一种形式:在linux内核4.1.15版本下,内核的mount操作与用户空间的mount系统调用操作接口函数是一致的:都由sys_mount()函数完成。在linux内核4.19.4版本下,linux内核中mount调用的接口则分离成ksys_mount()

    文本以4.1.15版本的linux内核作为分析对象展开。

    ​mount系统调用在linux内核中的定义如下(/fs/namespace.c):

    SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
    		char __user *, type, unsigned long, flags, void __user *, data)
    {
    	int ret;
    	char *kernel_type;
    	char *kernel_dev;
    	unsigned long data_page;
    	
    	kernel_type = copy_mount_string(type);
    	ret = PTR_ERR(kernel_type);
    	if (IS_ERR(kernel_type))
    		goto out_type;
    
    	kernel_dev = copy_mount_string(dev_name);
    	ret = PTR_ERR(kernel_dev);
    	if (IS_ERR(kernel_dev))
    		goto out_dev;
    
    	ret = copy_mount_options(data, &data_page);
    	if (ret < 0)
    		goto out_data;
    
    	ret = do_mount(kernel_dev, dir_name, kernel_type, flags,
    		(void *) data_page);
    
    	free_page(data_page);
    out_data:
    	kfree(kernel_dev);
    out_dev:
    	kfree(kernel_type);
    out_type:
    	return ret;
    }
    

    上述第9-12、14-17行代码,使用copy_mount_string()函数从用户空间复制已经存在的字符串:挂载类型、挂载设备名称。

    第19-21行代码,使用copy_mount_options()函数复制挂载选项参数。

    如果代码执行异常,将通过goto语句跳转到对应的位置,从而结束mount系统调用流程。如果没有出现错误或异常,将调用do_mount()函数执行实际的挂载操作。该函数则是mount操作的核心函数,下文将分析该函数。


    do_mount()函数定义如下:

    long do_mount(const char *dev_name, const char __user *dir_name,
    		const char *type_page, unsigned long flags, void *data_page)
    {
    	struct path path;
    	int retval = 0;
    	int mnt_flags = 0;
    
    	/* Discard magic */
    	if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
    		flags &= ~MS_MGC_MSK;
    
    	/* 执行基本的检查*/
    	if (data_page)
    		((char *)data_page)[PAGE_SIZE - 1] = 0;
    
    	/*寻找挂载点 */
    	retval = user_path(dir_name, &path);
    	if (retval)
    		return retval;
    
    	retval = security_sb_mount(dev_name, &path,
    				   type_page, flags, data_page);
    	if (!retval && !may_mount())
    		retval = -EPERM;
    	if (retval)
    		goto dput_out;
    
    	if (!(flags & MS_NOATIME))
    		mnt_flags |= MNT_RELATIME;
    
        //分割每个挂载点的挂载标志
    	if (flags & MS_NOSUID)
    		mnt_flags |= MNT_NOSUID;
    	if (flags & MS_NODEV)
    		mnt_flags |= MNT_NODEV;
    	if (flags & MS_NOEXEC)
    		mnt_flags |= MNT_NOEXEC;
    	if (flags & MS_NOATIME)
    		mnt_flags |= MNT_NOATIME;
    	if (flags & MS_NODIRATIME)
    		mnt_flags |= MNT_NODIRATIME;
    	if (flags & MS_STRICTATIME)
    		mnt_flags &= ~(MNT_RELATIME | MNT_NOATIME);
    	if (flags & MS_RDONLY)
    		mnt_flags |= MNT_READONLY;
    
    	/* 设置默认的重新挂载时间是保存时间 */
    	if ((flags & MS_REMOUNT) &&
    	    ((flags & (MS_NOATIME | MS_NODIRATIME | MS_RELATIME |
    		       MS_STRICTATIME)) == 0)) {
    		mnt_flags &= ~MNT_ATIME_MASK;
    		mnt_flags |= path.mnt->mnt_flags & MNT_ATIME_MASK;
    	}
    
    	flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE | MS_BORN |
    		   MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT |
    		   MS_STRICTATIME);
    
    	if (flags & MS_REMOUNT)
    		retval = do_remount(&path, flags & ~MS_REMOUNT, mnt_flags,
    				    data_page);
    	else if (flags & MS_BIND)
    		retval = do_loopback(&path, dev_name, flags & MS_REC);
    	else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
    		retval = do_change_type(&path, flags);
    	else if (flags & MS_MOVE)
    		retval = do_move_mount(&path, dev_name);
    	else
    		retval = do_new_mount(&path, type_page, flags, mnt_flags,
    				      dev_name, data_page);
    dput_out:
    	path_put(&path);
    	return retval;
    }
    

    从以上代码可见,在之前的59行的代码大部分用于flags标志位的判断和设置。在59-70行代码则是真正执行的挂载逻辑。从代码可知,在do_mount()函数中,将挂载分成了5种情况:

    (1)如果是重新挂载:将调用do_remount()执行挂载操作。

    (2)如果是MS_BIND标志:则调用do_loopback()函数。

    (3)如果是MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE标志:则调用do_change_type()函数。

    (4)如果是MS_MOVE标志:则调用do_move_mount()函数。

    (5)如果都不是以上四种挂载情况,那么就会调用do_new_mount()函数创建新的挂载。

    在实际挂载中,小生假设运行逻辑中do_new_mount()函数将被执行,下文将分析该函数。


    do_new_mount()函数功能是:为用户空间创建一个新的挂载和请求,并将其添加到名称空间挂载树上。该函数定义如下:

    static int do_new_mount(struct path *path, const char *fstype, int flags,
    			int mnt_flags, const char *name, void *data)
    {
    	struct file_system_type *type;
    	struct user_namespace *user_ns = current->nsproxy->mnt_ns->user_ns;
    	struct vfsmount *mnt;
    	int err;
    
    	if (!fstype)
    		return -EINVAL;
    	//根据fstype参数获取文件系统的类型,返回struct file_system_type
    	type = get_fs_type(fstype);
    	if (!type)
    		return -ENODEV;
    
    	if (user_ns != &init_user_ns) {
    		if (!(type->fs_flags & FS_USERNS_MOUNT)) {
    			put_filesystem(type);
    			return -EPERM;
    		}
    		/* Only in special cases allow devices from mounts
    		 * created outside the initial user namespace.
    		 */
    		if (!(type->fs_flags & FS_USERNS_DEV_MOUNT)) {
    			flags |= MS_NODEV;
    			mnt_flags |= MNT_NODEV | MNT_LOCK_NODEV;
    		}
    		if (type->fs_flags & FS_USERNS_VISIBLE) {
    			if (!fs_fully_visible(type, &mnt_flags))
    				return -EPERM;
    		}
    	}
    
    	mnt = vfs_kern_mount(type, flags, name, data);
    	if (!IS_ERR(mnt) && (type->fs_flags & FS_HAS_SUBTYPE) &&
    	    !mnt->mnt_sb->s_subtype)
    		mnt = fs_set_subtype(mnt, fstype);
    
    	put_filesystem(type);
    	if (IS_ERR(mnt))
    		return PTR_ERR(mnt);
    
    	err = do_add_mount(real_mount(mnt), path, mnt_flags);
    	if (err)
    		mntput(mnt);
    	return err;
    }
    

    从以上代码可知,do_new_mount()函数会调用vfs_kern_mount()函数创建文件系统的挂载,然后再调用do_add_mount()函数将创建的挂载添加到namespace的挂载树上。


    vfs_kern_mount()函数定义如下:

    struct vfsmount *
    vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data)
    {
    	struct mount *mnt;
    	struct dentry *root;
    
    	if (!type)
    		return ERR_PTR(-ENODEV);
    	//分配mnt挂载描述符的内存空间
    	mnt = alloc_vfsmnt(name);
    	if (!mnt)
    		return ERR_PTR(-ENOMEM);
    
    	if (flags & MS_KERNMOUNT)
    		mnt->mnt.mnt_flags = MNT_INTERNAL;
    	
        //在mount_fs()函数中,将调用对应文件系统类型注册的mount函数挂载文件系统,读取并且解析超级块并返回对应的struct dentry。
    	root = mount_fs(type, flags, name, data);
    	if (IS_ERR(root)) {
    		mnt_free_id(mnt);
    		free_vfsmnt(mnt);
    		return ERR_CAST(root);
    	}
    	
        //设置挂载树的根和超级快
    	mnt->mnt.mnt_root = root;
    	mnt->mnt.mnt_sb = root->d_sb;
    	mnt->mnt_mountpoint = mnt->mnt.mnt_root;
    	mnt->mnt_parent = mnt;
    	lock_mount_hash();
        //把挂载描述符添加到超级块的挂载实例链表中。
    	list_add_tail(&mnt->mnt_instance, &root->d_sb->s_mounts);
    	unlock_mount_hash();
    	return &mnt->mnt;
    }
    

    do_add_mount()函数定义如下:

    static int do_add_mount(struct mount *newmnt, struct path *path, int mnt_flags)
    {
    	struct mountpoint *mp;
    	struct mount *parent;
    	int err;
    
    	mnt_flags &= ~MNT_INTERNAL_FLAGS;
    
    	mp = lock_mount(path);
    	if (IS_ERR(mp))
    		return PTR_ERR(mp);
    
    	parent = real_mount(path->mnt);
    	err = -EINVAL;
    	if (unlikely(!check_mnt(parent))) {
    		/* that's acceptable only for automounts done in private ns */
    		if (!(mnt_flags & MNT_SHRINKABLE))
    			goto unlock;
    		/* ... and for those we'd better have mountpoint still alive */
    		if (!parent->mnt_ns)
    			goto unlock;
    	}
    
    	/* 拒绝在同一个挂载点上使用相同的文件系统 */
    	err = -EBUSY;
    	if (path->mnt->mnt_sb == newmnt->mnt.mnt_sb &&
    	    path->mnt->mnt_root == path->dentry)
    		goto unlock;
    
    	err = -EINVAL;
    	if (d_is_symlink(newmnt->mnt.mnt_root))
    		goto unlock;
    
    	newmnt->mnt.mnt_flags = mnt_flags;
    	err = graft_tree(newmnt, parent, mp);
    
    unlock:
    	unlock_mount(mp);
    	return err;
    }
    

    do_add_mount()函数的核心操作是:

    1、把挂载描述符加入到散列表中。

    2、将挂载描述符加入父亲的孩子链表中。如下代码片段(出自/fs/namespace.c文件中commit_tree()函数):

    	list_add_tail(&head, &mnt->mnt_list);
    	list_for_each_entry(m, &head, mnt_list)
    		m->mnt_ns = n;
    

    结尾

    ​ 总结一下,mount系统调用主要执行的流程如下:

    (1)调用user_path()函数,根据目录名称找到挂载描述符和dentry实例。

    (2)调用get_fs_type()函数,根据文件系统类型的名称查找对应的file_system_type实例。

    (3)调用alloc_vfsmount()函数,分配挂载描述符内存空间,并填充相关参数。

    (4)在mount_fs()函数中,调用对应文件系统类型下注册的mount回调函数,执行文件系统挂载操作,读取并解析超级块。(该函数与具体文件系统相关)

    (5)把挂载描述符添加到超级块的挂载实例链表中。

    (6)把挂载描述符加入父亲的孩子链表。


    由于小生知识与精力有限,如果文章存在不妥的地方,欢迎批评指正或与我讨论,哈哈!


    搜索关注【嵌入式小生】wx公众号获取更多精彩内容>>>>
    请添加图片描述

    更多相关内容
  • 针对 Linux 上 ZFS 的 Mountall 增强功能这个 git 存储库的主页是: 位于的 ZoL PPA 中的 Mountall 包是使用 git-buildpackage 工具从此存储库构建的。休闲构建说明只需像这样快速构建: $ apt-get source --build ...
  • 知道大家时间都很宝贵,我直接把流程...mount /dev/vdb /u01 # mount 磁盘到/u01,保证/u01为空 blkid # 获取磁盘的uuid和属性,用uuid来进行开机mount vim /etc/fstab # 开机mount,模板是UUID=********** /u01 ext4 d
  • sudo mount //192.168.10.22/FTPServer /windows -o username=user,password=abcdefg -t cifs  方式二:密码单独输入 sudo mount //192.168.10.22/FTPServer /windows -o username=user -t cifs password:...
  • 对于新手学习,mount 命令,一定会有很多疑问。其实我想疑问来源更多的是对linux系统本身特殊性了解问题。 linux是基于文件系统,所有的设备都会对应于:/dev/下面的设备。如:  [chengmo@centos5 dev]$ ls | grep...
  • 在Vue构造函数时,需要配置一个el属性,如果没有没有el属性时,可以使用.$mount(‘#app’)进行挂载。 配置了el属性: new Vue({ el:#app, router }); 如果没有配置el属性,可以使用手动挂载$mount(“#app”) new...
  • 安装iso 使用 udisksctl 挂载 ISO ... 还可以创建 Thunar 的自定义操作( mount-iso.sh复制到/usr/bin/mount-iso ): <icon>application-x-cd-image <name>Mount ISO <command>mount-iso %f *.iso;*.ISO <other>
  • Linux mount命令 Linux mount命令是经常会使用到的命令,它用于挂载Linux系统外的文件。 语法 mount [-hV] mount -a [-fFnrsvw] [-t vfstype] mount [-fnrsvw] [-o options [,...]] device | dir mount [-fnrsvw] [-...
  • 在vue实例中,通过$mount()实现实例的挂载,下面来分析一下$mount()函数都实现了什么功能。 $mount函数执行位置 _init这个私有方法是在执行initMixin时候绑定到Vue原型上的。   $mount函数是如如何把组件挂在到...
  • 找了好久,百度上一直都是mount命令加各种参数,确认了用户跟密码都没有问题,目录权限也都给了,最后是使用下面的办法解决的。 在/etc/fstab的挂载配置里面添加参数sec=ntlmssp,如下: //hahaha....
  • 最近工作中遇到一个问题,在linux mount /dev/vdb 到 /home 分区时报错: # mount /dev/vdb /home mount: you must specify the filesystem type 先执行:mkfs.ext3 /dev/vdb # mkfs.ext3 /dev/vdb mke2fs 1.41.12...
  • ipfs-api-mount 将IPFS目录挂载为本地FS。 go-ipfs守护程序具有此功能,但从0.4.22版本开始,它的速度很慢。 ipfs-api-mount旨在提高效率。 对于顺序访问随机数据,它比ipfs cat慢3倍ipfs cat但比go-ipfs挂载的cat...
  • 主要介绍了python获得linux下所有挂载点(mount points)的方法,涉及Python操作Linux下挂载点的相关技巧,非常具有实用价值,需要的朋友可以参考下
  • mount.nfs: Connection timed out
  • mountpoint命令用来判断指定的目录是否是加载点,如果是挂载点返回0,如果不是就返回非0。设备总是挂载在某个指定的目录下,所以就可以使用mountpoint这条命令来确认某个目录是否“临时性”的被文件系统占用。 语法...
  • tianma-mount 在给定域名或路径上使用中间件。 安装 $ npm install tianma-mount 使用 挂载域名 可以为不同的域名使用不同的中间件。域名可以精确到二级或者三级,也可以模糊到一级甚至是零级。 var tianma = ...
  • Linux 命令之mount

    2020-12-02 16:02:27
    Linux 命令之mount mount [-t vfstype] [-o options] device dir -t vfstype 指定文件系统的类型 iso9660 光盘或光盘镜像 msdos DOS fat 16文件系统 vfat windows 9x fat32 文件系统 ntfs Windows nt ntfs ...
  • linux中mount命令 linux的mount命令使用方法参数说明 --入党程序 Linux系统下mount命令是常用的命令之一它主要用于挂载linux系统外的文件主要用法有显示程序信息挂载档案等具体怎么操作呢?下面由为大家了linux的...
  • TF_EFS_MOUNT 提供一个EFS文件系统,挂载目标和安全组。 用法 module " efs_mount " { source = " github.com/manheim/tf_efs_mount " name = " my-efs-mount " subnets = " subnet-abcd1234,subnet-efgh5678 " ...
  • mount命令剖析.doc

    2020-01-11 15:48:19
    系统调用mount在内核中的实现函数的深度剖析,分析了sys_mount,do_mount,do_new_mount,do_kern_mount,vfs_kern_mount,get_sb等一些接口。
  • 每每天天学学点点Vue源源码码之之vm$mount挂挂载载函函数数 这篇文章主要介绍了vm$mount挂载函数文中通过示例代码介绍的非常详细对大家的学习或者工作具有一定 的参 学习价值需要的朋友们下面随着小编来一起学习学习...
  • 卢克山一个简单的脚本,使... 只需克隆存储库,将其插入cd,然后sudo ./luks-mount-install.sh执行sudo chmod a+x luks-mount-install.sh然后执行sudo ./luks-mount-install.sh 进行sudo luks-mount help以查看使用案例
  • 洪流装载使用和 fuse 实时安装 torrent(或磁力链接)作为文件系统。... [options]source .torrent file or magnet link to openOptions:-m PATH, --mount PATH Mount location path [directory] [.]-l, --lazy Dow
  • cgroupfs-mount.rar

    2021-08-06 10:08:30
    cgroupfs-mount.rar
  • auto-mount.zip

    2020-04-16 22:12:49
    1,auto-mount运行起来是会定期(30s)扫描是否有USB存储设备插入。 2,当有USB存储设备插入树莓派时auto-mount可以检测出来并识别该设备的名称也就是lable,然后会创建/home/mnt/{设备lable}目录并将该设备挂载到...
  • 【IT十八掌徐培成】Linux基础-04.xargs-mount-umount.zip

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 491,126
精华内容 196,450
关键字:

mount