一、背景:
嵌入式设备写SD卡的时候,偶尔会出现调用write卡顿,内核linux-3.4.y
二、linux内核io流程
1. 应用程序调用write,陷入内核执行vfs_write函数,将数据写入页高速缓存(每个缓存页包含若干个缓冲区)。而在写入之前需要(1)检查页是否在回写,如果正在回写则挂起进程,等待回写标志清空时唤醒进程;(2)检查页buffer是否locked,如果locked则挂起进程等待唤醒
2. 内核有一个常驻线程,为每个bdi创建一个线程,定时检查是否需要回写,需要则提交bio,让驱动写入sd卡
3. bio结束时执行回调,将页回写标志清除三、相关函数分析(记录主要函数,方便跟踪源码)
三、内核代码分析
1. 写页高速缓存
(1)重要结构:
const struct file_operations fat_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
.aio_read = generic_file_aio_read,
.aio_write = generic_file_aio_write,
.mmap = generic_file_mmap,
.release = fat_file_release,
.unlocked_ioctl = fat_generic_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = fat_generic_compat_ioctl,
#endif
.fsync = fat_file_fsync,
.splice_read = generic_file_splice_read,
};
struct address_space_operations {
int (*writepage)(struct page *page, struct writeback_control *wbc);
int (*readpage)(struct file *, struct page *);
int (*sync_page)(struct page *);
int (*writepages)(struct address_space *, struct writeback_control *);
int (*set_page_dirty)(struct page *page);
int (*readpages)(struct file *filp, struct address_space *mapping,
struct list_head *