Linux open系統呼叫 一

2021-08-28 15:03:45 字數 2746 閱讀 9586

注:本文分析基於3.10.0-693.el7核心版本,即centos 7.4

int open(const char *pathname, int flags);

int open(const char *pathname, int flags, mode_t mode);

引數說明:

pathname:表示要開啟的檔案路徑,可以是絕對路徑也可以是相對路徑;

flags:表示開啟檔案所採用的操作,用於控制可讀、可寫、建立、截斷等

注:以下模式有且只能指定其中乙個

o_rdonly:唯讀模式開啟

o_wronly:只寫模式開啟

o_rdwr:可讀可寫開啟

指定讀寫模式後還能位與一些其他控制標誌,來控制開啟的操作。

o_creat:表示如果指定檔案不存在,則建立這個檔案

o_trunc:表示截斷,如果檔案存在,則將其長度截斷為0

o_nonblock:表示將 i/o設定為非阻塞模式(nonblocking mode)

以上為常用選項,具體可參考man page使用者手冊。

mode:表示設定檔案訪問許可權的初始值,可按位與,s_irwxu、s_irusr、s_iwusr等選項,實際檔案許可權還受umask值影響。

總的來說,open()函式所做的事情就是將傳進去的字串的路徑在核心裡面轉換成相應的inode節點和dentry結構體。執行這一任務的標準過程就是分析路徑名並把它拆分成乙個檔名序列,除了最後乙個檔名以外,所有的檔名都必定是目錄。

syscall_define3(open, const char __user *, filename, int, flags, umode_t, mode)

long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode)

else

} putname(tmp);

} return fd;//返回可用的檔案描述符

}

可見,open系統呼叫在**結構上顯得和簡潔直觀,獲取檔案描述符fd->構建file結構體並和需要開啟的檔案關聯->關聯fd和file結構->返回檔案描述符fd。這一流程的重點在於構建file結構體並和需要開啟的檔案關聯,因為這涉及了檔案系統相關操作,正因如此,我們才要來細細分析。

struct file *do_filp_open(int dfd, struct filename *pathname,

const struct open_flags *op, int flags)

進入path_openat()之前,我們先來看看struct nameidata這個結構體,它用於儲存本次查詢的結果,因此在逐級查詢目錄項的過程中不斷變化,是乙個中間量。不過定義的nd這個變數最終目的就是儲存使用者所要開啟檔案的最後乙個目錄項的資訊。

struct nameidata ;
其中目錄項的型別有以下幾種,

last_norm:最後乙個分量是普通檔名

last_root:最後乙個分量是「/」

last_dot:最後乙個分量是「.」

last_dotdot:最後乙個分量是「..」

了解了struct nameidata,那我們回過頭來看path_openat函式。

static struct file *path_openat(int dfd, struct filename *pathname,

struct nameidata *nd, const struct open_flags *op, int flags)

在逐級查詢目錄項之前,首先得確定起始目錄,根據使用者傳入的引數,檔案路徑可能是絕對路徑,也可能是相對路徑,因此需要先通過path_init函式處理,說白了也就是設定nd->path的值。

static int path_init(int dfd, const char *name, unsigned int flags,

struct nameidata *nd, struct file **fp)

nd->root.mnt = null;

nd->m_seq = read_seqbegin(&mount_lock);

if (*name=='/') else

nd->path = nd->root;//設定起始遍歷路徑nd->path為根檔案系統

} else if (dfd == at_fdcwd) while (read_seqcount_retry(&fs->seq, seq));

} else

} else

} nd->path = f.file->f_path;//獲取到路徑

if (flags & lookup_rcu) else

} //當前目錄項對應的inode

nd->inode = nd->path.dentry->d_inode;

return 0;

}

設定好遍歷的起始目錄後,就可以開始真正的遍歷目錄了,我們下篇文章再繼續分析。

Linux系統呼叫列表(一)

fork 建立乙個新程序 clone 按指定條件建立子程序 execve 執行可執行檔案 exit 中止程序 exit 立即中止當前程序 getdtablesize 程序所能開啟的最大檔案數 getpgid 獲取指定程序組標識號 setpgid 設定指定程序組標誌號 getpgrp 獲取當前程序組標...

read系統呼叫,mmap系統呼叫

read系統呼叫,mmap系統呼叫 2012 07 23 09 54 28 分類 linux 標籤 linux 檔案系統 虛擬記憶體 儲存系統 字型大小 訂閱 一般情況下,操作檔案既可以使用標準i o,也可直接使用系統呼叫。兩者有何區別呢?在輸入輸出中,直接使用底層的系統呼叫效率是非常低的,為什麼?...

Linux open 乙個函式,兩個函式原型

open 在手冊中有兩個函式原型,如下所示 int open const char pathname,int flags int open const char pathname,int flags,mode t mode 這樣的函式原型有些違背了我們的直覺。c語言是不支援函式過載的,為什麼 ope...