1. 概述
今天本来打算写一篇关于linux内核sys_mount()代码分析的文章,习惯性地打开google,看看是否有别人写的比较好,可以参考参考,打开第一篇发现居然是自己以前写的博客,真是囧,而且也记录在优快云上,本想直接行使拿来主义,但看了下内容,发觉略有不妥,于是在那篇博客的基础上进行些修改和润色。
Linux下任何块设备在使用之前,首先要对其进行格式化成特定文件系统,如mkfs.ext3等,然后再将其挂载到系统中特定目录下,于是通过该挂载点即可访问该块设备文件系统下的所有文件和目录等。如
mount -t ext3 -o option /device/hda /home/mountdir,
便将设备/dev/hda挂载到了/home/mountdir下,我们今天的重点就是钻研kernel在该命令下到底做了些什么。参考的内核版本是linux2.6.36,本人博客如无作特别说明,内核的版本都是2.6.36。
2. 实现
2.1 相关数据结构
相关数据结构留到我们代码分析完成以后再写。
2.2 sys_mount()流程分析
内核mount函数的入口为sys_mount(),你需要在fs/namespace.c的SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name, char __user *, type, unsigned long, flags, void __user *, data)才能找到其实现,其源代码如下:
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_dir;
char *kernel_dev;
unsigned long data_page;
/* 以下几个函数将用户态参数拷贝至内核态,包括:
** 1. kernel_type:挂载文件系统类型,如ext3
** 2. kernel_dir: 挂载点路径
** 3. dev_name: 设备名称
** 4. data_pages: 选项信息
*/
ret = copy_mount_string(type, &kernel_type);
if (ret < 0)
goto out_type;
kernel_dir = getname(dir_name);
if (IS_ERR(kernel_dir)) {
ret = PTR_ERR(kernel_dir);
goto out_dir;
}
ret = copy_mount_string(dev_name, &kernel_dev);
if (ret < 0)
goto out_dev;
ret = copy_mount_options(data, &data_page);
if (ret < 0)
goto out_data;
/* 调用do_mount 完成主要挂载工作 */
ret = do_mount(kernel_dev, kernel_dir, kernel_type, flags,
(void *) data_page);
free_page(data_page);
out_data:
kfree(kern