struct pid_namespace {
struct kref kref;
struct pidmap pidmap[PIDMAP_ENTRIES];
int last_pid;
struct task_struct *child_reaper;
struct kmem_cache *pid_cachep;
unsigned int level;
struct pid_namespace *parent;
#ifdef CONFIG_PROC_FS
struct vfsmount *proc_mnt;
#endif
#ifdef CONFIG_BSD_PROCESS_ACCT
struct bsd_acct_struct *bacct;
#endif
};
/*
* PID-map pages start out as NULL, they get allocated upon
* first use and are never deallocated. This way a low pid_max
* value does not cause lots of bitmaps to be allocated, but
* the scheme scales to up to 4 million PIDs, runtime.
*/
struct pid_namespace init_pid_ns = {
.kref = {
.refcount = ATOMIC_INIT(2),
},
.pidmap = {
[ 0 ... PIDMAP_ENTRIES-1] = { ATOMIC_INIT(BITS_PER_PAGE), NULL }
},
.last_pid = 0,
.level = 0,
.child_reaper = &init_task,
};
EXPORT_SYMBOL_GPL(init_pid_ns);
static struct file_system_type proc_fs_type = {
.name = "proc",
.mount = proc_mount,
.kill_sb = proc_kill_sb,
};
register_filesystem(&proc_fs_type);
INIT_LIST_HEAD(&fs->fs_supers);
然后将proc_fs_type加到文件系统列表中。
proc_root_init(void)
pid_ns_prepare_proc(&init_pid_ns);
kern_mount_data(&proc_fs_type, ns);
vfs_kern_mount(type, MS_KERNMOUNT, type->name, data);
mnt = alloc_vfsmnt(name);调用mnt_alloc_id()为该vfsmount对象分配一个标识符,并设置vfsmount对象的标识符字段mnt_id。
INIT_LIST_HEAD(&mnt->mnt_hash);
INIT_LIST_HEAD(&mnt->mnt_child);
INIT_LIST_HEAD(&mnt->mnt_mounts);
INIT_LIST_HEAD(&mnt->mnt_list);
INIT_LIST_HEAD(&mnt->mnt_expire);
INIT_LIST_HEAD(&mnt->mnt_share);
INIT_LIST_HEAD(&mnt->mnt_slave_list);
INIT_LIST_HEAD(&mnt->mnt_slave);
mount_fs(type, flags, name, data);
struct dentry *root;
root = type->mount(type, flags, name, data);
root = type->mount(type, flags, name, data);
proc_mount(struct file_system_type *fs_type,int flags, const char *dev_name, void *data)
sget(fs_type, proc_test_super, proc_set_super, ns);
if (test) //proc_test_super
list_for_each_entry(old, &type->fs_supers, s_instances)
if (!s)
alloc_super(type);
err = set(s, data);//proc_set_super
struct pid_namespace *ns = (struct pid_namespace *)data;
sb->s_fs_info = get_pid_ns(ns);
s->s_type = type;
list_add_tail(&s->s_list, &super_blocks);
list_add(&s->s_instances, &type->fs_supers);
sb->s_flags = flags;
err = proc_fill_super(sb);
struct inode * root_inode;
s->s_flags |= MS_NODIRATIME | MS_NOSUID | MS_NOEXEC;s->s_blocksize = 1024;s->s_blocksize_bits = 10;s->s_magic = PROC_SUPER_MAGIC;s->s_op = &proc_sops;s->s_time_gran = 1;root_inode = proc_get_inode(s, &proc_root);s->s_root = d_alloc_root(root_inode);struct proc_dir_entry proc_root = {.low_ino = PROC_ROOT_INO,.namelen = 5,.mode = S_IFDIR | S_IRUGO | S_IXUGO,.nlink = 2,.count = ATOMIC_INIT(1),.proc_iops = &proc_root_inode_operations,.proc_fops = &proc_root_operations,.parent = &proc_root,.name = "/proc",};
static const struct inode_operations proc_root_inode_operations = {.lookup = proc_root_lookup,.getattr = proc_root_getattr,};static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentry, struct nameidata *nd){if (!proc_lookup(dir, dentry, nd)) {return NULL;}return proc_pid_lookup(dir, dentry, nd);}static const struct file_operations proc_root_operations = {.read = generic_read_dir,.readdir = proc_root_readdir,.llseek = default_llseek,};proc_root_readdir
if (nr < FIRST_PROCESS_ENTRY) {int error = proc_readdir(filp, dirent, filldir);}ret = proc_pid_readdir(filp, dirent, filldir);
ns = filp->f_dentry->d_sb->s_fs_info;
iter.task = NULL;
iter.tgid = filp->f_pos - TGID_OFFSET;for (iter = next_tgid(ns, iter);iter.task;iter.tgid += 1, iter = next_tgid(ns, iter)) {filp->f_pos = iter.tgid + TGID_OFFSET;if (proc_pid_fill_cache(filp, dirent, filldir, iter) < 0) {put_task_struct(iter.task);goto out;}}next_tgid
iter.task = NULL;pid = find_ge_pid(iter.tgid, ns);
struct pid *pid;do {pid = find_pid_ns(nr, ns);if (pid)break;nr = next_pidmap(ns, nr);} while (nr > 0);
if (pid) {
iter.tgid = pid_nr_ns(pid, ns);iter.task = pid_task(pid, PIDTYPE_PID);get_task_struct(iter.task);}
Struct proc_dir_entry定义
struct proc_dir_entry {unsigned short low_ino; /*保存对应inode的低16位的数值*/unsigned short namelen; /*名字长度*/
const char *name; /*节点名字*/mode_t mode; /*节点的属性,如是否目录,可读等*/nlink_t nlink; /*链接数*/uid_t uid; /*用户标识*/gid_t gid; /*用户组标识*/unsigned long size; /*一般为0*/struct inode_operations * ops; /*对应inode的inode操作函数指针*/int (*get_info)(char *, char **, off_t, int, int); /*取系统信息的函数,在net中有实例*/void (*fill_inode)(struct inode *, int); /*填写对应的inode信息*/struct proc_dir_entry *next, *parent, *subdir; /*兄弟指针,父指针,子目录指针*/void *data;int (*read_proc)(char *page, char **start, off_t off, int count, int *eof, void *data);int (*write_proc)(struct file *file, const char *buffer, unsigned long count, void *data);int (*readlink_proc)(struct proc_dir_entry *de, char *page);unsigned int count; /* use count */int deleted; /* delete flag */};
proc_mkdir("fs", NULL);
proc_mkdir_mode(name, S_IRUGO | S_IXUGO, parent);
__proc_create(&parent, name, S_IFDIR | S_IRUGO | S_IXUGO, 2);
struct proc_dir_entry *ent = NULL;
kmalloc(sizeof(struct proc_dir_entry) + len + 1, GFP_KERNEL);
memset(ent, 0, sizeof(struct proc_dir_entry));
memcpy(ent->name, fn, len + 1);
ent->namelen = len;
ent->mode = mode;
ent->nlink = nlink;
atomic_set(&ent->count, 1);
ent->pde_users = 0;
spin_lock_init(&ent->pde_unload_lock);
ent->pde_unload_completion = NULL;
INIT_LIST_HEAD(&ent->pde_openers);
proc_register(proc_register(parent, ent)
i = get_inode_number();
dp->low_ino = i;
if (S_ISDIR(dp->mode)) {
if (dp->proc_iops == NULL) {dp->proc_fops = &proc_dir_operations;dp->proc_iops = &proc_dir_inode_operations;}dir->nlink++;} else if (S_ISLNK(dp->mode)) {if (dp->proc_iops == NULL)dp->proc_iops = &proc_link_inode_operations;} else if (S_ISREG(dp->mode)) {if (dp->proc_fops == NULL)dp->proc_fops = &proc_file_operations;if (dp->proc_iops == NULL)dp->proc_iops = &proc_file_inode_operations;}dp->next = dir->subdir;dp->parent = dir;dir->subdir = dp;
proc_mkdir("driver", NULL);
proc_mkdir("bus", NULL);
proc_sys_init()