2012-12-03 77 views
18

根據我的理解,您可以編寫一個無限循環監聽請求的Linux守護程序。
喜歡的東西..無盡無盡While循環佔用CPU資源?

int main() { 
    while(1) { 
     //do something... 
    } 
} 

裁判:http://www.thegeekstuff.com/2012/02/c-daemon-process/

,我讀了睡覺的程序使其進入等待模式,因此不會吃起來的資源。

1.如果我想讓我的守護進程每隔1秒檢查一次請求,下面是否會耗費資源?

int main() { 
    while(1) { 
     if (request) { 
      //do something... 
     } 
     sleep(1) 
    } 
} 

2.如果我要消除睡眠,是否意味着CPU消耗會增加100%?

3.是否有可能在沒有資源的情況下運行無限循環?說..如果它什麼也不做,只是循環自己。或者只是睡覺(1)。

無盡的循環和CPU資源對我來說是個謎。

+1

睡覺告訴調度,使CPU,而不是你的進程上的一個特定的時間卸載運行一些其他進程(也保持簡單)。您的程序在睡眠時不會消耗任何CPU資源。即使睡幾毫秒,也可以讓事情順利進行,就像你展示的那樣。 –

+3

如果你是*聽*,那麼你應該使用一些系統調用復像'調查(2)'(或上了年紀,幾乎過時,'選擇(2)') –

回答

12

是否有可能在沒有資源的情況下運行無限循環?說..如果它什麼也不做,只是循環自己。或者只是睡覺(1)。

還有一個更好的選擇。
您可以使用信號量,該信號在循環開始時保持阻塞狀態,只要您希望循環執行就可以發出信號。
請注意,這不會吃任何資源。

+1

「不會吃任何資源」並不完全如此.. 。創建一個信號量使用內核資源和對象,並且是一個相當繁重的操作。在信號量上等待是內核模式操作,並且也會導致上下文切換到內核模式。如果使用超時 –

+0

信號量是合適的,但睡眠仍可能是最好的。如果你希望你的代碼在* timeout *或者*一些外部事件上觸發,信號量是最相關的。 –

+0

感謝提到的信號量。總得探索,當時間到來:) – resting

2

簡短的回答是肯定的 - 消除睡眠可以使CPU達到100% - 但是答案確實取決於一些額外的細節。它會消耗所有可以獲得的CPU,除非...

  1. 循環體是微不足道的,並優化了。
  2. 循環包含阻止操作(如文件或網絡操作)。您提供的鏈接建議避免這種情況,但阻止相關事件發生通常是一個好主意。

編輯:對於您的情況,我支持@Als提出的建議。

編輯2:我希望這個答案已經收到-1,因爲我聲稱阻止操作實際上可以是一個好主意。 [如果你-1,你應該在評論中留下動力,以便我們都可以學到一些東西。]

當前流行的思想是非塊(基於事件)IO很好,阻塞是不好的。此視圖過於簡化,因爲它假定所有執行IO的軟件都可以通過使用非阻塞操作來提高吞吐量。

什麼?我真的建議使用非阻塞IO實際上可以降低吞吐量嗎?是的,它可以。當進程服務於單個活動時,使用阻塞IO實際上會更好,因爲阻塞IO僅會燒燬已存在進程中已支付的資源。

相反,非阻塞IO可攜帶比簡單的阻塞IO更大固定的開銷。如果該過程無法提供可以交錯的附加IO,那麼通過支付非阻塞設置就沒有任何好處。 (實際上,不恰當的非阻塞IO的最大代價只是增加了代碼的複雜性,除此之外,這個主題主要是一個思考練習。)

在阻塞IO下,我們依靠操作系統來安排這些進程可以取得進展。這就是操作系統設計的目的。

在非阻塞IO,我們有更大的安裝成本,而且可以共享進程的資源和交錯的工作線程之間。因此,非阻塞IO適用於爲多個獨立活動(如Web服務器)提供服務的任何進程。所獲得的吞吐量遠遠優於非阻塞IO的固定成本開銷。

+0

軟件可能無法通過使用非阻塞I/O提高吞吐量,但它總是提高*響應*。是的,你應該阻止,但它應該是一個阻塞調用,等待各種事件,被忽略,導致用戶輸入不阻塞I/O調用,直到I/O完成。 'select','poll','aio_suspend'都是例子。您說「如果進程無法提供可以交錯的附加IO」,但始終至少有一個額外的輸入可能發生......用戶請求退出。 –

+0

@ BenVoigt的確如此。交互式應用程序不應無限期地阻止,例如信號量應該使用超時。也就是說,即使在執行阻塞操作時,posix後端服務也可以接收信號。總而言之,你提出了一個要記住的好點 - 謝謝。 –

13

pollselect調用(由Basile Starynkevitch在評論中提到)或信號量(由Als在答案中提到)是根據情況等待請求的正確方法。在沒有pollselect的操作系統上,應該有類似的東西。

由於以下原因,sleep,YieldProcessorsched_yield都不是這樣做的正確方法。

YieldProcessorsched_yield僅將進程移動到可運行隊列的末尾,但保留它可運行。其效果是,他們允許在相同或更高優先級的其他進程來執行,但是,當這些工序均由內部完成(或者,如果是沒有的),然後調用YieldProcessorsched_yield繼續運行的過程。這會導致兩個問題。一個是較低優先級的進程仍然不會運行。另一個原因是這會導致處理器一直在運行,使用能量。我們希望操作系統能夠識別何時不需要運行進程並將處理器置於低功耗狀態。

sleepsleep可能會允許這種低功耗狀態,但它會在下一個請求進入前玩多長時間的猜謎遊戲,它會在沒有需要時重複喚醒處理器,並且會使進程響應速度變慢因爲該過程將持續休眠,直到請求時間到期,即使有請求被服務。

pollselect電話的設計正是這種情況。他們告訴操作系統這個進程想要服務一個來自其I/O通道之一的請求,但沒有工作要做。這允許操作系統將進程標記爲不可運行,並且如果合適的話將處理器置於低功耗狀態。

使用信號量提供了相同的行爲,不同之處在於以喚醒處理的信號來自另一個處理提高在I/O通道所產生的信號量,而不是活性。當信號做某些工作以這種方式到達時,信號量是合適的;只需使用poll中的任意一個或信號量更適合您的情況。

poll,select或信號量導致內核模式調用的批評是無關緊要的,因爲其他方法也會導致內核模式調用。一個過程不能獨立睡眠;它必須調用操作系統來請求它。同樣,YieldProcessorsched_yield向操作系統發出請求。