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);
}

include\linux\types.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\n", mode, inode->i_sb->s_id,inode->i_ino);
}
EXPORT_SYMBOL(init_special_inode);

函數設置file_operation的i_fop和設備號i_rdev


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM