新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > linux內核中的文件描述符(一)--基礎知識簡介

linux內核中的文件描述符(一)--基礎知識簡介

作者: 時間:2016-11-22 來源:網(wǎng)絡 收藏
Kernel version:2.6.14

CPU architecture:ARM920T

本文引用地址:http://m.butianyuan.cn/article/201611/319997.htm

Author:ce123(http://blog.csdn.net/ce123)

作為文件的使用者,進程理所當然的要將所使用的文件記錄于自己的控制塊中,也就是task_struct。另外,由于進程所對應的程序也是一個文件,因此進程控制塊還必須記錄這個文件的相關信息。由于OS要對所有進程提供服務,因此OS還要維護一個記錄所有進程打開的文件的總表。

1.文件對象

當進程通過open系統(tǒng)調用打開一個文件時,該系統(tǒng)調用找到這個文件后,會把文件封裝到一個file結構的實例中提供給進程,這個實例稱為file對象。file結構的定義如下:

[plain]view plaincopy
print?
  1. structfile{
  2. structlist_headf_list;//所有打開文件的鏈表
  3. structdentry*f_dentry;//文件的dentry
  4. structvfsmount*f_vfsmnt;//文件目錄的VFS安裝點指針
  5. structfile_operations*f_op;//指向文件操作函數(shù)集的指針
  6. atomic_tf_count;//記錄訪問本文件的進程數(shù)目的計數(shù)器
  7. unsignedintf_flags;//訪問類型
  8. mode_tf_mode;//訪問模式
  9. loff_tf_pos;//文件當前的讀寫位置
  10. structfown_structf_owner;
  11. unsignedintf_uid,f_gid;//文件所有者ID和用戶組ID
  12. structfile_ra_statef_ra;
  13. unsignedlongf_version;
  14. void*f_security;
  15. /*neededforttydriver,andmaybeothers*/
  16. void*private_data;
  17. #ifdefCONFIG_EPOLL
  18. /*Usedbyfs/eventpoll.ctolinkallthehookstothisfile*/
  19. structlist_headf_ep_links;
  20. spinlock_tf_ep_lock;
  21. #endif/*#ifdefCONFIG_EPOLL*/
  22. structaddress_space*f_mapping;
  23. structrcu_headf_rcuhead;
  24. };

結構中的域f_uid為文件所有者的ID,f_gid為文件所有者所在組的ID。這樣就使得一個文件可能面臨三種用戶的訪問:

  • 文件所有者;
  • 同組用戶;
  • 其他用戶。

內核在處理一個進程或用戶訪問一個文件的請求時,要根據(jù)進程的f_uid和f_gid以及訪問模式來確定該進程是否具有訪問這個文件的權限。對于一個用戶來說,可以有讀、寫和執(zhí)行三種文件權限,這三種權限和三種用戶就共有9中組合,即文件的訪問權限可以用9個bit來表示,并將其保存在文件的dentry中。

結構中的域f_pos記錄了進程對文件讀寫位置的當前值,可以通過調用函數(shù)llseek進程移動。

結構中的f_op執(zhí)向結構file_operations,該結構封裝了對文件進行操作的函數(shù),定義如下:

[plain]view plaincopy
print?
  1. structfile_operations{
  2. structmodule*owner;
  3. loff_t(*llseek)(structfile*,loff_t,int);
  4. ssize_t(*read)(structfile*,char__user*,size_t,loff_t*);
  5. ssize_t(*aio_read)(structkiocb*,char__user*,size_t,loff_t);
  6. ssize_t(*write)(structfile*,constchar__user*,size_t,loff_t*);
  7. ssize_t(*aio_write)(structkiocb*,constchar__user*,size_t,loff_t);
  8. int(*readdir)(structfile*,void*,filldir_t);
  9. unsignedint(*poll)(structfile*,structpoll_table_struct*);
  10. int(*ioctl)(structinode*,structfile*,unsignedint,unsignedlong);
  11. long(*unlocked_ioctl)(structfile*,unsignedint,unsignedlong);
  12. long(*compat_ioctl)(structfile*,unsignedint,unsignedlong);
  13. int(*mmap)(structfile*,structvm_area_struct*);
  14. int(*open)(structinode*,structfile*);
  15. int(*flush)(structfile*);
  16. int(*release)(structinode*,structfile*);
  17. int(*fsync)(structfile*,structdentry*,intdatasync);
  18. int(*aio_fsync)(structkiocb*,intdatasync);
  19. int(*fasync)(int,structfile*,int);
  20. int(*lock)(structfile*,int,structfile_lock*);
  21. ssize_t(*readv)(structfile*,conststructiovec*,unsignedlong,loff_t*);
  22. ssize_t(*writev)(structfile*,conststructiovec*,unsignedlong,loff_t*);
  23. ssize_t(*sendfile)(structfile*,loff_t*,size_t,read_actor_t,void*);
  24. ssize_t(*sendpage)(structfile*,structpage*,int,size_t,loff_t*,int);
  25. unsignedlong(*get_unmapped_area)(structfile*,unsignedlong,unsignedlong,unsignedlong,unsignedlong);
  26. int(*check_flags)(int);
  27. int(*dir_notify)(structfile*filp,unsignedlongarg);
  28. int(*flock)(structfile*,int,structfile_lock*);
  29. };
從上面的代碼可以看到,結構中是一系列函數(shù)的指針,這里有我們比較熟悉的read、open、write和close等函數(shù)的指針。進程就是通過這些函數(shù)訪問一個文件的,file_operations是linux虛擬文件系統(tǒng)VFS和進程之間的接口。

2.文件描述符

下面進一步介紹進程對自己所訪問的file對象的管理方法。linux中使用一個數(shù)組來管理進程打開的文件的file對象,數(shù)組中的每個元素都存放一個紙箱進程所打開的文件的file對象。既然用一個數(shù)組來存放file對象,那么用數(shù)組的下標來訪問文件就是一件順理成章的方法,于是,linux就把數(shù)組元素的下標叫做該數(shù)組元素所對應的文件的文件描述符,該描述符就是系統(tǒng)對文件的標識,這個數(shù)組也叫文件描述符數(shù)組,如下圖所示:

內核通過系統(tǒng)調用dup、dup2和fctl可以使數(shù)組中的多個元素指向同一個文件的file對象,也就是說,在linux中,同一個文件可以有多個文件描述符。

3.進程打開文件表

進程描述符數(shù)組中存放了一個進程所訪問的所有文件,把這個文件描述符數(shù)組和這個數(shù)組在系統(tǒng)中的一些動態(tài)信息組合到一起,就形成了一個新的數(shù)據(jù)結構——進程打開文件表,即file_struct,其定義如下:

[plain]view plaincopy
print?
  1. /*
  2. *Openfiletablestructure
  3. */
  4. structfiles_struct{
  5. atomic_tcount;//引用計數(shù)
  6. spinlock_tfile_lock;/*Protectsallthebelowmembers.Nestsinsidetsk->alloc_lock*/
  7. structfdtable*fdt;//管理文件描述符
  8. structfdtablefdtab;//管理文件描述符
  9. fd_setclose_on_exec_init;//位圖
  10. fd_setopen_fds_init;//位圖
  11. structfile*fd_array[NR_OPEN_DEFAULT];//文件描述符數(shù)組
  12. };
顯然,這個結構應該屬于進程的私有數(shù)據(jù),所以進程控制塊task_struct用指針files指向它。

[plain]view plaincopy
print?
  1. structtask_struct{
  2. ...
  3. /*openfileinformation*/
  4. structfiles_struct*files;
  5. ...
  6. };
進程與其打開文件之間的關系如下圖所示。

4.文件描述符的管理

file_struct中的fdt和fdtab用于管理文件文件描述符,一個是fdtable類型,另一個是其指針類型。fdtable的定義如下:

[plain]view plaincopy
print?
  1. structfdtable{
  2. unsignedintmax_fds;//可以代開的最大文件數(shù)
  3. intmax_fdset;//位圖的最大長度
  4. intnext_fd;//下一個可用的fd
  5. structfile**fd;/*currentfdarray指向files_struct的fd_array*/
  6. fd_set*close_on_exec;
  7. fd_set*open_fds;//打開的文件標記,比如第2位為0,則打開了2號文件
  8. structrcu_headrcu;
  9. structfiles_struct*free_files;
  10. structfdtable*next;
  11. };

下圖可以很直觀的說明文件描述符fd的管理。




評論


技術專區(qū)

關閉