在内核想对一个文件中的数据用二分法查找。二分法查找的输入是需要一个长度做二分的。对文件而言就是文件长度了。于是想到了内核中用seek函数,实现对文件中内容的二分法查找。
seek在内核中是怎么实现的呢?
直接想到了在内核中找了file_operations的实现于是
在Fs.h中发现了file_operations
struct file_operations {
struct module *owner;
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
..........
};
其中只看到了llseek();
说明llseek();是seek簇函数的最终实现。
分析loff_t (*llseek) (struct file *, loff_t, int);
其中loff_t为 long long型:
typedef long long __kernel_loff_t; //Posix_types.h
typedef __kernel_loff_t loff_t; //Types.h
struct file* 为文件指针是由filp_open得到的。
int应该是方向
在ext3中(file.c)
const struct file_operations ext3_file_operations = {
.llseek = generic_file_llseek,
...
};
可见最终实现是generic_file_llseek,
generic_file_llsee实现在Read_write.c里
loff_t generic_file_llseek(struct file *file, loff_t offset, int origin)
{
long long retval;
struct inode *inode = file->f_mapping->host;
mutex_lock(&inode->i_mutex);
switch (origin) {
case SEEK_END:
offset += inode->i_size;
break;
case SEEK_CUR:
offset += file->f_pos;
}
retval = -EINVAL;
if (offset>=0 && offset<=inode->i_sb->s_maxbytes) {
if (offset != file->f_pos) {
file->f_pos = offset;
file->f_version = 0;
}
retval = offset;
}
mutex_unlock(&inode->i_mutex);
return retval;
}
注意其中没有显式写SEEK_SET,体会一下:)
以上就是在ext3文件系统中对用户态seek的最终实现。
回到开始的问题,
对llseek使用参数llseek(filp, 0L, SEEK_END);
返回值就是以字节为单位的文件大小。
得到了文件大小,再用llseek实现二分法查找,呵呵下面的就简单了。
阅读(1357) | 评论(0) | 转发(0) |