Linux内核查找文件操作函数的过程
2017-06-07 11:32
288 查看
先根据路径找到父目录项,然后找到对应的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;
}
在创建文件的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;
}
相关文章推荐
- java 实现 文件操作工具集。包括文件、目录树的拷贝、删除、移动、查找等工具函数
- elf文件查找函数的过程
- 在C语言中对utmp文件进行查找和写入操作的函数小结
- Linux内核中文件操作函数整理
- 基于php常用函数总结(数组,字符串,时间,文件操作)
- .prg文件中自定义了一些过程和函数'该怎么调用?
- FileSystem对象常用的文件操作函数有哪些?
- 文件操作 API 函数介绍
- 补充:用Ms SQL Server 存储过程操作DBF文件
- c文件操作函数
- Windows API 函数学习(6)---文件操作
- c语言写的*.dbf文件的操作函数库
- C语言中关于文件操作的常用函数
- Windows API 函数学习(7)---文件操作示例
- linux 文件操作函数 通过例子来解释 父子间文件描述符共享 内存映像图
- 一个非常非常非常基础的程序,写的不好,但是一般的文件读写操作及字符处理函数都涉及到了..新手学习用的
- FSO操作文件的几个小函数(转)
- 标准文件操作函数(转载)
- 文件操作的函数
- Linux C 函数参考(文件内容操作)