在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

            EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > linux內核中的dup系統(tǒng)調用

            linux內核中的dup系統(tǒng)調用

            作者: 時間:2016-11-22 來源:網(wǎng)絡 收藏
            內核版本:2.6.14

            dup系統(tǒng)調用的服務例程為sys_dup函數(shù),定義在fs/fcntl.c中。sys_dup()的代碼也許稱得上是最簡單的之一了,但是就是這么一個簡單的系統(tǒng)調用,卻成就了linux系統(tǒng)最著名的一個特性:輸入/輸出重定向。sys_dup()的主要工作就是用來“復制”一個打開的文件號,并使兩個文件號都指向同一個文件,下面我們來分析一下它的代碼。

            本文引用地址:http://www.biyoush.com/article/201611/319990.htm

            1.sys_dup源碼分析

            [plain]view plaincopy
            print?
            1. asmlinkagelongsys_dup(unsignedintfildes)//sys_dup函數(shù)的參數(shù),即fildes,是文件描述符fd
            2. {
            3. intret=-EBADF;
            4. structfile*file=fget(fildes);//通過文件描述符找到對應的文件
            5. if(file)
            6. ret=dupfd(file,0);//分配一個新的文件描述符fd,并將fd和file聯(lián)系起來
            7. returnret;
            8. }

            1.1fget(fildes)

            [plain]view plaincopy
            print?
            1. structfilefastcall*fget(unsignedintfd)
            2. {
            3. structfile*file;
            4. structfiles_struct*files=current->files;//獲得當前進程的打開文件表
            5. rcu_read_lock();
            6. file=fcheck_files(files,fd);//根據(jù)fd從打開文件表files里取出相應的file結構變量
            7. if(file){
            8. if(!rcuref_inc_lf(&file->f_count)){//增加引用
            9. /*Fileobjectrefcouldntbetaken*/
            10. rcu_read_unlock();
            11. returnNULL;
            12. }
            13. }
            14. rcu_read_unlock();
            15. returnfile;
            16. }
            17. staticinlinestructfile*fcheck_files(structfiles_struct*files,unsignedintfd)
            18. {
            19. structfile*file=NULL;
            20. structfdtable*fdt=files_fdtable(files);
            21. if(fdmax_fds)
            22. file=rcu_dereference(fdt->fd[fd]);
            23. returnfile;
            24. }

            1.2dupfd(file, 0)

            [plain]view plaincopy
            print?
            1. staticintdupfd(structfile*file,unsignedintstart)
            2. {
            3. structfiles_struct*files=current->files;
            4. structfdtable*fdt;
            5. intfd;
            6. spin_lock(&files->file_lock);
            7. fd=locate_fd(files,file,start);//分配文件描述符
            8. if(fd>=0){
            9. /*locate_fd()mayhaveexpandedfdtable,loadtheptr*/
            10. fdt=files_fdtable(files);//獲得文件描述符表
            11. FD_SET(fd,fdt->open_fds);//設置打開文件標記
            12. FD_CLR(fd,fdt->close_on_exec);
            13. spin_unlock(&files->file_lock);
            14. fd_install(fd,file);//建立fd和file的聯(lián)系,之后通過fd就可以找到file
            15. }else{
            16. spin_unlock(&files->file_lock);
            17. fput(file);
            18. }
            19. returnfd;
            20. }

            2.內核初始化中的相關源碼分析

            [plain]view plaincopy
            print?
            1. staticintinit(void*unused)
            2. {
            3. ...
            4. if(sys_open((constchar__user*)"/dev/console",O_RDWR,0)<0)
            5. printk(KERN_WARNING"Warning:unabletoopenaninitialconsole.n");
            6. //打開控制臺,這樣init進程就擁有一個控制臺,并可以從中讀取輸入信息,也可以向其中寫入信息
            7. (void)sys_dup(0);//調用dup打開/dev/console文件描述符兩次,這樣控制太設備也可以供表述輸出和標準錯誤使用(文件描述符為1和2)
            8. (void)sys_dup(0);
            9. //假設sys_open((constchar__user*)"/dev/console",O_RDWR,0)成功執(zhí)行,init進程就擁有3個文件描述符(標準輸入、標準輸出和標準錯誤)
            10. ...
            11. }

            3.系統(tǒng)重定向

            我們通過一個簡單的來講解重定向。
            當我們在shell下輸入如下命令:“echo hello!”,這條命令要求shell進程執(zhí)行一個可執(zhí)行文件echo,參數(shù)為“hello!”。當shell接收到命令之后,先找到bin/echo,然后fork()出一個子進程讓他執(zhí)行bin/echo,并將參數(shù)傳遞給它,而這個進程從shell繼承了三個標準文件,即標準輸入(stdin),標準輸出(stdout)和標準出錯信息(stderr),它們三個的文件號分別為0、1、2。而至于echo進程的工作很簡單,就是將參數(shù)“hello!”寫道標準輸出文件中去,通常都是我們的顯示器上。但是如果我們將命令改成“echo hello! > foo”,則在執(zhí)行時輸出將會被重定向到磁盤文件foo中。我們假定在此之前該shell進程只有三個標準文件打開,文件號分別為0、1、2,以上命令行將按如下序列執(zhí)行:

            • (1) 打開或創(chuàng)建磁盤文件foo,如果foo中原來有內容,則清除原來內容,其文件號為3。
            • (2) 通過dup()復制文件stdout,即將文件號1出的file結構指針復制到文件號4處,目的是將stdout的file指針暫時保存一下
            • (3) 關閉stdout,即1號文件,但是由于4號文件對stdout也同時有個引用,所以stdout文件并未真正關閉,只是騰出1號文件號位置。
            • (4) 通過dup(),復制3號文件(即磁盤文件foo),由于1號文件關閉,其位置空缺,故3號文件被復制到1號,即進程中原來指向stdout的指針指向了foo。
            • (5) 通過系統(tǒng)調用fork()和exec()創(chuàng)建子進程并執(zhí)行echo,子進程在執(zhí)行echo前夕關閉3號和4號文件,只留下0、1、2三個文件,請注意,這時的1號文件已經不是stdout而是磁盤文件foo了。當echo想向stdout文件寫入“hello!”時自然就寫入到了foo中。
            • (6) 回到shell后,關閉指向foo的1號與3號文件,再用dup()和close()將2號恢復至stdout,這樣shell就恢復了0、1、2三個標準輸入/輸出文件。
            由此可見,當echo程序(或其他)在運行的時候并不知道stdout(對于stdin和stderr同樣)指向什么,進程與實際輸出文件或設備的結合是在運行時由其父進程“包辦”的。這樣就簡化了子進程的程序設計,因為在設計時只要跟三個邏輯上存在的文件打交道就可以了,類似于面向對象中的多態(tài)和重載。


            評論


            技術專區(qū)

            關閉