Linux中的fopen()和open()是什麼?


在Linux作業系統中,fopen()和open()函式的主要區別在於,open()函式是一個低階呼叫,而fopen()函式在被呼叫時會在後臺簡單地呼叫open()函式,並直接返回一個檔案指標。

open()函式的呼叫包括呼叫其他幾個函式,整個過程的行為在下面作為一個參考,以便更好地理解open()函式。

考慮以下程式碼:

int sys_open(const char *filename, int flags, int mode) {
   char *tmp = getname(filename);
   int fd = get_unused_fd();
   struct file *f = filp_open(tmp, flags, mode);
   fd_install(fd, f);
   putname(tmp);
   return fd;
}

上述程式碼也可以在你的Linux機器上的fs/open.c檔案中找到。

現在,我們可以看到,這個函式呼叫了許多其他函式,例如第一個函式名為getname(),我們向其中傳遞檔名作為引數,getname()函式的程式碼如下:

#define __getname() kmem_cache_alloc(names_cachep, SLAB_KERNEL)
#define putname(name) kmem_cache_free(names_cachep, (void *)(name))

char *getname(const char *filename) {
   char *tmp = __getname(); /* allocate some memory */
   strncpy_from_user(tmp, filename, PATH_MAX + 1);
   return tmp;
}

上述程式碼可以在**fs/namei.c**檔案中找到,其主要用途是從使用者空間複製檔名並將其傳遞到核心空間。然後,在getname()函式之後,我們有get_unused_fd()函式,它返回一個未使用的檔案描述符,它只不過是一個可增長的當前開啟檔案列表中的整數索引。get_unused_fd()函式的程式碼如下:

int get_unused_fd(void) {
   struct files_struct *files = current->files;
   int fd = find_next_zero_bit(files->open_fds, files->max_fdset, files->next_fd);
   FD_SET(fd, files->open_fds); /* in use now */
   files->next_fd = fd + 1;
   return fd;
}

現在我們有filp_open()函式,其實現如下:

struct file *filp_open(const char *filename, int flags, int mode) {
   struct nameidata nd;
   open_namei(filename, flags, mode, &nd);
   return dentry_open(nd.dentry, nd.mnt, flags);
}

上述函式起著兩個關鍵作用:首先,它使用檔案系統查詢與傳入路徑的檔名對應的inode。接下來,如果它建立一個包含所有關於inode的基本資訊的struct file,然後返回該檔案。

現在,呼叫棧中的下一個函式是fd_install()函式,它可以在include/linux/file.h檔案中找到。它用於儲存filp_open()函式返回的資訊。fd_install()函式的程式碼如下:

void fd_install(unsigned int fd, struct file *file) {
   struct files_struct *files = current->files;
   files->fd[fd] = file;
}

然後我們有store()函式,它儲存從filp_open()函式返回的結構體,然後將該結構體安裝到程序的開啟檔案列表中。

下一步是釋放已分配的核心控制記憶體塊。最後,它返回檔案描述符,然後可以將其傳遞給其他C函式,例如close(),write()等。

更新於:2021年7月31日

5K+ 次瀏覽

開啟你的職業生涯

透過完成課程獲得認證

開始學習
廣告
© . All rights reserved.