Linux内核查找文件操作函数的过程

本文介绍了Linux中文件系统的i_node初始化过程。详细解释了如何根据文件类型设置i_fop和i_op,以及sysfs文件系统如何实现自定义初始化。

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

先根据路径找到父目录项,然后找到对应的i_node,i_ndoe的成员 file_operations  *  i_fop是指向文件操作函数集的指针。

在创建文件的i_node时会设定 file_operations  *  i_fop的值。一般默认使用init_special_inode()函数进行设置,其代码如下:

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))                                               
                inode->i_fop = &pipefifo_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);                                 
}
这个函数会根据文件的类型,给i_fop赋不同值。
def_chr_fops:  字符设备文件的操作函数。
def_blk_fops:  块设备文件的操作函数。
pipefifo_fops: 管道文件的操作函数
bad_sock_fops: 网络设备文件的操作函数
另外,对于字符设备文件和块设备文件,i_node的成员i_rdev也会被赋值成rdev,这个rdev实际上是由主设备号和从设备号生成的设备号。


当然,具体的文件系统有可能会实现自己的初始化函数,比如sysfs就是使用自己的函数,如下:

static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)       
{                                                                                
        struct bin_attribute *bin_attr;                                          
                                                                                 
        inode->i_private = sysfs_get(sd);                                        
        inode->i_mapping->a_ops = &sysfs_aops;                                   
        inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;            
        inode->i_op = &sysfs_inode_operations;                                   
                                                                                 
        set_default_inode_attr(inode, sd->s_mode);                               
        sysfs_refresh_inode(sd, inode);                                          
                                                                                 
        /* initialize inode according to type */                                 
        switch (sysfs_type(sd)) {                                                
        case SYSFS_DIR:                                                          
                inode->i_op = &sysfs_dir_inode_operations;                       
                inode->i_fop = &sysfs_dir_operations;                            
                break;                                                           
        case SYSFS_KOBJ_ATTR:                                                    
                inode->i_size = PAGE_SIZE;                                       
                inode->i_fop = &sysfs_file_operations;                           
                break;                                                           
        case SYSFS_KOBJ_BIN_ATTR:                                                
                bin_attr = sd->s_bin_attr.bin_attr;                              
                inode->i_size = bin_attr->size;                                  
                inode->i_fop = &bin_fops;                                        
                break;                                                           
        case SYSFS_KOBJ_LINK:                                                    
                inode->i_op = &sysfs_symlink_inode_operations;                   
                break;                                                           
        default:                                                                 
                BUG();                                                           
        }                                                                        
                                                                                 
        unlock_new_inode(inode);                                                 
}     
该函数会根据文件类型(ktype)给i_fop和i_op赋不同值。                                                                                      
而sysfs_type(sd)的定义如下:
static inline unsigned int sysfs_type(struct sysfs_dirent *sd)
{
	return sd->s_flags & SYSFS_TYPE_MASK;
}
sysfs_dirent的成员变量sd->s_flags用于标识文件的类型,该变量在创建目录或文件对应的sysfs_dirent时进行初始化:
(1)file:
    sysfs_create_file()--->sysfs_add_file(kobj->sd, attr, SYSFS_KOBJ_ATTR)--->sysfs_add_file_mode()--->sysfs_new_dirent()
 (2) dir:
    sysfs_create_dir()--->create_dir--->sysfs_new_dirent(name, mode, SYSFS_DIR)
	
  在创建文件和目录的过程中都会调用sysfs_new_dirent()去创建sysfs_dirent,其源码如下:
  
struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type)
{
	char *dup_name = NULL;
	struct sysfs_dirent *sd;

	if (type & SYSFS_COPY_NAME) {
		name = dup_name = kstrdup(name, GFP_KERNEL);
		if (!name)
			return NULL;
	}

	sd = kmem_cache_zalloc(sysfs_dir_cachep, GFP_KERNEL);
	if (!sd)
		goto err_out1;

	if (sysfs_alloc_ino(&sd->s_ino))
		goto err_out2;

	atomic_set(&sd->s_count, 1);
	atomic_set(&sd->s_active, 0);

	sd->s_name = name;
	sd->s_mode = mode;
	sd->s_flags = type | SYSFS_FLAG_REMOVED;

	return sd;

 err_out2:
	kmem_cache_free(sysfs_dir_cachep, sd);
 err_out1:
	kfree(dup_name);
	return NULL;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值