-------------
内核:2.6.30
-------------
//入口
void __init proc_root_init(void) {
int err; proc_init_inodecache(); err = register_filesystem(&proc_fs_type); //注册proc文件系统 if (err) return; proc_mnt = kern_mount_data(&proc_fs_type, &init_pid_ns); //必须在注册函数之后调用vfs_kern_mount(),使得在内核范围内的vfsmnt被放置在->kern_mnt处。 err = PTR_ERR(proc_mnt); if (IS_ERR(proc_mnt)) {
unregister_filesystem(&proc_fs_type); //未挂载上注销文件系统 return; } proc_symlink("mounts", NULL, "self/mounts"); //符号链接 proc_net_init();//注册初始net子目录
/* 创建相关目录文件*/ #ifdef CONFIG_SYSVIPC proc_mkdir("sysvipc", NULL); #endif proc_mkdir("fs", NULL); proc_mkdir("driver", NULL); proc_mkdir("fs/nfsd", NULL); /* somewhere for the nfsd filesystem to be mounted */ #if defined(CONFIG_SUN_OPENPROMFS) || defined(CONFIG_SUN_OPENPROMFS_MODULE) /* just give it a mountpoint */ proc_mkdir("openprom", NULL); #endif proc_tty_init();//tty子目录 #ifdef CONFIG_PROC_DEVICETREE proc_device_tree_init(); #endif proc_mkdir("bus", NULL); proc_sys_init(); //sys子目录 }
proc文件系统的注册非常简单,主要有如下几个步骤: 1.调用register_filesystem(&proc_fs_type),将proc文件类型加入到文件类型的单向链表中,如果发生错误,则返回。 2.调用 kern_mount_data函数,来mount 该文件系统,其又调用vfs_kern_mount里使用add_vfsmnt()函数建立proc文件系统的vfsmount结构,并将其加入到已装载文件系统的链表中。 最后,返回该vfsmount结构,并利用返回值,使用指针proc_mnt指向该vfsmount结构。 3.判断返回值是否错误,如果错误,那么就卸载文件系统。
注册成功接下调用type->get_sb()的函数执行:
static struct file_system_type proc_fs_type = {
.name = "proc", .get_sb = proc_get_sb, //调用 .kill_sb = proc_kill_sb, }
static int proc_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct vfsmount *mnt) {
int err; struct super_block *sb; struct pid_namespace *ns; struct proc_inode *ei;
//mount 成功 if (proc_mnt) {
/* Seed the root directory with a pid so it doesn't need * to be special in base.c. I would do this earlier but * the only task alive when /proc is mounted the first time * is the init_task and it doesn't have any pids. */ ei = PROC_I(proc_mnt->mnt_sb->s_root->d_inode); if (!ei->pid) ei->pid = find_get_pid(1); } if (flags & MS_KERNMOUNT) ns = (struct pid_namespace *)data; else ns = current->nsproxy->pid_ns; sb = sget(fs_type, proc_test_super, proc_set_super, ns); //分配一个的超级块 if (IS_ERR(sb)) return PTR_ERR(sb); if (!sb->s_root) {
sb->s_flags = flags; err = proc_fill_super(sb);//超级块例程 if (err) {
deactivate_locked_super(sb); return err; } ei = PROC_I(sb->s_root->d_inode); if (!ei->pid) {
rcu_read_lock();