• linux之mknod


    一、源码分析:

      mknod->系统调用->

    /fs/namei.c

    SYSCALL_DEFINE3(mknod, const char __user *, filename, int, mode, unsigned, dev)
    {
       return sys_mknodat(AT_FDCWD, filename, mode, dev);
    }

    SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, int, mode, unsigned, dev)
    {
      int error;
      char *tmp;
      struct dentry *dentry;
      struct nameidata nd;

      ...

      error = user_path_parent(dfd, filename, &nd, &tmp);

      ...

      dentry = lookup_create(&nd, 0);

      ...
      if (!IS_POSIXACL(nd.path.dentry->d_inode)) mode &= ~current_umask();
      error = may_mknod(mode);

      ...
      error = mnt_want_write(nd.path.mnt);
      ...
      error = security_path_mknod(&nd.path, dentry, mode, dev);
      ...
      switch (mode & S_IFMT)

      {
        case 0: case S_IFREG:
          error = vfs_create(nd.path.dentry->d_inode,dentry,mode,&nd);
          break;
        case S_IFCHR: case S_IFBLK:
          error = vfs_mknod(nd.path.dentry->d_inode, dentry, mode, new_decode_dev(dev));
          break;
        case S_IFIFO: case S_IFSOCK:
          error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,0);
          break;
      }
      ...
    }

    使用new_decode_dev(dev)创建设备号

    static inline dev_t new_decode_dev(u32 dev)
    {
      unsigned major = (dev & 0xfff00) >> 8;
      unsigned minor = (dev & 0xff) | ((dev >> 12) & 0xfff00);
      return MKDEV(major, minor);
    }

    includelinux ypes.h 

    typedef __kernel_dev_t  dev_t;

    typedef __u32 __kernel_dev_t;

    vfs_create():用于普通文件创建

    vfs_mkdir():用于目录节点创建

    vfs_mknod():用于特殊文件(FIFO、插口、字符设备文件、块设备文件)创建

    /proc目录下的特殊文件,则由内核生成,非用户创建。

    int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
    {
      int error = may_create(dir, dentry);

      ...

      if ((S_ISCHR(mode) || S_ISBLK(mode)) && !ns_capable(inode_userns(dir), CAP_MKNOD)) return -EPERM;

      ...

      error = devcgroup_inode_mknod(mode, dev);

      error = security_inode_mknod(dir, dentry, mode, dev);

      error = dir->i_op->mknod(dir, dentry, mode, dev);

      ...

    }

    dir : innode结构指针,指向待创建设备文件的父节点,由path_walk()找到的。

    dentry:指向代表着或将要代表待创建设备文件节点的目录项dentry结构,sys_mknod中lookup_create在内核dentry结构杂凑表中找到或创建

    vfs_mknod是虚拟文件系统的mknod

    下面还有诸如ext2、ext3、ext4、jffs、yaffs等实际文件系统,对应struct inode_operations jfs_dir_inode_operations

    中的.mknod  = jfs_mknod,

    static int jfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
    {
      ...
      struct inode *ip;

      ...

      ip = ialloc(dir, mode);

      ...
      init_special_inode(ip, ip->i_mode, rdev);

      ...
    }

    ialloc分配inode结构体,init_special_inode进行填充

    /fs/inode.c 

    void init_special_inode(struct inode *inode, umode_t mode, dev_t rdev)
    {
      inode->i_mode = mode;
      if (S_ISCHR(mode)) //字符设备

      {
        inode->i_fop = &def_chr_fops;
        inode->i_rdev = rdev;
      }

      else if (S_ISBLK(mode)) //块设备

      {
        inode->i_fop = &def_blk_fops;
        inode->i_rdev = rdev;
      }

      else if (S_ISFIFO(mode))//FIFO流设备
        inode->i_fop = &def_fifo_fops;
      else if (S_ISSOCK(mode))//网络设备
        inode->i_fop = &bad_sock_fops;
      else//未知设备提示
        printk(KERN_DEBUG "init_special_inode: bogus i_mode (%o) for inode %s:%lu ", mode, inode->i_sb->s_id,inode->i_ino);
    }
    EXPORT_SYMBOL(init_special_inode);

    函数设置file_operation的i_fop和设备号i_rdev

  • 相关阅读:
    bzoj 4017: 小Q的无敌异或
    [TJOI2014] Alice and Bob
    [TJOI2014] 上升子序列
    bzoj 3261: 最大异或和
    bzoj3087: Coci2009 misolovke
    bzoj3521: [Poi2014]Salad Bar
    bzoj4032: [HEOI2015]最短不公共子串
    bzoj1027: [JSOI2007]合金
    bzoj4637: 期望
    bzoj3919: [Baltic2014]portals
  • 原文地址:https://www.cnblogs.com/pokerface/p/6542392.html
Copyright © 2020-2023  润新知