Windows XP Windows 7 Windows 2003 Windows Vista Windows教程綜合 Linux 系統教程
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟件教程
 Windows教程網 >> Linux系統教程 >> Linux教程 >> Linux下的sleep函數,fflush函數和緩沖區問題

Linux下的sleep函數,fflush函數和緩沖區問題

日期:2017/2/7 14:31:14      編輯:Linux教程
 

//---------------------- sleep()函數

函數名: sleep
功 能: 執行掛起一段時間
用 法: unsigned int sleep(unsigned int seconds);
程序例:

#include <unistd.h>
#include <stdio.h>

int main(void)
{
int i;

for (i=1; i<5; i++)
{
printf("Sleeping for %d seconds\n", i);
sleep(i);
}
return 0;
}


另:

VC++中的Sleep函數原型為:

void Sleep(
DWORD dwMilliseconds
);

linux下的sleep函數原型為:

unsigned int sleep(unsigned int seconds);

MFC中的是微秒,linux下的是秒。linux下用微秒的線程休眠函數是:

void usleep(unsigned long usec);
int usleep(unsigned long usec); /* SUSv2 */

或者用select函數+timeval結構也可以(最多精確到微秒),

或者用pselect函數+timespec(可以精確到納秒,足夠精確了!)

//----------------fflush() 函數


以下是 C99 對 fflush 函數的定義:


int fflush(FILE *stream);


如果 stream 指向輸出流或者更新流(update stream),並且這個更新流
最近執行的操作不是輸入,那麼 fflush 函數將把這個流中任何待寫數據傳送至
宿主環境(host environment)寫入文件。否則,它的行為是未定義的。

原文如下:


int fflush(FILE *stream);

 

If stream points to an output stream or an update stream in which
the most recent operation was not input, the fflush function causes
any unwritten data for that stream to be delivered to the host environment
to be written to the file; otherwise, the behavior is undefined.


其中,宿主環境可以理解為操作系統或內核等。


由此可知,如果 stream 指向輸入流(如 stdin),那麼 fflush 函數的行為是不確定的。故而使用 fflush(stdin) 是不正確的,至少是移植性不好的。


fflush庫函數的作用是把文件流裡的所有未寫出數據立刻寫出。例如,你可以用這個函數來確保在試圖讀入一個用戶響應之前,先向終端送出一個交互提示符。使用這個函數還可以確保在程序繼續執行之前重要的數據都已經被寫到磁盤上。有時在調試程序時,還可以用它來確定程序是正在寫數據而不是被掛起了。注意,調用fclose函數隱含執行了一次flush操作,所以不必在fclose之前調用fflush。

應該少用這個函數,書上說fflush只是用於異常情況,正常情況應該用fclose與EXIT來刷新輸出緩沖區。LINUX下更不能這麼用的。

*

 

 

 

 

*

//------------------ 緩沖區問題

*

詳細內容可見:關於流和緩沖區的理解以及一般標准輸入問題的解決方法小結

*

*

 

 

標准I / O提供緩存的目的是盡可能減少使用read和write調用的數量。它也對每個I / O流自動地進行緩存管理,避免了應用程序需要考慮這一點所帶來的麻煩。不幸的是,標准I / O庫令人最感迷惑的也是它的緩存。不同類型緩存往往使人在進行I/O操作時不知所措。標准I / O提供了三種類型的緩存:全緩存、行緩存、無緩存。


說的最清楚的要數Stevens的《UNIX環境高級編程》了,以下摘自Stevens的《UNIX環境高級編程》第五章:

 

//******************

標准I / O提供了三種類型的緩存:
(1) 全緩存。在這種情況下,當填滿標准I / O緩存後才進行實際I / O操作。對於駐在磁盤上的文件通常是由標准I / O庫實施全緩存的。在一個流上執行第一次I / O操作時,相關標准I / O函數通常調用m a l l o c(見7 . 8節)獲得需使用的緩存。
術語刷新( f l u s h)說明標准I / O緩存的寫操作。緩存可由標准I / O例程自動地刷新(例如當填滿一個緩存時),或者可以調用函數ff l u s h刷新一個流。值得引起注意的是在U N I X環境中,刷新有兩種意思。在標准I / O庫方面,刷新意味著將緩存中的內容寫到磁盤上(該緩存可以只是局部填寫的)。在終端驅動程序方面(例如在第11章中所述的t c f l u s h函數),刷新表示丟棄已存在緩存中的數據。
(2) 行緩存。在這種情況下,當在輸入和輸出中遇到新行符時,標准I / O庫執行I / O操作。這允許我們一次輸出一個字符(用標准I/O fputc函數),但只有在寫了一行之後才進行實際I / O操作。當流涉及一個終端時(例如標准輸入和標准輸出),典型地使用行緩存。對於行緩存有兩個限制。第一個是:因為標准I / O庫用來收集每一行的緩存的長度是固定的,所以只要填滿了緩存,那麼即使還沒有寫一個新行符,也進行I / O操作。第二個是:任何時候只要通過標准輸入輸出庫要求從( a )一個不帶緩存的流,或者( b )一個行緩存的流(它預先要求從內核得到數據)得到輸入數據,那麼就會造成刷新所有行緩存輸出流。在( b )中帶了一
個在括號中的說明的理由是,所需的數據可能已在該緩存中,它並不要求內核在需要該數據時才進行該操作。很明顯,從不帶緩存的一個流中進行輸入( ( a )項)要求當時從內核得到數據。
(3) 不帶緩存。標准I / O庫不對字符進行緩存。如果用標准I / O函數寫若干字符到不帶緩存
的流中,則相當於用w r i t e系統調用函數將這些字符寫至相關聯的打開文件上。標准出錯流s t d e r r通常是不帶緩存的,這就使得出錯信息可以盡快顯示出來,而不管它們是否含有一個新行字符。
ANSI C要求下列緩存特征:
(1) 當且僅當標准輸入和標准輸出並不涉及交互作用設備時,它們才是全緩存的。
(2) 標准出錯決不會是全緩存的。
但是,這並沒有告訴我們如果標准輸入和輸出涉及交互作用設備時,它們是不帶緩存的還
是行緩存的,以及標准輸出是不帶緩存的,還是行緩存的。S V R 4和4 . 3 + B S D的系統默認使用下列類型的緩存:
? 標准出錯是不帶緩存的。
? 如若是涉及終端設備的其他流,則它們是行緩存的;否則是全緩存的。

//****************************

*


我們經常要用到標准輸入和輸出,而ANSI C對stdin、stdout和stderr的緩存特征沒有強行的規定,以至於不同的系統可能有不同的stdin、stdout和stderr的緩存特征。目前主要的緩存特征是:stdin和stdout是行緩存;而stderr是無緩存的。

 

Copyright © Windows教程網 All Rights Reserved