最近在看write系統(tǒng)調(diào)用的實現(xiàn),雖然還有一下細節(jié)不是很清楚,但是大致的實現(xiàn)機理還是有一定的理解了。總結(jié)如下:
這里假設(shè)最普通的情況,不考慮Direct IO 的情況。從全家的高度看,要往一個文件中寫入內(nèi)容,需要一下幾步。
1. sys_write 將用戶進程要寫的內(nèi)容寫入到內(nèi)核的文件頁面緩沖中。sys_write 本身到此就結(jié)束了。
2. pdflush 內(nèi)核線程(定期或者由內(nèi)核閾值觸發(fā))刷新臟的頁面緩沖,其實只是提交IO請求給底層的驅(qū)動。
3. IO請求并不是同步執(zhí)行的,而是由底層的驅(qū)動調(diào)度執(zhí)行,發(fā)出DMA操作指令。
4. 物理IO完成之后會中斷并通知內(nèi)核,內(nèi)核負責(zé)更新IO的狀態(tài)。
先要去陪兒子睡覺了。有空會繼續(xù)細化各個部分的實現(xiàn)。
sys_write 的調(diào)用過程。(我的linux內(nèi)核版本為2.6.24,文件系統(tǒng)為ext3)
asmlinkage ssize_t sys_write(unsigned int fd, const char __user * buf, size_t count)
vfs_write(file, buf, count, &pos);
file->f_op->write(file, buf, count, pos);
這里的file->fop 是在open一個文件是初始化的函數(shù)指針,ext3文件系統(tǒng)對應(yīng)的函數(shù)為do_sync_write。
下面是其實現(xiàn)的要點。
for (;;) {
300 ret = filp->f_op->aio_write(&kiocb, &iov, 1, kiocb.ki_pos);
301 if (ret != -EIOCBRETRY)
302 break;
303 wait_on_retry_sync_kiocb(&kiocb);
304 }
305
306 if (-EIOCBQUEUED == ret)
307 ret = wait_on_sync_kiocb(&kiocb);
filp->f_op->aio_write(&kiocb, &iov, 1, kiocb.ki_pos); 是實現(xiàn)的核心,其函數(shù)指針指向ext3_file_write。
307行的作用在于等待IO的完成。這里的IO完成指的是進入IO的隊列而已,不是物理IO的完成。
generic_file_aio_write(iocb, iov, nr_segs, pos);
__generic_file_aio_write_nolock(iocb, iov, nr_segs, &iocb->ki_pos);
generic_segment_checks(iov, &nr_segs, &ocount, VERIFY_READ);
generic_file_buffered_write(iocb, iov, nr_segs, pos,ppos,count,written);
generic_file_direct_IO(WRITE, iocb, iov, pos, *nr_segs);
以下的調(diào)用序列還很長,一時還消化不了。僅供自己參考。