小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

批處理技術內幕:重定向與句柄 | Demon's Blog

 ar135 2016-06-15

標題: 批處理技術內幕:重定向與句柄
作者: Demon
鏈接: http:///reverse/cmd-internal-redirect.html
版權: 本博客的所有文章,都遵守“署名-非商業(yè)性使用-相同方式共享 2.5 中國大陸”協議條款。

雖然很多人在批處理中經常用到重定向操作符和句柄,但是能理解重定向與句柄高級用法的寥寥無幾,知道重定向與句柄內部實現的更是鳳毛麟角。

按照慣例,先從簡單的說起:

>blog.txt echo http://

重定向輸出操作符>的默認句柄為1,即標準輸出(STDOUT),該代碼將句柄1的輸出重定向到blog.txt文件。

嚴格的說,句柄這個說法并不準確,正確的稱呼應該是文件描述符(file descriptor),但是鑒于幫助文檔ntcmds.chm里面用的也是句柄(handle)這個概念,并且一個文件描述符對應于一個文件句柄,所以本文沿用句柄這個說法。

在進行重定向時,CMD會先調用_get_osfhandle函數獲取文件描述符對應的文件句柄。

_get_osfhandle

如果_get_osfhandle函數的返回值不是-1,即該文件描述符存在對應的文件句柄,則調用_dup函數為該文件描述符所代表的文件創(chuàng)建一個新的文件描述符。

_dup

_dup函數返回的是下一個可以使用的文件描述符,由于標準輸入(STDIN)、標準輸出(STDOUT)、標準錯誤(STDERR)已經使用了0、1、2文件描述符,所以不出意外的話,_dup函數應該返回3,這時3和1都代表了標準輸出。這就是那些批處理教程中的所謂的“句柄備份”。

“備份”完句柄之后,CMD會調用_close函數將原來的文件句柄(描述符)關閉。

_close

關閉之后調用CreateFile函數打開重定向操作符后的文件,這里是blog.txt,因為是重定向輸出,所以以只讀模式(GENERIC_WRITE)打開。

CreateFile

成功打開文件之后,又調用_open_osfhandle函數將CreateFile函數返回的文件句柄轉成文件描述符。

_open_osfhandle

因為剛才已經把1給關閉了,所以不出意外的話,_open_osfhanle返回的應該也是1,即句柄(描述符)1指向了blog.txt文件,而不是原來的STDOUT。

到這里為止重定向已經設置好了,剩下的工作就交給echo來處理。echo命令會先判斷句柄1是否指向控制臺(Console),這里顯然不是,所以echo命令調用_os_getfhandle函數來獲取句柄1所對應的文件句柄,然后調用WriteFile函數來把http://寫入blog.txt文件。(這部分不是本文的重點,就不截圖了,詳見《批處理技術內幕:Unicode》。

命令運行完之后,就要恢復重定向的設置,剛才已經把句柄1“備份”到了句柄3,所以CMD調用_dup2函數將句柄1指向句柄3。這就是批處理教程中所謂的“句柄取回”。

_dup2

從句柄3中取回之后,句柄3就沒用了,于是調用_close函數關閉之。

上面的過程用C代碼簡單的模擬一下,大概是這樣(非常簡略的代碼,CMD的實現要復雜得多):

#include <io.h>
#include <fcntl.h>
#include <stdio.h>
#include <windows.h>

int main()
{
    int fd;
    HANDLE hFile;
    char buf[] = "http://";
    DWORD cb;

    /* 重定向句柄1到blog.txt */
    fd = _dup(1);
    _close(1);
    hFile = CreateFileW(L"blog.txt", GENERIC_WRITE, FILE_SHARE_READ,
        NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    _open_osfhandle((long)hFile, _O_WRONLY);

    /* echo命令 */
    WriteFile((HANDLE)_get_osfhandle(1), buf, sizeof(buf) - 1, &cb, NULL);

    /* 重置重定向 */
    _dup2(fd, 1);
    _close(fd);

    return 0;
}

重定向輸入<與追加模式的重定向輸出>>跟上面差不多,只不過重定向輸入>的話文件是以只讀模式(GENERIC_READ)打開的,而>>在打開文件后還要調用SetFilePointer將文件指針指向文件的末尾。

再簡單說說>&和<&,幫助文檔里的描述讓人摸不著頭腦:<&從后一個句柄讀取輸入并寫入到前一個句柄輸出中;>&將前一個句柄的輸出寫成后一個句柄的輸入。其實除了默認的句柄不同之外,>&和<&是完全一樣的,也就是說2>&1和2<&1的效果相同,都是復制句柄1到句柄2,或者說句柄2指向句柄1所指向的文件。

這樣說還是有些拗口,讓我們看看CMD內部是如何實現的吧。

cd _ 1>error.txt 2>&1

1>error.txt和上面的例子一樣,都不多說了,只講2>&1的部分,先_dup(2)得到一個新的文件描述符4(因為重定向1>error.txt時占用了3),然后_close(2),到這里為止跟上面也是一樣的。

在CMD內部,>&或者<&并不會被當成新的重定向操作符,2>&1中的重定向操作符仍然是>,&1會被認為的重定向到的文件,只不過當文件的第一個字符為&的時候CMD會特別處理罷了。這時CMD會調用dup2函數,第一個參數為>&(或者<&)后面的數字,第二個參數為>&(或者<&)前面的數字(如果沒有則使用操作符默認的句柄,>為1,<為0)。

dup2

也就是句柄2現在指向了句柄1的文件,或者說句柄2復制了句柄1,怎么好理解就怎么理解吧,反正句柄2和句柄1現在是同一個東西。

運用重定向與句柄的高級技巧,可以實現一些有用的功能,比如說防止批處理重復運行:

@echo off 2>con 3>&2 4>>%0
echo single instance batch
echo http://
pause

拓展閱讀:

隨機文章:

  1. NDS上的NeoGeo模擬器NeoDS
  2. 用C語言實現PHP的basename函數
  3. 在C語言程序中嵌入Lua腳本
  4. VBScript獲取硬盤與分區(qū)個數
  5. VBS中沒有vbHide常量

這篇文章發(fā)布于 2012年08月26日,星期日,16:55,歸類于 逆向調試。 您可以跟蹤這篇文章的評論通過 RSS 2.0 feed。 您可以留下評論,或者從您的站點trackback。             

    本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯系方式、誘導購買等信息,謹防詐騙。如發(fā)現有害或侵權內容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多