<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
    主站蜘蛛池模板: 免费亚洲视频在线观看| 在线A亚洲老鸭窝天堂| 欧美好看的免费电影在线观看| 日韩免费高清大片在线| 亚在线观看免费视频入口| 日本免费人成网ww555在线| 免费无码作爱视频| a级午夜毛片免费一区二区| a级毛片无码免费真人久久| 99免费在线视频| 久久免费视频精品| 色欲色香天天天综合网站免费| 91福利免费视频| 国产免费不卡v片在线观看| 在线v片免费观看视频| 在线免费观看中文字幕| 热99re久久免费视精品频软件| 国产一区二区三区免费在线观看| 国产人妖ts在线观看免费视频| 婷婷综合缴情亚洲狠狠尤物| 亚洲一区二区精品视频| 久久亚洲精品无码播放| 亚洲AV无码国产精品麻豆天美| 亚洲天天做日日做天天看| 91亚洲精品麻豆| 亚洲精品V天堂中文字幕| 免费人妻精品一区二区三区| eeuss影院免费92242部| 无码国产精品一区二区免费式芒果| 无码成A毛片免费| 在线永久免费的视频草莓| 免费特级黄毛片在线成人观看| 日韩精品亚洲专区在线观看| 国产亚洲av片在线观看播放| 久久久久亚洲精品日久生情 | 亚洲乱码中文字幕手机在线| 中文字幕精品亚洲无线码一区 | 日韩a级毛片免费观看| 亚洲精品国产综合久久一线| 久久久久无码精品亚洲日韩| 精品久久久久久亚洲精品|