1. 程式人生 > >Linux VFS中write系統呼叫實現原理

Linux VFS中write系統呼叫實現原理

目錄

WORD裡面的目錄複製過來似乎不能直接用。。還是放在這裡當主線看吧..

使用者空間的write函式在核心裡面的服務例程為sys_write

[email protected] ~]# grep write /usr/include/asm/unistd_64.h

#define __NR_write1

__SYSCALL(__NR_write, sys_write)

#define __NR_pwrite6418

__SYSCALL(__NR_pwrite64, sys_pwrite64)

#define __NR_writev20

__SYSCALL(__NR_writev, sys_writev)

#define __NR_pwritev296

__SYSCALL(__NR_pwritev, sys_pwritev)

#define __NR_process_vm_writev311

__SYSCALL(__NR_process_vm_writev, sys_process_vm_writev)

這裡根據經驗判斷,通常write呼叫應該是sys_write,這裡我們討論sys_write函式的核心實現

SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf,size_t, count)

{

{//這裡SYSCALL_DEFINE3 write

sys_write的轉換請參看前面的文章

//這裡unsigned int fd表示使用者空間的檔案描述符

//char __user *buf是存放從檔案讀取內容的一個使用者空間記憶體區

struct file *file;

ssize_t ret = -EBADF;

int fput_needed;

file = fget_light(fd, &fput_needed);

if (file) {

loff_t pos = file_pos_read(file);

ret = vfs_write(file, buf, count, &pos);

file_pos_write(file, pos);

fput_light(file, fput_needed);

}

return ret;

}

可以看到,和sys_read系統呼叫不同的地方就是這裡呼叫了vfs_write函式來完成寫操作,所以這裡我們只看vfs_write都做了什麼,其餘部分請參看

Vfs_write函式實現原理

ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_t *pos)

即把使用者空間的char __user* buf指向的記憶體地址裡面的內容寫入相應的裝置檔案

基本同vfs_read,不過這裡變成了

如果檔案系統沒有實現file_operation或者既沒有實現file_operation->write,也沒有實現file_operation->aio_write,則報錯。(即檔案系統即沒有實現同步寫,也沒有實現非同步寫,那就報錯返回錯誤了)

如果檔案系統實現了file->file_operation->write(還記得我嗎在open系統呼叫中講到的嗎,在open系統呼叫中file->file_operation設定為了inode->file_operation)函式,則呼叫它來完成。

否則(說明檔案系統沒有實現write,但是實現了file_operation->aio_write)呼叫核心的預設函式do_sync_write(file, buf, count, pos);來做同步讀寫操作;而核心的do_sync_write函式內部實現是

ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos){

struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = len };

for (;;) {

ret = filp->f_op->aio_write(&kiocb, &iov, 1, kiocb.ki_pos);

if (ret != -EIOCBRETRY)

break;

wait_on_retry_sync_kiocb(&kiocb);

}

}

這裡和do_sync_read不同在於基本也就aio_read換成了aio_write了,do_sync_write最後呼叫的是file_operation->aio_write方法,但是iov陣列長度為1,並且寫入過程中如果寫入操作沒有完成則顯式呼叫程序排程函式,本程序可能被掛起來且程序狀態為TASK_UNINTERRUPTIBLE。直到最終寫入完成,讀取成功後進程狀態會變為TASK_RUNNING,且存放在使用者空間的buf記憶體區的內容已經寫入硬體上為止

參考:kernel 3.6.7

<script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script> 閱讀(188) | 評論(0) | 轉發(0) | 給主人留下些什麼吧!~~ 評論熱議

相關推薦

Linux VFSwrite系統呼叫實現原理

目錄 WORD裡面的目錄複製過來似乎不能直接用。。還是放在這裡當主線看吧.. 使用者空間的write函式在核心裡面的服務例程為sys_write [email protected]

Linux fsync和fdatasync系統呼叫實現分析(Ext4檔案系統

參考:https://blog.csdn.net/luckyapple1028/article/details/61413724 在Linux系統中,對檔案系統上檔案的讀寫一般是通過頁快取(page cache)進行的(DirectIO除外),這樣設計的可以延時磁碟IO的操作,從而可以減少磁碟讀

Linux VFS 之mount系統呼叫

1. 我們知道,在對檔案的開啟,讀和寫操作之前,必須掛載檔案系統。那麼,核心如何掛載檔案系統,換句話說,在掛載檔案系統時核心都做了哪些事情。這是本文討論的事情。在掛載檔案系統之前,必須格式化檔案系統型別,通過mkfs命令實現。在Linux中,一個檔案系統型別包括多個檔案系統,如/dev/sda, /

linux的read和write系統呼叫

linux中read和write系統呼叫 在這裡小koala著重於read()和write()來讀寫普通檔案,因為小koala在編寫實際檔案讀寫函式時,疏忽了一些重要的地方,造成無休止的向系統中寫資料,最後系統崩潰。當時瞬間“三觀”盡毀。現在較為詳細地分析錯誤

再探Linux核心write系統呼叫操作的原子性

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

amlogic平臺android 系統linux核心新增i2c裝置實現i2c的讀寫

上一篇,我介紹瞭如何在uboot中新增i2c裝置,以及移植i2c的讀寫介面。簡單來說uboot階段使用i2c裝置和平臺關聯性比較大,但不同平臺套路是差不多的。你可以將uboot階段看作是引導androi

Linux系統呼叫實現檔案操作

系統呼叫(系統呼叫是作業系統提供給使用者程式的一組“特殊”函式介面,使用者通過這組介面獲得作業系統提供的服務)中操作I/O的函式,都是針對檔案描述符的。 通過檔案描述符可以直接對相應檔案進行操作,如:open、close、write、read、ioctl #define STDIN_FIL

系統呼叫實現Linux命令 ls -al

二話不說直接上程式碼(這是我之前在網易部落格上寫的搬過來) ls.c 如下: #include "ls.h" /**********************************************************************/ //將路徑定位到

Linux(Android)系統Root實現原理

root原理 原理概述 1. 系統漏洞方案 主旨思想是查詢系統漏洞,讓本身具有root許可權的程序執行開啟root許可權的操作。 2. 重燒eng boot.img方案 Android版本有user版本和eng版本的區別,其中eng版本可以用於開發除錯,所以本身可以開啟r

Linux 系統呼叫實現機制

1. 提示:unable to copy the source file ./installer/services.sh to the destination file /etc/init.d/vmware-tools     錯誤原因: 我的解壓包的目錄是 /mnt/cd

64位Linux系統呼叫的新增以及系統呼叫原理

使用者地址空間和核心地址空間 每個程序都會有一個固定大小的虛擬地址空間,大小較固定,視作業系統位數而定(位數同時也決定實體地址的大小)。例如32位作業系統,其實體地址也就是32位,表示的空間也就是2的32次方,即4GB。 大家都知道系統核心事關作業系統的穩定

Linuxlisten()系統呼叫的backlog引數分析

這篇文章是對上一篇部落格網路程式設計常用介面的核心實現----sys_listen()的補充,上篇文章中我說listen()系統呼叫的backlog引數既是連線佇列的長度,也指定了半連線佇列的長度(不能說等於),而不是《Unix網路程式設計》中講到的是半連線佇列和連線佇列

linux下增加一個新的系統呼叫實現pstree功能

這是我們linux課程的一個作業。 首先得到init程序的task_struct,根據list_for_each可以迴圈遍歷可以的到其所有的子程序的 list_head,根據list_head使用li

Java網絡編程和NIO詳解7:淺談 Linux NIO Selector 的實現原理

fdt 重要 文件描述 block tor create size 註冊 comm Java網絡編程和NIO詳解7:淺談 Linux 中NIO Selector 的實現原理 轉自:https://www.jianshu.com/p/2b71ea919d49 本系列文章首發於

C++多型呼叫實現原理(虛擬函式表詳解)

1.帶有虛擬函式的基類物件模型 我們先看段程式碼: #include<iostream> using namespace std; class B1 { public: void func1() {} int _b; }; class B2 { pub

基於接口回調詳解JUCCallable和FutureTask實現原理

cnblogs blog 異步編程 但是 迷糊 對象 extend href 增加 Callable接口和FutureTask實現類,是JUC(Java Util Concurrent)包中很重要的兩個技術實現,它們使獲取多線程運行結果成為可能。它們底層的實現,就是基於接口

Linux : select()詳解 和 實現原理【轉】

https://www.cnblogs.com/sky-heaven/p/7205491.html#4119169   轉自:http://blog.csdn.net/huntinux/article/details/39289317 原文:http://blog.csdn.n

套介面層之socket系統呼叫實現

這篇筆記記錄了AF_INET協議族在套介面層對scoket()系統呼叫的實現,注意這裡只介紹了套介面層的實現,相比於完整的socket()系統呼叫實現,這裡缺少兩部分內容: 檔案系統相關的部分,比如檔案描述符的分配等; 傳輸層的實現,套接字的建立肯定是要傳輸層

基於介面回撥詳解JUCCallable和FutureTask實現原理

Callable介面和FutureTask實現類,是JUC(Java Util Concurrent)包中很重要的兩個技術實現,它們使獲取多執行緒執行結果成為可能。它們底層的實現,就是基於介面回撥技術。介面回撥,許多程式設計師都耳熟能詳,這種技術被廣泛應用於非同步模組的開發中。它的實現原理並不複雜,但是對初學

STL的sort函式實現原理

STL的sort()演算法,資料量大時採用Quick Sort,分段遞迴排序。一旦分段後的資料量小於某個閾值,為避免Quick Sort的遞迴呼叫帶來過大的額外開銷,就改用Insertion Sort(插入排序)。如果遞迴層次過深,還會改用Heap Sort。 STL中的sort並非只是