• <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>
            posts - 200, comments - 8, trackbacks - 0, articles - 0
                 轉載請注明 出自:http://m.shnenglu.com/mysileng/archive/2013/01/15/197284.html

                 今天在看UNP6.5節,學習到了select與stdio混用的后果。特此進程實驗一番。再實驗之前需明確一下幾點:
            1.stdio流的i/o函數 與 系統i/o函數不同。stdio流函數在用戶空間和內核都有緩沖,系統i/o函數只在內核有緩沖,用戶空間沒有。

            2.stdio流的i/o函數緩沖機制:在面對文件時候用的是全緩沖,面對設備的時候用的行緩沖。(等下試驗用的是鍵盤和屏幕),所以實驗用的stdio函數采用行行緩沖。

            3.select函數對于某一個描述符是否準備好可讀可寫,是對內核緩沖區中的數據是否達到某一個最低標準,而不是用戶緩沖區。也就是說select函數不知道用戶緩沖區的存在。

            首先寫了一個系統i/o函數 簡單的select函數程序:

                 程序給select函數只設置的鍵盤的描述符。也就是說如果鍵盤的描述符準備好了就不再阻塞。但是這里有一個問題,解除阻塞后,我們最多只從內核緩沖區讀3個字節,這個時候就會有兩個情況:
            (1)內核空間本來存儲的數據就小于等于3個字節,全被讀走。那下次再次調用select函數,應該肯定會阻塞的,因為鍵盤輸入的內核緩沖區已經沒有數據了。
            情況如下(內核空間只有3個字節:1 2 \n):


            (2)如果內核空間的數據多余3個字節,但是因為最多只能讀3個字節,就必將導致內核中有數據讀不完。那么下次再遇到select函數的時候是否會阻塞呢?
            情況見下:

                 當我們輸入5個字符時候(1 2 3 4 \n),第一次read掉3個字符,內核空間還剩下2個字符,然后再次碰到select函數,默認情況下如果鍵盤內核空間字符數大于1,select是不會阻塞鍵盤描述符的。結果也印證了,又read了2個字節,并沒有堵塞。
                  綜上所述select是可以看見內核空間的緩沖區的。那到底能不能看見用戶空間緩沖區呢?我們換成stdio流的i/o函數繼續實驗。

            --------------------------------------------------------------------
            stdio流的i/o函數使用select函數的程序如下:


            程序用stdio流的getc函數從鍵盤讀數據,運行結果如下:

               我們輸入5個字符(1 2 3 4 \n),結果只輸出了1個字符,然后就阻塞了。我們分析一下,首先輸入5個字符,這5個字符被放入用戶緩沖區,因為最后一個是換行符并且stdio面對設備使用行緩沖機制,所以這5個字符馬上接著被從用戶緩沖區刷入內核緩沖區。然后調用select函數,select函數發現內核空間中有數據,于是不阻塞返回。接著getc函數從用戶空間輸出緩沖區取一個字符,因為用戶空間輸出緩沖區沒有數據,于是把內核空間的數據調入一行給用戶空間輸出緩沖區,然后getc返回。接著又碰上select函數,因為內核緩沖空間的數據已經被放入用戶空間輸出緩沖區了,所以內核緩沖沒有數據,那么select認為鍵盤沒有準備好,所以阻塞。雖然阻塞了,但需要注意的時候這個時候,用戶空間是有4個字符數據的,被select函數無視了。

                 接下來假設我們再輸入2個字符(1 \n),將會發生什么呢?

                輸出一對東西,這是怎么回事,我們繼續分析。當輸入2個字符(1 \n)的時候,內核空間緩沖沒有數據,用戶空間輸出緩沖有4個字符。2個字符根據上一段同樣原理,被刷入內核空間緩沖區。select函數被調用,發現有2個字符,于是不阻塞返回。getc函數從用戶輸出緩沖取出一個字符,打印stardard... --2然后返回。再次循環,調用select函數。關鍵來了,這里跟上次不一樣了。這個時候內核空間的緩沖中還有上次遺留的2個字符,所以依然不阻塞返回,調用getc函數繼續打印。。。這里的關鍵是,getc函數。getc函數在用戶輸出緩沖中有數據的時候,不會把內核空間緩沖中的數據移入用戶空間的輸出緩沖,使得內核空間緩沖一直留有數據。這將會持續到用戶空間輸出緩沖的數據被取完為止。所以上述奇怪的打印結果就可以解釋的了。
            綜上所述,select函數確實是看不見用戶空間緩沖的尋在的。


            所以如果在使用select函數的時候,要謹慎使用stdio流函數。

            Feedback

            # re: select函數與stdio混用的不良后果 (原)  回復  更多評論   

            2016-01-18 20:00 by 2b程序員
            贊!
            蜜臀av性久久久久蜜臀aⅴ| 91久久福利国产成人精品| 亚洲国产一成久久精品国产成人综合| 狠狠色婷婷综合天天久久丁香| 久久综合丝袜日本网| 久久精品亚洲乱码伦伦中文| 人人狠狠综合久久亚洲高清| 无码精品久久久天天影视| 久久久久久人妻无码| 一级做a爰片久久毛片16| 国产69精品久久久久观看软件| 国产亚洲婷婷香蕉久久精品| 久久国产精品波多野结衣AV| 久久久av波多野一区二区| 日日狠狠久久偷偷色综合免费| 国产V亚洲V天堂无码久久久| 奇米影视7777久久精品人人爽| 热久久这里只有精品| 日韩精品久久久久久久电影蜜臀 | 亚洲精品乱码久久久久久蜜桃不卡| 久久这里只有精品18| 久久久亚洲裙底偷窥综合| 94久久国产乱子伦精品免费 | 精品久久久久香蕉网| 久久青青草原精品国产不卡| 久久久国产精品亚洲一区| 日日狠狠久久偷偷色综合免费 | 久久天天躁狠狠躁夜夜avapp| 久久影院午夜理论片无码| 成人a毛片久久免费播放| 免费国产99久久久香蕉| 久久免费线看线看| 久久精品www| 久久精品成人欧美大片| 老司机午夜网站国内精品久久久久久久久| 97久久精品无码一区二区 | 欧洲性大片xxxxx久久久| 欧美日韩精品久久久免费观看| 久久久久国产精品三级网| 久久久久久久久久免免费精品 | 久久国产精品久久精品国产|