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

兔子的技術(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>
            亚洲经典三级| 性欧美videos另类喷潮| 一区二区三区在线视频观看| 夜夜狂射影院欧美极品| 老司机午夜精品视频在线观看| 日韩视频在线观看| 欧美二区在线看| 亚洲激情综合| 久久亚洲欧美国产精品乐播| 亚洲欧美日韩视频一区| 国产精品欧美精品| 欧美一级精品大片| 午夜精品久久久久久久| 国产日韩专区| 麻豆精品网站| 欧美不卡视频一区发布| 亚洲黄色在线观看| 亚洲人成网站在线播| 欧美电影免费观看高清完整版| 亚洲国产一区在线| 欧美国产精品| 欧美日韩另类国产亚洲欧美一级| 一区二区高清在线观看| 亚洲麻豆视频| 国产女人水真多18毛片18精品视频| 午夜一区不卡| 久久精品成人一区二区三区蜜臀| 激情综合视频| 亚洲人成网站在线观看播放| 欧美特黄一级| 久久人人97超碰精品888| 老司机午夜精品视频在线观看| 亚洲国产精品久久久久久女王 | 亚洲精选91| 欧美日韩三级在线| 欧美在线播放| 美女日韩在线中文字幕| 一本色道久久88亚洲综合88| 亚洲专区一二三| 精品福利av| 91久久国产综合久久| 国产精品高清在线| 久久婷婷久久| 欧美日韩成人在线播放| 久久久精品动漫| 欧美福利在线| 久久精品国产亚洲a| 免费观看成人www动漫视频| 亚洲无亚洲人成网站77777 | 亚洲第一伊人| 日韩一级免费观看| 狠狠做深爱婷婷久久综合一区| 亚洲大片免费看| 国产精品一区一区| 亚洲国产婷婷综合在线精品| 狼狼综合久久久久综合网| 亚洲人成7777| 久久在精品线影院精品国产| 亚洲视频在线视频| 久久精品成人欧美大片古装| 一本一道久久综合狠狠老精东影业 | 亚洲国语精品自产拍在线观看| 国产精品免费一区二区三区观看| 狼人天天伊人久久| 国产精品美女久久福利网站| 欧美韩日精品| 国内自拍视频一区二区三区| 99综合精品| 亚洲日韩欧美视频一区| 欧美一区二区三区久久精品| 亚洲视频图片小说| 欧美精品午夜视频| 蜜桃av综合| 国产三区精品| 亚洲免费在线播放| 亚洲一区二区视频在线观看| 欧美在线视频免费播放| 亚洲午夜影视影院在线观看| 久久夜色撩人精品| 国产精品视频一区二区高潮| 亚洲国产另类 国产精品国产免费| 亚洲国产成人午夜在线一区| 国产一区999| 亚洲欧美日韩成人| 亚洲欧美日韩综合国产aⅴ| 欧美日本中文字幕| 亚洲欧洲一二三| 最近中文字幕日韩精品| 久久在线视频| 欧美电影在线免费观看网站| 激情六月综合| 久久久久99| 美女精品在线观看| 亚洲高清视频在线| 欧美成人高清| 亚洲精品久久久蜜桃| 日韩视频免费观看| 欧美日韩国产小视频| 日韩一区二区精品视频| 亚洲一区二区精品在线观看| 国产精品家庭影院| 午夜精品视频网站| 久久久久国产一区二区三区| 黄色成人在线网站| 蜜桃精品久久久久久久免费影院| 欧美激情一区二区三区不卡| 在线视频亚洲一区| 国产精品亚洲片夜色在线| 午夜在线一区| 欧美国产高潮xxxx1819| 一区二区三区不卡视频在线观看 | 欧美成人精精品一区二区频| 亚洲成人直播| 午夜精品视频在线观看一区二区 | 国产精品视频999| 欧美亚洲免费| 亚洲午夜久久久久久久久电影网| 最新高清无码专区| 亚洲二区在线视频| 欧美日韩大片| 亚洲欧美精品在线观看| 久久人人爽人人爽| 亚洲精品小视频在线观看| 国产精品成人免费视频 | 欧美日韩久久久久久| 亚洲制服少妇| 亚洲第一在线综合在线| 午夜精品久久久久久99热软件| 狠狠做深爱婷婷久久综合一区| 欧美精品色综合| 欧美一区在线直播| 日韩特黄影片| 欧美ed2k| 午夜久久黄色| 最新日韩精品| 国产一区二区三区久久| 欧美日韩成人综合天天影院| 欧美一二三视频| 亚洲精品影视| 欧美电影电视剧在线观看| 午夜精品999| 亚洲精品欧美专区| 国产综合久久| 国产精品视频免费观看| 欧美成va人片在线观看| 欧美在线高清| 亚洲一区综合| 亚洲乱亚洲高清| 欧美激情在线观看| 久久久国产亚洲精品| 一区二区日韩精品| 亚洲激情女人| 尤物九九久久国产精品的特点 | 尤物精品在线| 国产一区二区三区网站| 国产精品成人观看视频免费 | 亚洲国产精品传媒在线观看| 国产欧美精品| 国产精品视频九色porn| 欧美视频在线观看视频极品| 欧美国产日韩一区二区在线观看| 久久精品久久99精品久久| 亚洲欧美日韩视频二区| 亚洲视频一二| 国产精品99久久久久久www| 亚洲美女毛片| 亚洲欧洲精品成人久久奇米网 | 久久久亚洲人| 欧美中文字幕精品| 香蕉尹人综合在线观看| 亚洲欧美日韩国产另类专区| 中文亚洲字幕| 亚洲免费在线看| 亚洲综合二区| 欧美一级成年大片在线观看| 亚洲欧美另类中文字幕| 亚洲欧美在线x视频| 香蕉成人伊视频在线观看| 欧美激情亚洲国产| 欧美一区二区三区免费视| 亚洲五月六月| 亚洲欧美区自拍先锋| 性视频1819p久久| 欧美一级淫片aaaaaaa视频| 欧美在线高清| 在线免费高清一区二区三区| 欧美乱大交xxxxx| 亚洲免费在线观看| 午夜精品久久久久99热蜜桃导演| 欧美成人tv| 激情成人在线视频| 欧美国产日韩视频| 久久影视精品| 欧美专区18| 久久国产精品久久久久久| 欧美专区在线观看| 乱码第一页成人| 亚洲国产精品v| 一本久久综合亚洲鲁鲁五月天| 正在播放欧美视频|