青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

兔子的技術(shù)博客

兔子

   :: 首頁(yè) :: 聯(lián)系 :: 聚合  :: 管理
  202 Posts :: 0 Stories :: 43 Comments :: 0 Trackbacks

留言簿(10)

最新評(píng)論

閱讀排行榜

評(píng)論排行榜

因?yàn)镼TP的需要,同事寫(xiě)了通過(guò)進(jìn)程來(lái)調(diào)用Plink進(jìn)行Telnet連接的接口。我測(cè)試的時(shí)候發(fā)現(xiàn),他那個(gè)調(diào)用.Net 里面的Process進(jìn)程的方法,通過(guò)重定向獲取標(biāo)準(zhǔn)輸出流的辦法有點(diǎn)不好,就是調(diào)用了流動(dòng)Read()函數(shù)之后,就會(huì)一直阻塞在那里,知道流中有數(shù)據(jù)才能正確返回,而peek函數(shù)又不能正確的監(jiān)測(cè)到流中是否有數(shù)據(jù)可以讀。我先去翻翻了MSDN中那個(gè)StreamReader類(lèi)的辦法,好像確實(shí)沒(méi)有辦法,反倒是在Process的StandardOutput屬性的說(shuō)明那里,明顯寫(xiě)著,如果標(biāo)準(zhǔn)輸出里面沒(méi)有數(shù)據(jù)的話,read函數(shù)就會(huì)無(wú)限時(shí)的阻塞在那里知道有數(shù)據(jù)可以讀才行,然后他還提到了一些導(dǎo)致死鎖的問(wèn)題。

我去寫(xiě)了個(gè)簡(jiǎn)單的.Net程序來(lái)測(cè)試了一下,可以知道那個(gè)StreamReader是一個(gè)FileStream來(lái)的,而且那個(gè)CanTimeout等屬性都表明不是一個(gè)可以異步讀取的流。難道真沒(méi)有辦法監(jiān)測(cè)到這個(gè)流中是否有數(shù)據(jù)可讀的狀態(tài)嗎? 根據(jù)常識(shí)知道,這個(gè)流應(yīng)該是“匿名管道”來(lái)的,去找了一下MSDN中關(guān)于管道的api函數(shù),還真讓我找到了一個(gè),那就是PeekNamedPipe http://msdn.microsoft.com/en-us/library/aa365779(VS.85).aspx

根據(jù)它的說(shuō)明,來(lái)看看這個(gè)

The PeekNamedPipe function is similar to the ReadFile function with the following exceptions:

  • The data is read in the mode specified with CreateNamedPipe. For example, create a pipe with PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE. If you change the mode to PIPE_READMODE_BYTE with SetNamedPipeHandleStateReadFile will read in byte mode, but PeekNamedPipe will continue to read in message mode.
  • The data read from the pipe is not removed from the pipe's buffer.
  • The function can return additional information about the contents of the pipe.
  • The function always returns immediately in a single-threaded application, even if there is no data in the pipe. The wait mode of a named pipe handle (blocking or nonblocking) has no effect on the function.

Note   The PeekNamedPipe function can block thread execution the same way any I/O function can when called on a synchronous handle in a multi-threaded application. To avoid this condition, use a pipe handle created for asynchronous I/O.

If the specified handle is a named pipe handle in byte-read mode, the function reads all available bytes up to the size specified in nBufferSize. For a named pipe handle in message-read mode, the function reads the next message in the pipe. If the message is larger than nBufferSize, the function returns TRUE after reading the specified number of bytes. In this situation, lpBytesLeftThisMessage will receive the number of bytes remaining in the message.

這個(gè)函數(shù)不管命名管道是不是阻塞模式的,都會(huì)立即返回(除了在多線程環(huán)境下的某種情況下會(huì)阻塞,大概就是http://my.donews.com/yeyanbo/tag/peeknamedpipe/這個(gè)文章發(fā)現(xiàn)的問(wèn)題。),文檔又說(shuō)所有的”匿名管道“其實(shí)都是一個(gè)“命名管道”來(lái)實(shí)現(xiàn)的,所以操作“命名管道”的函數(shù)對(duì)“匿名管道”也是有效的。這個(gè)函數(shù)明顯是我想要的,可以用來(lái)檢測(cè)process標(biāo)準(zhǔn)輸出流中是否有數(shù)據(jù)可以讀,又不會(huì)阻塞。在vb.net的測(cè)試代碼里面試了一下,應(yīng)該是可以工作,測(cè)試代碼如下:

Imports System.Diagnostics.Process
Public Class Form1
    
Declare Function SetNamedPipeHandleState Lib "kernel32" (ByVal hNamedPipe As IntegerByRef lpMode As IntegerByRef lpMaxCollectionCount As IntegerByRef lpCollectDataTimeout As IntegerAs Integer
    
Declare Function PeekNamedPipe Lib "kernel32" (ByVal hNamedPipe As IntegerByRef lpBuffer As IntegerByVal nBufferSize As IntegerByRef lpBytesRead As IntegerByRef lpTotalBytesAvail As IntegerByRef lpBytesLeftThisMessage As IntegerAs Integer
    
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        
Dim p As Process = New Process
        p.StartInfo.FileName 
= "c:\windows\system32\cmd.exe"
        p.StartInfo.RedirectStandardInput 
= True
        p.StartInfo.RedirectStandardOutput 
= True
        p.StartInfo.UseShellExecute 
= False
        p.Start()
        p.StandardInput.WriteLine(
"hostname")
        
Dim f As System.IO.FileStream = p.StandardOutput.BaseStream

        
Dim mode As Integer
        mode 
= 1 ' no-wait
        Dim count As Integer
        
'修改這個(gè)命名管道為 異步的,是不能成功的
        ''mode = SetNamedPipeHandleState(f.Handle, mode, System.IntPtr.Zero, System.IntPtr.Zero)
        '不過(guò)這個(gè)PeekNamePipe 函數(shù)是可以得到 管道里面有多少字節(jié)可以讀到,執(zhí)行完之后count里面是對(duì)的,可以讀取的數(shù)據(jù)
        mode = PeekNamedPipe(f.Handle, System.IntPtr.Zero, 0, System.IntPtr.Zero, count, System.IntPtr.Zero)
        p.StandardOutput.Read()
        
While p.StandardOutput.Peek > 0
            p.StandardOutput.Read()
        
End While
        
'在這個(gè)地方的時(shí)候就不能再read了,read就無(wú)限阻塞直到有數(shù)據(jù)來(lái)才能返回了。
        mode = p.StandardOutput.Peek() '這個(gè)時(shí)候的peek返回 -1是對(duì)的
        mode = PeekNamedPipe(f.Handle, System.IntPtr.Zero, 0, System.IntPtr.Zero, count, System.IntPtr.Zero) '這個(gè)count得到0 是對(duì)的,管道里面沒(méi)有消息的了
        p.StandardInput.WriteLine("hostname")
        mode 
= p.StandardOutput.Peek() '這個(gè)還是返回 -1是不對(duì)的,
        mode = PeekNamedPipe(f.Handle, System.IntPtr.Zero, 0, System.IntPtr.Zero, count, System.IntPtr.Zero) '這個(gè)返回正確的count,表明管道里面有數(shù)據(jù)是對(duì)的
        p.StandardOutput.Read()
        p.StandardOutput.Peek() 
'peek函數(shù)一定要在read成功調(diào)用過(guò)一次之后才能正確的得到管道的狀態(tài)。但Read一次又可能引起無(wú)限時(shí)間的阻塞!!!!所以只有PeekNamedPipe才能正確的無(wú)阻塞的檢測(cè)到管道的數(shù)據(jù)
    End Sub
End Class

總結(jié)一下 :感覺(jué)。Net對(duì)這個(gè)“命名管道“”匿名管道“的支持明顯不夠,API中都有監(jiān)測(cè)到管道是否有數(shù)據(jù)可以讀到函數(shù)。.Net里面卻連管道對(duì)應(yīng)的類(lèi)都沒(méi)有實(shí)現(xiàn),所以相應(yīng)的這種阻塞情況就也沒(méi)法處理了。可能這部分的封裝有待完善吧。

后來(lái)有用Reflector工具反匯編看了看系統(tǒng)Process幾個(gè)類(lèi)的相應(yīng)實(shí)現(xiàn)代碼,可以看到他是CreatePipe創(chuàng)建一個(gè)管道,然后DuplicateHandle復(fù)制了一個(gè)文件句柄的,跟我事先的猜測(cè)是一樣的。Linux的輸出重定向使用也要類(lèi)似的這樣兩個(gè)步驟。如果你自己看他的代碼,可以看到創(chuàng)建的是一個(gè)只讀的、不支持異步的FileSteam來(lái)的,他代碼是這樣寫(xiě)的:

public bool Start()
{
    
this.Close();
    ProcessStartInfo startInfo 
= this.StartInfo;
    
if (startInfo.FileName.Length == 0)
    {
        
throw new InvalidOperationException(SR.GetString("FileNameMissing"));
    }
    
if (startInfo.UseShellExecute)
    {
        
return this.StartWithShellExecuteEx(startInfo);
    }
    
return this.StartWithCreateProcess(startInfo);
}

private bool StartWithCreateProcess(ProcessStartInfo startInfo)
{
    
if ((startInfo.StandardOutputEncoding != null&& !startInfo.RedirectStandardOutput)
    {
        
throw new InvalidOperationException(SR.GetString("StandardOutputEncodingNotAllowed"));
    }
    
if ((startInfo.StandardErrorEncoding != null&& !startInfo.RedirectStandardError)
    {
        
throw new InvalidOperationException(SR.GetString("StandardErrorEncodingNotAllowed"));
    }
    
if (this.disposed)
    {
        
throw new ObjectDisposedException(base.GetType().Name);
    }
    StringBuilder cmdLine 
= BuildCommandLine(startInfo.FileName, startInfo.Arguments);
    NativeMethods.STARTUPINFO lpStartupInfo 
= new NativeMethods.STARTUPINFO();
    SafeNativeMethods.PROCESS_INFORMATION lpProcessInformation 
= new SafeNativeMethods.PROCESS_INFORMATION();
    SafeProcessHandle processHandle 
= new SafeProcessHandle();
    SafeThreadHandle handle2 
= new SafeThreadHandle();
    
int error = 0;
    SafeFileHandle parentHandle 
= null;
    SafeFileHandle handle4 
= null;
    SafeFileHandle handle5 
= null;
    GCHandle handle6 
= new GCHandle();
    
try
    {
        
bool flag;
        
if ((startInfo.RedirectStandardInput || startInfo.RedirectStandardOutput) || startInfo.RedirectStandardError)
        {
            
if (startInfo.RedirectStandardInput)
            {
                
this.CreatePipe(out parentHandle, out lpStartupInfo.hStdInput, true);
            }
            
else
            {
                lpStartupInfo.hStdInput 
= new SafeFileHandle(NativeMethods.GetStdHandle(-10), false);
            }
            
if (startInfo.RedirectStandardOutput)
            {
                
this.CreatePipe(out handle4, out lpStartupInfo.hStdOutput, false);
            }
            
else
            {
                lpStartupInfo.hStdOutput 
= new SafeFileHandle(NativeMethods.GetStdHandle(-11), false);
            }


中間省略一部分

   if (startInfo.RedirectStandardInput)

    {
        this.standardInput = new StreamWriter(new FileStream(parentHandle, FileAccess.Write, 0x1000, false), Encoding.GetEncoding(NativeMethods.GetConsoleCP()), 0x1000);
        this.standardInput.AutoFlush = true;
    }
    if (startInfo.RedirectStandardOutput)
    {
        Encoding encoding = (startInfo.StandardOutputEncoding != null) ? startInfo.StandardOutputEncoding : Encoding.GetEncoding(NativeMethods.GetConsoleOutputCP());
        this.standardOutput = new StreamReader(new FileStream(handle4, FileAccess.Read, 0x1000, false), encoding, true, 0x1000);
    }
    if (startInfo.RedirectStandardError)
    {
        Encoding encoding2 = (startInfo.StandardErrorEncoding != null) ? startInfo.StandardErrorEncoding : Encoding.GetEncoding(NativeMethods.GetConsoleOutputCP());
        this.standardError = new StreamReader(new FileStream(handle5, FileAccess.Read, 0x1000, false), encoding2, true, 0x1000);
    }
    bool flag3 = false;
    if (!processHandle.IsInvalid)
    {
        this.SetProcessHandle(processHandle);
        this.SetProcessId(lpProcessInformation.dwProcessId);
        handle2.Close();
        flag3 = true;
    }
    return flag3;
}

private void CreatePipe(out SafeFileHandle parentHandle, out SafeFileHandle childHandle, bool parentInputs)
{
    NativeMethods.SECURITY_ATTRIBUTES lpPipeAttributes = new NativeMethods.SECURITY_ATTRIBUTES();
    lpPipeAttributes.bInheritHandle = true;
    SafeFileHandle hWritePipe = null;
    try
    {
        if (parentInputs)
        {
            CreatePipeWithSecurityAttributes(out childHandle, out hWritePipe, lpPipeAttributes, 0);
        }
        else
        {
            CreatePipeWithSecurityAttributes(out hWritePipe, out childHandle, lpPipeAttributes, 0);
        }
        if (!NativeMethods.DuplicateHandle(new HandleRef(this, NativeMethods.GetCurrentProcess()), hWritePipe, new HandleRef(this, NativeMethods.GetCurrentProcess()), out parentHandle, 0, false, 2))
        {
            throw new Win32Exception();
        }
    }
    finally
    {
        if ((hWritePipe != null) && !hWritePipe.IsInvalid)
        {
            hWritePipe.Close();
        }
    }
}

private static void CreatePipeWithSecurityAttributes(out SafeFileHandle hReadPipe, out SafeFileHandle hWritePipe, NativeMethods.SECURITY_ATTRIBUTES lpPipeAttributes, int nSize)
{
    if ((!NativeMethods.CreatePipe(out hReadPipe, out hWritePipe, lpPipeAttributes, nSize) || hReadPipe.IsInvalid) || hWritePipe.IsInvalid)
    {
        throw new Win32Exception();
    }
}

public override int Peek()
{
    if (this.stream == null)
    {
        __Error.ReaderClosed();
    }
    if ((this.charPos != this.charLen) || (!this._isBlocked && (this.ReadBuffer() != 0)))
    {
        return this.charBuffer[this.charPos];
    }
    return -1;
}
轉(zhuǎn)自:http://hi.baidu.com/widebright/item/f58e2516a6bb41dcbf9042a4
posted on 2012-08-16 13:30 會(huì)飛的兔子 閱讀(4451) 評(píng)論(0)  編輯 收藏 引用 所屬分類(lèi): 系統(tǒng)API,底層技術(shù)
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲一区二区三区三| 欧美国产精品劲爆| 亚洲无人区一区| 国产精品www| 欧美专区第一页| 欧美在线影院| 亚洲成人在线观看视频| 欧美成人激情视频免费观看| 欧美a级片网| 亚洲一区二区三区免费视频| 亚洲欧美国产高清va在线播| 在线成人av| 日韩视频中午一区| 国产亚洲女人久久久久毛片| 久久日韩粉嫩一区二区三区| 欧美gay视频| 新狼窝色av性久久久久久| 久久久久久久久久久成人| 亚洲精品视频在线| 亚洲影院免费观看| 亚洲国产精品123| 99热在这里有精品免费| 国产主播一区二区三区| 亚洲狠狠丁香婷婷综合久久久| 欧美巨乳在线| 久久视频在线免费观看| 欧美日本国产精品| 久久综合给合久久狠狠狠97色69| 欧美激情精品久久久六区热门| 亚洲影院一区| 免费成人高清视频| 久久av二区| 欧美日韩在线观看视频| 免费在线看成人av| 国产精品日韩专区| 最新国产成人av网站网址麻豆| 国产情侣一区| 一区二区三欧美| 亚洲免费观看高清完整版在线观看| 午夜精品久久| 亚洲欧美日韩视频一区| 欧美激情精品久久久久久免费印度 | 久久精品系列| 久久另类ts人妖一区二区| 亚洲一区二区三区777| 麻豆av一区二区三区久久| 欧美影院成人| 国产精品日本| 一区二区三区欧美激情| 精品av久久707| 亚洲综合不卡| 亚洲一区免费视频| 欧美日韩一区二区三区免费| 欧美大色视频| 亚洲第一页中文字幕| 久久久久国内| 久久亚洲精品一区| 国产色产综合色产在线视频| 亚洲视频一二| 午夜伦欧美伦电影理论片| 国产精品超碰97尤物18| 日韩午夜在线电影| 亚洲一区亚洲| 国产精品蜜臀在线观看| 亚洲视频视频在线| 香蕉av777xxx色综合一区| 国产精品av免费在线观看| 一区二区三区蜜桃网| 亚洲一区一卡| 国产目拍亚洲精品99久久精品| 亚洲午夜高清视频| 欧美一区二区三区四区高清| 国产日韩欧美精品| 欧美一区二区三区免费看| 久久久噜噜噜久久| 在线观看视频一区| 欧美大片91| 一区二区三区欧美视频| 欧美在线综合视频| 亚洲第一精品电影| 欧美激情一区二区三区在线| 亚洲免费观看视频| 欧美一级在线亚洲天堂| 国产一区深夜福利| 麻豆亚洲精品| 99视频有精品| 欧美在线播放| 91久久综合| 国产精品成人一区| 久久国产精品高清| 亚洲国内自拍| 亚洲欧美日韩视频一区| 在线播放中文一区| 欧美视频日韩视频在线观看| 亚洲一区二区成人| 欧美成人国产| 午夜精品国产更新| 亚洲级视频在线观看免费1级| 欧美日韩一区二区三区免费看| 亚洲女人av| 亚洲激情av| 久久久久久自在自线| 日韩一区二区高清| 国产一区二区三区自拍| 欧美精品在线网站| 久久精品日产第一区二区三区| 亚洲激情不卡| 久久综合亚洲社区| 亚洲欧美日韩精品在线| 亚洲国产精品成人综合| 国产精品网站一区| 欧美另类69精品久久久久9999| 午夜欧美大片免费观看| 亚洲毛片在线免费观看| 狼人天天伊人久久| 午夜一区二区三视频在线观看| 亚洲欧洲一区| 黑人巨大精品欧美一区二区小视频 | 最新亚洲电影| 国产老女人精品毛片久久| 欧美~级网站不卡| 久久精品国产99国产精品澳门 | 性色av一区二区三区在线观看 | 一区在线影院| 国产视频在线观看一区 | 欧美亚洲尤物久久| 夜夜狂射影院欧美极品| 亚洲国产裸拍裸体视频在线观看乱了中文 | 欧美极品一区二区三区| 久久国产婷婷国产香蕉| 一本色道久久综合亚洲精品不卡| 欧美.www| 你懂的成人av| 久久亚洲春色中文字幕| 欧美一区二区国产| 亚洲欧美另类国产| 一区二区三区回区在观看免费视频| 在线不卡亚洲| 在线欧美福利| 在线观看日产精品| 亚洲大胆av| 在线播放不卡| 亚洲第一页中文字幕| 亚洲电影免费观看高清| 亚洲国产高潮在线观看| 激情视频一区二区| 欲香欲色天天天综合和网| 影音先锋在线一区| 亚洲国产日韩欧美在线动漫| 亚洲国产一区二区在线| 亚洲清纯自拍| 一区二区三区精品| 亚洲欧美电影院| 久久精品99久久香蕉国产色戒| 欧美在线影院| 你懂的一区二区| 亚洲欧洲精品一区二区三区波多野1战4| 亚洲国产精品一区二区尤物区| 最新日韩在线视频| 一区二区高清在线| 午夜精品999| 老司机一区二区| 欧美日韩另类国产亚洲欧美一级| 欧美日韩一本到| 国产日本欧美一区二区| 好看的亚洲午夜视频在线| 最新日韩中文字幕| 亚洲欧美韩国| 免费91麻豆精品国产自产在线观看| 欧美电影打屁股sp| 日韩亚洲精品电影| 欧美一级视频一区二区| 美女视频网站黄色亚洲| 欧美日韩综合视频网址| 国产自产2019最新不卡| 亚洲精品九九| 香港久久久电影| 欧美激情精品久久久| 在线午夜精品| 麻豆精品国产91久久久久久| 欧美四级在线| 亚洲第一福利社区| 欧美一级久久| 欧美黄色免费网站| 亚洲欧美日韩一区在线| 男同欧美伦乱| 国内精品久久久久影院薰衣草| 亚洲美女啪啪| 久久一二三国产| 中国成人在线视频| 牛牛影视久久网| 国产美女精品视频| 99热这里只有成人精品国产| 久久久久网站| 亚洲一区视频| 欧美午夜不卡影院在线观看完整版免费| **网站欧美大片在线观看| 香蕉国产精品偷在线观看不卡 | 久久久久久国产精品mv| 日韩亚洲欧美成人|