proc 文件系統及初始化
proc 文件系統簡述:
proc文件系統使得內核可以生成與系統的狀態和配置有關的信息。該信息可以由用戶和系統程序從普通文件讀取,而無需專門的工具與內核通信。通過proc文件系統,可以獲得有關內核各子系統的信息,也可以在不重新編譯內核源代碼的情況下修改內核的行爲,或重啓系統。
在使用proc文件系統之前,必須用mount裝載他,而內核必須建立並初始化幾個數據結構,以便在內核內存中描述該文件系統的結構。由proc_root_init()完成proc初始化。基本步驟:
-
proc_init_inodecache() 利用kmem_cache_create()創建proc_inode對象創建一個slab緩存。
-
register_filesystem() 將該文件系統正式地註冊到內核。
-
proc_net_init() 建立很多與網絡相關的文件。
-
proc_tty_init() 建立與tty相關文件
-
proc_mkdir() 建立/proc的若干子目錄。
-
proc_sys_init() 建立sysctl層次結構,即/proc/sys/ 目錄層次。sysctl信息導出到/proc/sys目錄下。
fs/proc/root.c static struct file_system_type proc_fs_type = { .name = "proc", .mount = proc_mount, .kill_sb = proc_kill_sb, .fs_flags = FS_USERNS_VISIBLE | FS_USERNS_MOUNT, }; void __init proc_root_init(void) { int err; proc_init_inodecache(); err = register_filesystem(&proc_fs_type); if (err) return; proc_self_init(); proc_thread_self_init(); proc_symlink("mounts", NULL, "self/mounts"); proc_net_init(); #ifdef CONFIG_SYSVIPC proc_mkdir("sysvipc", NULL); #endif proc_mkdir("fs", NULL); proc_mkdir("driver", NULL); proc_create_mount_point("fs/nfsd"); /* somewhere for the nfsd filesystem to be mounted */ #if defined(CONFIG_SUN_OPENPROMFS) || defined(CONFIG_SUN_OPENPROMFS_MODULE) /* just give it a mountpoint */ proc_create_mount_point("openprom"); #endif proc_tty_init(); proc_mkdir("bus", NULL); proc_sys_init(); }
proc_mkdir新生成proc_dir_entry實例並將新生成proc_dir_entry實例註冊到內核。基本步驟:
-
檢測和賦值權限mode。
-
利用__proc_create(parent, name, node, nlink)新生成proc_dir_entry實例,其實質爲在parent目錄下建立目錄(文件)名爲name的子目錄(文件)。
-
使proc_iops和proc_fops分別指向inode_operations和file_operations類型實例,其父目錄的鏈接數加一。
-
新生成的proc_dir_entry實例註冊到內核中。並利用pde_subdir_insert()將新創建的目錄或文件添加到其父目錄的紅黑樹中。
struct proc_dir_entry *proc_mkdir(const char *name,
struct proc_dir_entry *parent)
{
return proc_mkdir_data(name, 0, parent, NULL);
}struct proc_dir_entry *proc_mkdir_data(const char *name, umode_t mode,
struct proc_dir_entry *parent, void *data)
{
struct proc_dir_entry *ent;if (mode == 0) mode = S_IRUGO | S_IXUGO; ent = __proc_create(&parent, name, S_IFDIR | mode, 2); if (ent) { ent->data = data; ent->proc_fops = &proc_dir_operations; ent->proc_iops = &proc_dir_inode_operations; parent->nlink++; if (proc_register(parent, ent) < 0) { kfree(ent); parent->nlink--; ent = NULL; } } return ent;
}
EXPORT_SYMBOL_GPL(proc_mkdir_data);
參考:深入linux內核架構, linux-4.4