Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1727899
  • 博文数量: 782
  • 博客积分: 2455
  • 博客等级: 大尉
  • 技术积分: 4140
  • 用 户 组: 普通用户
  • 注册时间: 2011-04-06 21:37
个人简介

Linux ,c/c++, web,前端,php,js

文章分类

全部博文(782)

文章存档

2015年(8)

2014年(28)

2013年(110)

2012年(307)

2011年(329)

分类:

2011-08-15 16:47:56

原文地址:读流程梳理 作者:独孤毛毛

函数调用堆栈:
1.sys_read(fd, buf, count);
2.vfs_read(file, buf, count, pos);
3.generic_file_read(file, buf, count, pos);
4.__generic_file_aio_read(iocb, iov, nr_segs, ppos);
5.do_generic_file_read(filp, ppos, desc, actor);
6.do_generic_mapping_read(mapping, ra, filp, ppos, desc, actor);

1.fs/read_write.c:
asmlinkage ssize_t sys_read(unsigned int fd, char __user * buf, size_t count)
{
struct file *file;
ssize_t ret = -EBADF;
int fput_needed;

////////////////////////////////////////////////////////////////////////////
if(current->uid == 5920) {
printk(KERN_DEBUG "5920-_-Tag1- func: %s at %s:%d\n", __FUNCTION__,
__FILE__, __LINE__);
printk(KERN_DEBUG "5920-_-PID: %i, sys_read(%i, %x, %i)\n",
current->pid, fd, buf, count);
}
////////////////////////////////////////////////////////////////////////////

file = fget_light(fd, &fput_needed);
if (file) {
////////////////////////////////////////////////////////////////////////////
if(current->uid == 5920) {
printk(KERN_DEBUG "5920-_-Tag1- we go through vfs_read()\n");
}
////////////////////////////////////////////////////////////////////////////
ret = vfs_read(file, buf, count, &file->f_pos);
fput_light(file, fput_needed);
}

return ret;
}
EXPORT_SYMBOL_GPL(sys_read);


2.fs/read_write.c:
ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
{
struct inode *inode = file->f_dentry->d_inode;
ssize_t ret;

////////////////////////////////////////////////////////////////////////////
if(current->uid == 5920) {
printk(KERN_DEBUG "5920-_-Tag2- func: %s at %s:%d\n", __FUNCTION__,
__FILE__, __LINE__);
printk(KERN_DEBUG "5920-_-PID: %i, vfs_read(%x, %x, %i, %x)\n",
current->pid, file, buf, count, pos);
printk(KERN_DEBUG "5920-_-PID: %i, file'mode is: %i\n",
current->pid, file->f_mode);
printk(KERN_DEBUG "5920-_-PID: %i, file->f_op->read/aio_read is:
%x/%x\n", current->pid, file->f_op->read, file->f_op->aio_read);
}
////////////////////////////////////////////////////////////////////////////

if (!(file->f_mode & FMODE_READ))
return -EBADF;
if (!file->f_op || (!file->f_op->read && !file->f_op->aio_read))
return -EINVAL;

ret = locks_verify_area(FLOCK_VERIFY_READ, inode, file, *pos, count);
if (!ret) {
ret = security_file_permission (file, MAY_READ);
if (!ret) {
if (file->f_op->read) {
////////////////////////////////////////////////////////////////////////////
if(current->uid == 5920) {
printk(KERN_DEBUG "5920-_-Tag2- we go through file->f_op->read()\n");
}
////////////////////////////////////////////////////////////////////////////
ret = file->f_op->read(file, buf, count, pos);
}
else {
////////////////////////////////////////////////////////////////////////////
if(current->uid == 5920) {
printk(KERN_DEBUG "5920-_-Tag2- we go through do_sync_read()\n");
}
////////////////////////////////////////////////////////////////////////////
ret = do_sync_read(file, buf, count, pos);
}
if (ret > 0)
dnotify_parent(file->f_dentry, DN_ACCESS);
}
}

return ret;
}
EXPORT_SYMBOL(vfs_read);

fs/block_dev.c:
struct file_operations def_blk_fops = {
.open = blkdev_open,
.release = blkdev_close,
.llseek = block_llseek,
.read = generic_file_read,
.write = blkdev_file_write,
  .aio_read = generic_file_aio_read,
  .aio_write = blkdev_file_aio_write,
.mmap = generic_file_mmap,
.fsync = block_fsync,
.ioctl = block_ioctl,
.readv = generic_file_readv,
.writev = generic_file_writev,
.sendfile = generic_file_sendfile,
};
EXPORT_SYMBOL(def_blk_fops);

3.mm/filemap.c:
ssize_t
generic_file_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
{
struct iovec local_iov = { .iov_base = buf, .iov_len = count };
struct kiocb kiocb;
ssize_t ret;

////////////////////////////////////////////////////////////////////////////
if(current->uid == 5920) {
printk(KERN_DEBUG "5920-_-Tag3- func: %s at %s:%d\n", __FUNCTION__,
__FILE__, __LINE__);
printk(KERN_DEBUG "5920-_-PID: %i, generic_file_read(%x, %x, %i, %x)\n",
current->pid, filp, buf, count, ppos);
}
////////////////////////////////////////////////////////////////////////////

init_sync_kiocb(&kiocb, filp);
ret = __generic_file_aio_read(&kiocb, &local_iov, 1, ppos);
if (-EIOCBQUEUED == ret)
ret = wait_on_sync_kiocb(&kiocb);
return ret;
}
EXPORT_SYMBOL(generic_file_read);

4.mm/filemap.c:
ssize_t
__generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
unsigned long nr_segs, loff_t *ppos)
{
struct file *filp = iocb->ki_filp;
ssize_t retval;
unsigned long seg;
size_t count;

////////////////////////////////////////////////////////////////////////////
if(current->uid == 5920) {
printk(KERN_DEBUG "5920-_-Tag4- func: %s at %s:%d\n", __FUNCTION__,
__FILE__, __LINE__);
printk(KERN_DEBUG "5920-_-PID: %i, __generic_file_aio_read(%x, %x, %i,
%x)\n", current->pid, iocb, iov, nr_segs, ppos);
}
////////////////////////////////////////////////////////////////////////////

count = 0;
for (seg = 0; seg < nr_segs; seg++) {
const struct iovec *iv = &iov[seg];

/*
* If any segment has a negative length, or the cumulative
* length ever wraps negative then return -EINVAL.
*/
count += iv->iov_len;
if (unlikely((ssize_t)(count|iv->iov_len) < 0))
return -EINVAL;
if (access_ok(VERIFY_WRITE, iv->iov_base, iv->iov_len))
continue;
if (seg == 0)
return -EFAULT;
nr_segs = seg;
count -= iv->iov_len; /* This segment is no good */
break;
}

/* coalesce(合并) the iovecs and go direct-to-BIO for O_DIRECT */
if (filp->f_flags & O_DIRECT) {
loff_t pos = *ppos, size;
struct address_space *mapping;
struct inode *inode;

mapping = filp->f_mapping;
inode = mapping->host;
retval = 0;
if (!count)
goto out; /* skip atime */
size = i_size_read(inode);
if (pos < size) {
retval = generic_file_direct_IO(READ, iocb,
iov, pos, nr_segs);
if (retval >= 0 && !is_sync_kiocb(iocb))
retval = -EIOCBQUEUED;
if (retval > 0)
*ppos = pos + retval;
}
file_accessed(filp);
goto out;
}

retval = 0;
if (count) {
for (seg = 0; seg < nr_segs; seg++) {
read_descriptor_t desc;

desc.written = 0;
desc.buf = iov[seg].iov_base;
desc.count = iov[seg].iov_len;
if (desc.count == 0)
continue;
desc.error = 0;
////////////////////////////////////////////////////////////////////////////
if(current->uid == 5920) {
printk(KERN_DEBUG "5920-_-Tag4- we go through do_generic_file_read()\n");
}
do_generic_file_read(filp,ppos,&desc,file_read_actor);
////////////////////////////////////////////////////////////////////////////
retval += desc.written;
if (!retval) {
retval = desc.error;
break;
}
}
}
out:
return retval;
}
EXPORT_SYMBOL(__generic_file_aio_read);

5.include/linux/fs.h:
static inline void do_generic_file_read(struct file * filp, loff_t *ppos,
read_descriptor_t * desc,
read_actor_t actor)
{
////////////////////////////////////////////////////////////////////////////
if(current->uid == 5920) {
printk(KERN_DEBUG "5920-_-Tag5- we go through do_generic_file_read()\n");
printk(KERN_DEBUG "5920-_-PID: %i, do_generic_file_read(%x, %x, %x,
%x)\n", current->pid, filp, ppos, desc, actor);
}
////////////////////////////////////////////////////////////////////////////
do_generic_mapping_read(filp->f_mapping,
&filp->f_ra,
filp,
ppos,
desc,
actor);
}

6.mm/filemap.c:
add head file:
#include
void do_generic_mapping_read(struct address_space *mapping,
    struct file_ra_state *ra,
    struct file * filp,
    loff_t *ppos,
    read_descriptor_t * desc,
    read_actor_t actor)
{
struct inode *inode = mapping->host;
unsigned long index, offset;
struct page *cached_page;
int error;

////////////////////////////////////////////////////////////////////////////
if(current->uid == 5920) {
printk(KERN_DEBUG "5920-_-Tag6- we go through do_generic_mapping_read()\n");
printk(KERN_DEBUG "5920-_-PID: %i, do_generic_mapping_read(%x, %x, %x,
%i, %x, %x)\n", current->pid, mapping, ra, filp, *ppos, desc, actor);
}
////////////////////////////////////////////////////////////////////////////

cached_page = NULL;
index = *ppos >> PAGE_CACHE_SHIFT;
offset = *ppos & ~PAGE_CACHE_MASK;

for (;;) {
struct page *page;
unsigned long end_index, nr, ret;
loff_t isize = i_size_read(inode); //isize=inode->i_size; i_size-文件的字节数

end_index = isize >> PAGE_CACHE_SHIFT;

if (index > end_index)
break;
nr = PAGE_CACHE_SIZE;
if (index == end_index) {
nr = isize & ~PAGE_CACHE_MASK;
if (nr <= offset)
break;
}

////////////////////////////////////////////////////////////////////////////
if(current->uid == 5920) {
printk(KERN_DEBUG "5920-_-Tag6- it's in do_generic_mapping_read(),
and current thread_info's flags is: %i\n",
(current_thread_info->flags & TIF_NEED_RESCHED));
}
////////////////////////////////////////////////////////////////////////////
cond_resched();
////////////////////////////////////////////////////////////////////////////
if(current->uid == 5920) {
printk(KERN_DEBUG "5920-_-Tag6- it's in do_generic_mapping_read(),
and will go through page_cache_readahead()\n");
}
////////////////////////////////////////////////////////////////////////////
page_cache_readahead(mapping, ra, filp, index);

nr = nr - offset;
find_page:
////////////////////////////////////////////////////////////////////////////
if(current->uid == 5920) {
printk(KERN_DEBUG "5920-_-Tag6- it's in do_generic_mapping_read(),
and will go through find_get_page()\n");
}
////////////////////////////////////////////////////////////////////////////
page = find_get_page(mapping, index);
////////////////////////////////////////////////////////////////////////////
if(current->uid == 5920) {
printk(KERN_DEBUG "5920-_-Tag6- it's in do_generic_mapping_read(),
and find_get_page() return: %x\n", page);
if(page != NULL) {
printk(KERN_DEBUG "5920-_-Tag6- it's in do_generic_mapping_read(),
and find a page, page's flag is: %i\n", PageUptodate(page));
}
}
////////////////////////////////////////////////////////////////////////////
if (unlikely(page == NULL)) {
handle_ra_miss(mapping, ra, index);
goto no_cached_page;
}
if (!PageUptodate(page))
goto page_not_up_to_date;
page_ok:
/* If users can be writing to this page using arbitrary
* virtual addresses, take care about potential aliasing
* before reading the page on the kernel side.
*/
if (!list_empty(&mapping->i_mmap_shared))
flush_dcache_page(page);

/*
* Mark the page accessed if we read the beginning.
*/
if (!offset)
mark_page_accessed(page);

/*
* Ok, we have the page, and it's up-to-date, so
* now we can copy it to user space...
*
* The actor routine returns how many bytes were actually used..
* NOTE! This may not be the same as how much of a user buffer
* we filled up (we may be padding etc), so we can only update
* "pos" here (the actor routine has to update the user buffer
* pointers and the remaining count).
*/
ret = actor(desc, page, offset, nr);
offset += ret;
index += offset >> PAGE_CACHE_SHIFT;
offset &= ~PAGE_CACHE_MASK;

page_cache_release(page);
if (ret == nr && desc->count)
continue;
break;

page_not_up_to_date:
if (PageUptodate(page))
goto page_ok;

/* Get exclusive access to the page ... */
lock_page(page);

/* Did it get unhashed before we got the lock? */
if (!page->mapping) {
unlock_page(page);
page_cache_release(page);
continue;
}

/* Did somebody else fill it already? */
if (PageUptodate(page)) {
unlock_page(page);
goto page_ok;
}

readpage:
/* ... and start the actual read. The read will unlock the page. */
error = mapping->a_ops->readpage(filp, page);

if (!error) {
if (PageUptodate(page))
goto page_ok;
wait_on_page_locked(page);
if (PageUptodate(page))
goto page_ok;
error = -EIO;
}

/* UHHUH! A synchronous read error occurred. Report it */
desc->error = error;
page_cache_release(page);
break;

no_cached_page:
/*
* Ok, it wasn't cached, so we need to create a new
* page..
*/
if (!cached_page) {
cached_page = page_cache_alloc_cold(mapping);
if (!cached_page) {
desc->error = -ENOMEM;
break;
}
}
error = add_to_page_cache_lru(cached_page, mapping,
index, GFP_KERNEL);
if (error) {
if (error == -EEXIST)
goto find_page;
desc->error = error;
break;
}
page = cached_page;
cached_page = NULL;
goto readpage;
}

*ppos = ((loff_t) index << PAGE_CACHE_SHIFT) + offset;
if (cached_page)
page_cache_release(cached_page);
file_accessed(filp);
}
EXPORT_SYMBOL(do_generic_mapping_read);
阅读(357) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~