一、源碼分析:
mknod->系統(tǒng)調用->
/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)創(chuàng)建設備號
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():用于普通文件創(chuàng)建
vfs_mkdir():用于目錄節(jié)點創(chuàng)建
vfs_mknod():用于特殊文件(FIFO、插口、字符設備文件、塊設備文件)創(chuàng)建
/proc目錄下的特殊文件,則由內核生成,非用戶創(chuàng)建。
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結構指針,指向待創(chuàng)建設備文件的父節(jié)點,由path_walk()找到的。
dentry:指向代表著或將要代表待創(chuàng)建設備文件節(jié)點的目錄項dentry結構,sys_mknod中l(wèi)ookup_create在內核dentry結構雜湊表中找到或創(chuàng)建
vfs_mknod是虛擬文件系統(tǒng)的mknod
下面還有諸如ext2、ext3、ext4、jffs、yaffs等實際文件系統(tǒng),對應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
?
評論
查看更多