一、源码分析:
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_crea te (&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)创建设备号
sta      ti    c inline dev_t new_decode_dev(u32 dev) 
 { 
 unsigned major = (dev & 0xfff00) >> 8; 
 unsigned      mi    nor = (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_opera TI ons jfs_dir_inode_opera TI ons
中的.mknod = jfs_mknod,
sta   TI  c 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_opera TI on的i_fop和设备号i_rdev
 





