<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
    主站蜘蛛池模板: 亚洲午夜久久久久久久久电影网| 亚洲国产成人久久综合碰| 亚洲国产另类久久久精品黑人| 男人和女人高潮免费网站| 午夜dj在线观看免费视频| 亚洲精华国产精华精华液好用| 成人毛片免费播放| 在线aⅴ亚洲中文字幕| 最近2019中文免费字幕| 亚洲欧美自偷自拍另类视| 国产精品另类激情久久久免费| 日本亚洲高清乱码中文在线观看| 免费va在线观看| a一级爱做片免费| 亚洲热线99精品视频| 久久爰www免费人成| 亚洲人成在线免费观看| 免费无遮挡无码视频网站| 在线亚洲精品视频| 国产亚洲色视频在线| 18女人腿打开无遮掩免费| 亚洲一久久久久久久久| 国产禁女女网站免费看| 国产精品极品美女自在线观看免费| 在线观看亚洲av每日更新| 无码av免费网站| 最新国产精品亚洲| 亚洲精品无码日韩国产不卡?V| 大地资源在线资源免费观看| 亚洲色欲或者高潮影院| 好男人视频社区精品免费| 国产精品美女久久久免费 | 国产精品免费αv视频| 亚洲AV无码乱码国产麻豆穿越| 国产免费一区二区三区| 国产精品无码亚洲精品2021| 亚洲av最新在线网址| 中国在线观看免费国语版| 日韩精品免费一线在线观看 | 黄瓜视频影院在线观看免费| 男男黄GAY片免费网站WWW|