<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Calvin's Tech Space

    成于堅忍,毀于浮躁

       :: 首頁 :: 聯系 :: 聚合  :: 管理
    ?? 在linux紛繁復雜的內核代碼中,sys_dup()的代碼也許稱得上是最簡單的之一了,但是就是這么一個簡單的系統調用,卻成就了unix/linux系統最著名的一個特性:輸入/輸出重定向。
    ??? sys_dup()的主要工作就是用來“復制”一個打開的文件號,使兩個文件號都指向同一個文件。既然說簡單,我們就首先來看一下它的代碼(定義在fs/fcntl.c中):
    ?1?asmlinkage?long?sys_dup(unsigned?int?fildes)
    ?2?{
    ?3?????int?ret?=?-EBADF;
    ?4?????struct?file?*?file?=?fget(fildes);
    ?5?
    ?6?????if?(file)
    ?7?????????ret?=?dupfd(file,?0);
    ?8?????return?ret;
    ?9?}
    10?

    而sys_dup()的主體是dupfd()(定義在同一個文件中):

    ?1?static?int?dupfd(struct?file?*file,?int?start)
    ?2?{
    ?3?????struct?files_struct?*?files?=?current->files;
    ?4?????int?ret;
    ?5?
    ?6?????ret?=?locate_fd(files,?file,?start);
    ?7?????if?(ret?<?0)
    ?8?????????goto?out_putf;
    ?9?????allocate_fd(files,?file,?ret);
    10?????return?ret;
    11?
    12?out_putf:
    13?????write_unlock(&files->file_lock);
    14?????fput(file);
    15?????return?ret;
    16?}
    17?

    注:dup和dup2的原型如下:
    #include <unistd.h>

    int dup(int file_descriptor);
    int dup2(int file_descriptor1, int file_descriptor2)
    dup返回的文件描述符總是取最小的可用值
    dup2返回的文件描述符或者與file_descriptor2相同,或者是第一個大于該參數的可用值。


    ??? 而這么一個簡單的系統調用是如何完成重定向這個艱巨的任務的呢?我們不妨先看個例子。
    ??? 當我們在shell下輸入如下命令:“echo hello!”,這條命令要求shell進程執行一個可執行文件echo,參數為“hello!”。當shell接收到命令之后,先找到 bin/echo,然后fork()出一個子進程讓他執行bin/echo,并將參數傳遞給它,而這個進程從shell繼承了三個標準文件,即標準輸入 (stdin),標準輸出(stdout)和標準出錯信息(stderr),他們三個的文件號分別為0、1、2。而至于echo進程的工作很簡單,就是將參數“hello!”寫到標準輸出文件中去,通常都是我們的顯示器上。但是如果我們將命令改成“echo hello! > foo”,則在執行時輸出將會被重定向到磁盤文件foo中(注:重定向于文件描述符有關)。我們假定在此之前該shell進程只有三個標準文件打開,文件號分別為0、1、2,以上命令行將按如下序列執行:
    ??? (1) 打開或創建磁盤文件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) 通過系統調用fork()和exec()創建子進程并執行echo,子進程在執行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同樣)指向什么,進程與實際輸出文件或設備的結合是在運行時由其父進程“包辦”的。這樣就簡化了子進程的程序設計,因為在設計時只要跟三個邏輯上存在的文件打交道就可以了。可能有人會覺得這很像面向對象中 的多態和重載,沒有什么新奇之處,但是如果你活在30甚至40年前,可能你會改變你的看法。?
    posted on 2011-12-13 14:20 calvin 閱讀(2365) 評論(0)  編輯  收藏 所屬分類: LinuxC
    主站蜘蛛池模板: 一级一级一级毛片免费毛片| 男女交性永久免费视频播放| 久久WWW免费人成人片| 国产免费观看a大片的网站| 亚洲精品无码av天堂| 亚洲国产精品国自产拍电影| 亚洲AV无码国产精品色| 人碰人碰人成人免费视频| 久久免费看黄a级毛片| 亚洲男女内射在线播放| 亚洲第一区二区快射影院| 亚欧洲精品在线视频免费观看| 97碰公开在线观看免费视频| 亚洲精品专区在线观看| 亚洲欧洲综合在线| a级黄色毛片免费播放视频| 日韩免费高清视频网站| 亚洲一区中文字幕在线观看| 最近免费中文字幕中文高清| 日日夜夜精品免费视频| 亚洲国产成人久久| 午夜免费福利片观看| 国产亚洲欧洲精品| 三年片在线观看免费西瓜视频| 免费看男女下面日出水视频| 亚洲AV永久无码天堂影院| 国产啪精品视频网免费| 亚洲婷婷天堂在线综合| h视频在线观看免费完整版| 亚洲国产一区二区a毛片| 午夜无码A级毛片免费视频| 国产成人精品日本亚洲专区61| 黄色a三级免费看| 亚洲精品成人网久久久久久| 老司机午夜在线视频免费| 日韩一级视频免费观看| 猫咪免费观看人成网站在线| 亚洲成网777777国产精品| yy一级毛片免费视频| 国产亚洲A∨片在线观看| 久久国产乱子伦免费精品|