我們常常使用系統呼叫open來開啟乙個檔案,例如:
fd = open( "/mnt/data/myfile",o_rdwr|o_creat);
下面來看看linux是如何完成的,首先是系統呼叫的**:
sys_open的源程式
view plaincopy to clipboardprint?
asmlinkage long sys_open(const char * filename, int flags, int mode)
out:
putname(tmp);
}
return fd;
out_error:
put_unused_fd(fd);
fd = error;
goto out;
} asmlinkage long sys_open(const char * filename, int flags, int mode)
out:
putname(tmp);
}return fd;
out_error:
put_unused_fd(fd);
fd = error;
goto out;
} 這裡面完成的幾個工作
1.注意到返回乙個整數fd,所以在(1)的位置獲得乙個整數fd。
2.根據路徑/mnt/data/myfile找到(或建立)檔案,並且建立乙個結構file(見(2))。
3.將整數fd和file結構指標f聯絡起來(見(3))。
注意:結構file實際上是系統開啟檔案表中的表項,目的是實現不同程序共享檔案的讀寫指標的情形。(另外一種檔案共享是不同的程序有各自的檔案讀寫指標的情形)。
檔案開啟過程的總結:
系統在程序開啟檔案表中找到乙個未使用的fd;
根據open中提供的路徑字串找到(建立)對應的dentry(從而找到inode);
建立系統開啟檔案表中的乙個開啟檔案表項(建立乙個file結構,使用指標filp指向file結構),並使該表項指向dentry(file的字段之一就是f_dentry,指向被開啟檔案在其目錄中的表項dentry);
在fd所指示的程序開啟檔案表表項中設定指向file結構的指標;
系統使用filp->f_dentry->d_inode的方式訪問磁碟inode,將其讀入記憶體中,建立對應的vnode。因此,可以認為系統開啟檔案表表項有指標指向vnode結構
進一步了解:
linux 2.6.11核心檔案io系統呼叫
linux 2.6.11核心檔案io系統呼叫
1. 引言
從事linux環境工作2年有餘,一直懵懵懂懂,1年前拜讀了《萊昂氏unix源**分析》一書,感覺自己的學習道路漫漫且修遠。最近受chinaunix的精華文帖啟發,擬將近來的部分核心呼叫分析筆記拿出來與各前輩先進共同**學習,以壯個人學習之路。
本部分主要講述的是檔案i/o操作的2.6.11核心版本實現,包括了主要的資料結構、巨集定義和函式流程。以下分別講述open,create,close,read,write,lseek系統呼叫。
2. 主要參考
《萊昂氏unix源**分析》
《unix環境高階程式設計》
www.kernel.org
3. 主要資料結構
3.1. fd
對於核心而言,所有開啟檔案都由檔案描述符引用。檔案描述符是乙個非負整數。當開啟乙個現存盤案或建立乙個新檔案時,核心向程序返回乙個檔案描述符。
當讀、寫乙個檔案時,用open或creat返回的檔案描述符標識該檔案,將其作為引數傳送給read或write。在posix.1應用程式中,檔案描述符為常數0、1和2分別代表stdin_fileno、stdout_fileno和stderr_fileno,意即標準輸入,標準輸出和標準出錯輸出,這些常數都定義在標頭檔案
// 如果不是32位處理器,則增加大檔案標識
#if bits_per_long != 32
flags |= o_largefile;
#endif
// 為了提高使用效率,在使用之前先將檔名拷貝到核心資料區。見3.2.2說明
tmp = getname(filename);
// 獲取到返回值,如果出錯,則返回,否則執行開啟操作。
fd = ptr_err(tmp);
if (!is_err(tmp))
out:
// 釋放getname分配的記憶體空間
putname(tmp);
}return fd;
out_error:
// 將檔案表指標返回到程序的檔案表中,並返回錯誤**。
put_unused_fd(fd);
fd = error;
goto out;
}4.2.3. sys_open子函式getname
getname函式主要功能是在使用檔名之前將其拷貝到核心資料區,正常結束時返回核心分配的空間首位址,出錯時返回錯誤**。其呼叫了函式do_getname來實現。
static inline int do_getname(const char __user *filename, char *page)
// 將filename拷貝len長度到page中,返回實際拷貝長度
retval = strncpy_from_user(page, filename, len);
if (retval >; 0) else if (!retval)
// filename 為空,則返回-enoent
retval = -enoent;
return retval;
}char * getname(const char __user * filename)
}// 如果前面操作成功,且audit_context不為空,則將當前檔名新增到audit列表中
if (unlikely(current->;audit_context) && !is_err(result) && result)
audit_getname(result);
// 返回處理結果
return result;
從Struts原始碼看action呼叫過程
從struts原始碼看action呼叫過程,以下 片斷來自struts1.1 struts中所有的請求都是通過actionservlet 的,乙個action請求首先會傳給actionservlet,actionservlet會將其委託給requestprocessor,requestprocess...
nginx原始碼分析 從原始碼看nginx框架總結
nginx原始碼總結 1 中沒有特別繞特別彆扭的編碼實現,從變數的定義呼叫函式的實現封裝,都非常恰當,比如從函式命名或者變數命名就可以看出來定義的大體意義,函式的基本功能,再好的架構實現在編碼習慣差的人實現也會黯然失色,如果透徹理解 的實現,領悟架構的設計初衷,覺得每塊 就想經過耐心雕琢一樣,不僅僅...
從原始碼看Handler和Looper
private looper boolean quitallowed public handler looper looper,callback callback,boolean async public inte ce callback從looper的構造方法可以看出,looper建立messag...