新聞中心

        EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > linux內(nèi)核中的文件描述符(一)--基礎(chǔ)知識(shí)簡介

        linux內(nèi)核中的文件描述符(一)--基礎(chǔ)知識(shí)簡介

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

        CPU architecture:ARM920T

        本文引用地址:http://www.104case.com/article/201611/319997.htm

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

        作為文件的使用者,進(jìn)程理所當(dāng)然的要將所使用的文件記錄于自己的控制塊中,也就是task_struct。另外,由于進(jìn)程所對應(yīng)的程序也是一個(gè)文件,因此進(jìn)程控制塊還必須記錄這個(gè)文件的相關(guān)信息。由于OS要對所有進(jìn)程提供服務(wù),因此OS還要維護(hù)一個(gè)記錄所有進(jìn)程打開的文件的總表。

        1.文件對象

        當(dāng)進(jìn)程通過open系統(tǒng)調(diào)用打開一個(gè)文件時(shí),該系統(tǒng)調(diào)用找到這個(gè)文件后,會(huì)把文件封裝到一個(gè)file結(jié)構(gòu)的實(shí)例中提供給進(jìn)程,這個(gè)實(shí)例稱為file對象。file結(jié)構(gòu)的定義如下:

        [plain]view plaincopy
        print?
        1. structfile{
        2. structlist_headf_list;//所有打開文件的鏈表
        3. structdentry*f_dentry;//文件的dentry
        4. structvfsmount*f_vfsmnt;//文件目錄的VFS安裝點(diǎn)指針
        5. structfile_operations*f_op;//指向文件操作函數(shù)集的指針
        6. atomic_tf_count;//記錄訪問本文件的進(jìn)程數(shù)目的計(jì)數(shù)器
        7. unsignedintf_flags;//訪問類型
        8. mode_tf_mode;//訪問模式
        9. loff_tf_pos;//文件當(dāng)前的讀寫位置
        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. };

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

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

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

        結(jié)構(gòu)中的域f_pos記錄了進(jìn)程對文件讀寫位置的當(dāng)前值,可以通過調(diào)用函數(shù)llseek進(jìn)程移動(dòng)。

        結(jié)構(gòu)中的f_op執(zhí)向結(jié)構(gòu)file_operations,該結(jié)構(gòu)封裝了對文件進(jìn)行操作的函數(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. };
        從上面的代碼可以看到,結(jié)構(gòu)中是一系列函數(shù)的指針,這里有我們比較熟悉的read、open、write和close等函數(shù)的指針。進(jìn)程就是通過這些函數(shù)訪問一個(gè)文件的,file_operations是linux虛擬文件系統(tǒng)VFS和進(jìn)程之間的接口。

        2.文件描述符

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

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

        3.進(jìn)程打開文件表

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

        [plain]view plaincopy
        print?
        1. /*
        2. *Openfiletablestructure
        3. */
        4. structfiles_struct{
        5. atomic_tcount;//引用計(jì)數(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. };
        顯然,這個(gè)結(jié)構(gòu)應(yīng)該屬于進(jìn)程的私有數(shù)據(jù),所以進(jìn)程控制塊task_struct用指針files指向它。

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

        4.文件描述符的管理

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

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

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




        評論


        技術(shù)專區(qū)

        關(guān)閉
        主站蜘蛛池模板: 武宁县| 汶上县| 秦皇岛市| 青州市| 荆州市| 丰台区| 甘洛县| 桃园县| 富裕县| 长汀县| 青岛市| 古丈县| 自治县| 望都县| 泌阳县| 安化县| 长泰县| 茌平县| 连平县| 金溪县| 抚远县| 隆化县| 红原县| 休宁县| 玛沁县| 谷城县| 五河县| 兴和县| 板桥市| 开封市| 宜川县| 新化县| 克拉玛依市| 乌鲁木齐市| 邹城市| 灵川县| 中江县| 尼玛县| 晴隆县| 吉隆县| 阿坝县|