fxx

Linux内核写文件流程

7月 29th, 2013 | Filed under FileSystem
 

接上篇Linux内核读文件流程,写这篇Linux内核写文件流程。文中涉及的内核代码版本是linux内核版本号:3.0.13-0.27 sles11sp2版本。

用户态write函数到内核态的调用是:

 

 

SYSCALL_DEFINE3调用的vfs_write,vfs_write调用rw_verify_area检查当前是否有写权限,然后调用虚拟文件系统(vfs)的f_op指针write函数。f_op指针write函数在ext3_file_operations中定义的,定义为do_sync_write。

 

 

在write中函数定义了iov和kiocb,调用aio_write完成数据写入,aio_write是在ext3_file_operations中定义为generic_file_aio_write;然后等待wait_on_retry_sync_kiocb将数据刷新到磁盘。

 

 

generic_file_aio_write同样在开始检查各种锁等控制开关,直接通过__generic_file_aio_write将功能实现,但大部分检查是在__generic_file_aio_write里面测试的,如vfs_check_frozen检查文件系统是否有冻僵(不能写入),generic_write_checks权限块设备等检查。文件的修改时间也是在此处刷新的:file_update_time。然后检查是否有直接写入(O_DIRECT)的参数,O_DIRECT部分后面再说,如果没有则是generic_file_buffered_write,最后进入到generic_perform_write.

generic_perform_write也是文件写入的主要完成部分,整个部分是由一个do{}while循环完成的。首先是通过write_begin函数进行一些预处理工作,具体指向ext3_write_begin函数。ext3_write_begin首先用grab_cache_page_write_begin获取页高速缓存,调用__block_write_begin,在其中用get_block获取物理块号,同时启用journal机制。

当write_begin已经完成的时候,将用户态数据拷贝到内核态的page上。

 

 

通过write_end完成具体写入,由于ext3的journal有3中不同的写入方式,此处介绍默认的order方式,ext3_ordered_write_end函数首先调用block_write_end函数,其中调用__block_commit_write提交写入的数据,但事实上其提交只是对buff的状态做了处理,并没有其他大的操作。

 

 

而后的walk_page_buffers只是通过journal_dirty_data_fn利用journal机制将数据标记为脏,然后用update_file_sizes更新文件所属inode的属性,并置为脏。

 

 

此时将inode添加到孤儿链表中,具体介绍见链接。

 

 

事实上前面都没有做刷新磁盘的操作,最后还是回到generic_perform_write函数,有balance_dirty_pages_ratelimited函数,顾名思义,平衡脏页比率,在此处进行脏页的刷新。另外一篇文章有详细介绍,点击Linux缓存写回机制

如此才完成了文件的写入过程。

—结束—

 

posted on 2016-10-27 20:38  fxx  阅读(323)  评论(0)    收藏  举报