proc sys

本文深入探讨了Linux内核中Proc文件系统的实现原理和技术细节,包括其数据结构、挂载过程及目录条目创建机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  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);
                        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()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值