linux -- read(), write()

read()函數??

2011-03-23 16:28:37|??分類:?linux?|??標簽:?|字號?訂閱


read
函數從打開的設備或文件中讀取數據。

#include <unistd.h>    
ssize_t read(int fd, void *buf, size_t count);  
返回值:成功返回讀取的字節數,出錯返回-1并設置errno,如果在調read之前已到達文件末尾,則這次read返回0
參數
count
是請求讀取的字節數,讀上來的數據保存在緩沖區buf中,同時文件的當前讀寫位置向后移。注意這個讀寫位置和使用C標準I/O庫時的讀寫位置有可能不同,這個讀寫位置是記在內核中的,而使用C標準I/O庫時的讀寫位置是用戶空間I/O緩沖區中的位置。比如用fgetc讀一個字節,fgetc有可能從內核中預讀1024個字節到I/O緩沖區中,再返回第一個字節,這時該文件在內核中記錄的讀寫位置是1024,而在FILE結構體中記錄的讀寫位置是1。注意返回值類型是ssize_t,表示有符號的size_t,這樣既可以返回正的字節數、0(表示到達文件末尾)也可以返回負值-1(表示出錯)。
read函數返回時,返回值說明了buf中前多少個字節是剛讀上來的。有些情況下,實際讀到的字節數(返回值)會小于請求讀的字節數count,例如:讀常規文件時,在讀到count個字節之前已到達文件末尾。例如,距文件末尾還有30個字節而請求讀100個字節,則read返回30,下次read將返回0。

從終端設備讀,通常以行為單位,讀到換行符就返回了。

從網絡讀,根據不同的傳輸層協議和內核緩存機制,返回值可能小于請求的字節數,后面socket編程部分會詳細講解。


write
函數向打開的設備或文件中寫數據。

#include <unistd.h>   
ssize_t write(int fd, const void *buf, size_t count);  
返回值:成功返回寫入的字節數,出錯返回-1并設置errno寫常規文件時,write的返回值通常等于請求寫的字節數
count,而向終端設備或網絡寫則不一定。

讀常規文件是不會阻塞的,不管讀多少字節,read一定會在有限的時間內返回。從終端設備或網絡讀則不一定,如果從終端輸入的數據沒有換行符,調用read讀終端設備就會阻塞,如果網絡上沒有接收到數據包,調用read從網絡讀就會阻塞,至于會阻塞多長時間也是不確定的,如果一直沒有數據到達就一直阻塞在那里。同樣,寫常規文件是不會阻塞的,而向終端設備或網絡寫則不一定。

現在明確一下阻塞(Block)這個概念。當進程調用一個阻塞的系統函數時,該進程被置于睡眠(Sleep)狀態,這時內核調度其它進程運行,直到該進程等待的事件發生了(比如網絡上接收到數據包,或者調用sleep指定的睡眠時間到了)它才有可能繼續運行。與睡眠狀態相對的是運行(Running)狀態,在Linux內核中,處于運行狀態的進程分為兩種情況:


正在被調度執行。CPU處于該進程的上下文環境中,程序計數器(eip)里保存著該進程的指令地址,通用寄存器里保存著該進程運算過程的中間結果,正在執行該進程的指令,正在讀寫該進程的地址空間。


就緒狀態。該進程不需要等待什么事件發生,隨時都可以執行,但CPU暫時還在執行另一個進程,所以該進程在一個就緒隊列中等待被內核調度。系統中可能同時有多個就緒的進程,那么該調度誰執行呢?內核的調度算法是基于優先級和時間片的,而且會根據每個進程的運行情況動態調整它的優先級和時間片,讓每個進程都能比較公平地得到機會執行,同時要兼顧用戶體驗,不能讓和用戶交互的進程響應太慢。


下面這個小程序從終端讀數據再寫回終端。


例 28.2. 阻塞讀終端


#include <unistd.h>  
#include <stdlib.h>    
int main(void)  {
   char buf[10];
   int n;
   n = read(STDIN_FILENO, buf, 10);
   if (n < 0) {
    perror("read STDIN_FILENO");
    exit(1);
   }
   write(STDOUT_FILENO, buf, n);
   return 0;  }


執行結果如下:

$ ./a.out   hello(回車)  hello  
$ ./a.out   hello world(回車)  hello 
worl$ d  bash: d: command not found

第一次執行a.out的結果很正常,而第二次執行的過程有點特殊,現在分析一下:


Shell進程創建a.out進程,a.out進程開始執行,而Shell進程睡眠等待a.out進程退出。



a.out調用read時睡眠等待,直到終端設備輸入了換行符才從read返回,read只讀走10個字符,剩下的字符仍然保存在內核的終端設備輸入緩沖區中。


a.out
進程打印并退出,這時Shell進程恢復運行,Shell繼續從終端讀取用戶輸入的命令,于是讀走了終端設備輸入緩沖區中剩下的字符d和換行符,把它當成一條命令解釋執行,結果發現執行不了,沒有d這個命令。


如果在open一個設備時指定了O_NONBLOCK標志,read/write就不會阻塞。以read為例,如果設備暫時沒有數據可讀就返回-1,同時置errno為EWOULDBLOCK(或者EAGAIN,這兩個宏定義的值相同),表示本來應該阻塞在這里(would block,虛擬語氣),事實上并沒有阻塞而是直接返回錯誤,調用者應該試著再讀一次(again)。這種行為方式稱為輪詢(Poll),調用者只是查詢一下,而不是阻塞在這里死等,這樣可以同時監視多個設備:

while(1) {
非阻塞read(設備1);
if(設備1有數據到達)
? 處理數據;
非阻塞read(設備2);
if(設備2有數據到達)
? 處理數據;
...
}

如果
read(設備1)
是阻塞的,那么只要設備1沒有數據到達就會一直阻塞在設備1的
read
調用上,即使設備2有數據到達也不能處理,使用非阻塞I/O就可以避免設備2得不到及時處理。

非阻塞I/O有一個缺點,如果所有設備都一直沒有數據到達,調用者需要反復查詢做無用功,如果阻塞在那里,操作系統可以調度別的進程執行,就不會做無用功了。在使用非阻塞I/O時,通常不會在一個while循環中一直不停地查詢(這稱為Tight Loop),而是每延遲等待一會兒來查詢一下,以免做太多無用功,在延遲等待的時候可以調度其它進程執行。

while(1) {
   非阻塞read(設備1);
   if(設備1有數據到達)    處理數據;
   非阻塞read(設備2);
   if(設備2有數據到達)    處理數據;
   ...   sleep(n);
  }

這樣做的問題是,設備1有數據到達時可能不能及時處理,最長需延遲n秒才能處理,而且反復查詢還是做了很多無用功。以后要學習的select(2)函數可以阻塞地同時監視多個設備,還可以設定阻塞等待的超時時間,從而圓滿地解決了這個問題。

以下是一個非阻塞I/O的例子。目前我們學過的可能引起阻塞的設備只有終端,所以我們用終端來做這個實驗。程序開始執行時在0、1、2文件描述符上自動打開的文件就是終端,但是沒有O_NONBLOCK標志。所以就像例 28.2 “阻塞讀終端”一樣,讀標準輸入是阻塞的。我們可以重新打開一遍設備文件/dev/tty(表示當前終端),在打開時指定
O_NONBLOCK標志。


例 28.3. 非阻塞讀終端


#include <unistd.h>  
#include <fcntl.h>  
#include <errno.h>  
#include <string.h>  
#include <stdlib.h>    
#define MSG_TRY "try again\n"    
int main(void)  {
   char buf[10];
   int fd, n;
   fd = open("/dev/tty", O_RDONLY|O_NONBLOCK);
   if(fd<0) {
    perror("open /dev/tty");
    exit(1);
   }
  tryagain:
   n = read(fd, buf, 10);
   if (n < 0) {
    if (errno == EAGAIN) {
     sleep(1);
     write(STDOUT_FILENO, MSG_TRY, strlen(MSG_TRY));
     goto tryagain;
    }
     perror("read /dev/tty");
    exit(1);
   }
   write(STDOUT_FILENO, buf, n);
   close(fd);
   return 0;
  }

以下是用非阻塞I/O實現等待超時的例子。既保證了超時退出的邏輯又保證了有數據到達時處理延遲較小。


例 28.4. 非阻塞讀終端和等待超時


#include <unistd.h> 
#include <fcntl.h>  
#include <errno.h> 
#include <string.h> 
#include <stdlib.h>   
#define MSG_TRY "try again\n"  
#define MSG_TIMEOUT "timeout\n"    
int main(void)  {
   char buf[10];
   int fd, n, i;
   fd = open("/dev/tty", O_RDONLY|O_NONBLOCK);
   if(fd<0) {
    perror("open /dev/tty");
    exit(1);
   } 
  for(i=0; i<5; i++) {
    n = read(fd, buf, 10);
    if(n>=0)     break;
    if(errno!=EAGAIN) {
     perror("read /dev/tty");
     exit(1); 
   } 
   sleep(1);
    write(STDOUT_FILENO, MSG_TRY, strlen(MSG_TRY));
   } 
  if(i==5)
     write(STDOUT_FILENO, MSG_TIMEOUT, strlen(MSG_TIMEOUT));
  else 
    write(STDOUT_FILENO, buf, n);
   close(fd);
   return 0;
  }

轉載于:https://www.cnblogs.com/tianzhiyi/p/5430575.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/458767.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/458767.shtml
英文地址,請注明出處:http://en.pswp.cn/news/458767.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

jquery的$.extend、$.fn.extend、 jQuery.extend( target, object1, [objectN])作用及區別

jQuery為開發插件提拱了兩個方法&#xff0c;分別是&#xff1a; jQuery.fn.extend();jQuery.extend(); 雖然 javascript 沒有明確的類的概念&#xff0c;但是用類來理解它&#xff0c;會更方便。 jQuery便是一個封裝得非常好的類&#xff0c;比如我們用 語句 $("#btn1&…

CATia對計算機配置要求,【2人回答】求CATIA對電腦的詳細配置要求-3D溜溜網

回答&#xff1a;1、內存要求在32G和64G之間。2、硬盤要求選擇7200轉機械硬盤&#xff0c;4k以上分辨&#xff0c;就選擇SSD固態硬盤。3、CPU要求睿頻在4.1GHZ以上&#xff0c;核心在6和8核之間。4、顯卡要求顯存在6GB和11GB之間&#xff0c;位寬要求在192bit和384bit之間。5、…

如何制作自動更新程序?

原文出自&#xff1a;http://blog.csdn.net/metaphysis/article/details/18866631 如何制作自動更新程序&#xff1f; [版權所有 邱秋 2014 metaphysisyeah.net, 轉載請注明出處] 最近為單位寫了一個C/S結構的軟件&#xff0c;這個軟件是工作在單位的局域網內的。為了減輕為程序…

包含JS交互的混淆出錯

2019獨角獸企業重金招聘Python工程師標準>>> 小上司離職&#xff0c;我接手他負責的項目&#xff0c;進行版本更新的時候&#xff0c;在生成jar包測試的時候&#xff0c;點擊按鈕沒有反應&#xff0c;頁面是webview&#xff0c;按鈕則是與js交互&#xff0c;logcat打…

計算機常用代碼大全,常用電腦命令大全【圖文】

導語 &#xff1a;電腦&#xff0c;這個在前幾年貌似還離我們非常遙遠的詞匯&#xff0c;現在隨著信息化社會的不斷發展&#xff0c;已經走進了我們的千家萬戶。現在每一家新 裝修 &#xff0c;它都作為一種必備的家用電器來使用。由此可見電腦對我們 現代 人的重要性。但電腦畢…

細數技術指標-[轉載]

技術指標類別龐雜&#xff0c;要一一學全&#xff0c;基本不可能&#xff0c;也沒有這個必要。我們只要掌握幾個常用的指標&#xff0c;了解它們的原理&#xff0c;從而舉一反三&#xff0c;就足夠了。其實任何一種技術指標都是從形態、價格、量、時間這四項出發的&#xff0c;…

[javaSE] 看博客學習java并發編程

共享性 多線程操作同一個數據&#xff0c;產生線程安全問題 新建一個類ShareData 設計一個int 型的成員變量count 設計一個成員方法addCount()&#xff0c;把count變量 在main函數中開啟多個線程操作這個成員變量&#xff0c;在main函數里 獲取ShareData對象&#xff0c;new 出…

GetProcAddress() LoadLibrary() DLL

GetProcAddress函數檢索指定的動態鏈接庫(DLL)中的輸出庫函數地址。 函數原型&#xff1a; FARPROC GetProcAddress( HMODULE hModule, // DLL模塊句柄 LPCSTR lpProcName // 函數名 ); 參數&#xff1a; hModule [in] 包含此函數的DLL模塊的句柄。LoadLibrary、AfxLoadLibrary…

小學計算機輸入法主題教研設計,《拼音輸入法》教學設計.doc

10.拼音輸入法【教材分析】《拼音輸入法》是浙江攝影出版社出版的新版《小學信息技術》三年級下冊第三單元第10課。信息技術是一門技能課&#xff0c;學以致用是技能課的教學目的&#xff0c;相對來說&#xff0c;在小學生的學習和生活中&#xff0c;用到這項技能的地方還比較少…

圖論測試題(一)第一題:longest

第一題&#xff1a;longest 烏托邦有n個城市&#xff0c;某些城市之間有公路連接。任意兩個城市都可以通過公路直接或者間接到達&#xff0c;并且任意兩個城市之間有且僅有一條路徑&#xff08;What does this imply? A tree!&#xff09;。 每條公路都有自己的長度&#xff0…

RTC實時時鐘驅動

RTC&#xff08;Real-Time Clock)實時時鐘為操作系統提供了一個可靠的時間&#xff0c;并且在斷電的情況下&#xff0c;RTC實時時鐘也可以通過電池供電&#xff0c;一直運行下去。 RTC通過STRB/LDRB這兩個ARM指令向CPU傳送8位數據&#xff08;BCD碼&#xff09;。數據包括秒&am…

Compass樣式重置

1. 全局樣式重置 main.scss文件插入 import "compass/reset"; 對應的生成css為 html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, sa…

計算機表格復制粘貼后不變,excel表格復制粘貼后格式不變

Excel使用過程中經常需要將一個表格內容復制粘貼到其他表格中去。如果原始表格設置了行高和列寬&#xff0c;選中要復制的區域復制后&#xff0c;當在其他表格選擇一個單元格進行粘貼時&#xff0c;行高和列寬就都變了。下面介紹excel表格復制粘貼后格式不變的操作方法。excel表…

C++ Primer章課后編程問題

1、代碼#include<iostream> int main() {using namespace std;int num1;int num2;int total0;cout << "請輸入開始數字\n";cin >> num1;cout << "請輸入結束數字\n";cin >> num2;for (num1; num1<num2; num1)total num1…

vps搭建網站服務器,vps如何架設網站服務器

彈性云服務器 ECS彈性云服務器(Elastic Cloud Server)是一種可隨時自助獲取、可彈性伸縮的云服務器&#xff0c;幫助用戶打造可靠、安全、靈活、高效的應用環境&#xff0c;確保服務持久穩定運行&#xff0c;提升運維效率三年低至5折&#xff0c;多種配置可選了解詳情手工部署D…

vs 常見問題匯總

vs添加對dll的引用 我們在使用vs進行開發調試的時候經常會遇到一個問題&#xff0c;就是當我們的主工程引用到其他工程更新的dll&#xff08;我們經常采用copy到工程目錄的方法&#xff09;、亦或者當我們的多個工程引用到同一個dll文件的時候&#xff0c;我們怎么來配置&#…

斯柯達柯珞克顯示服務器錯誤,斯柯達柯珞克原來還有四驅的版本,不信你看!...

?有望推出四驅版本?專利圖已經曝光?外觀沒有變化斯柯達柯珞克大家應該不會特別陌生&#xff0c;雖然它在前兩個月才正式上市&#xff0c;不過作為一款合資的緊湊型SUV來說&#xff0c;它的關注度還是不錯的。銷量上&#xff0c;4月份交出了2668輛的成績&#xff0c;雖然還不…

javascript實例——鼠標特效篇(包含2個實例)

鼠標是現在電腦的基本配置之一&#xff0c;也是最常用的輸入命令的工具之一。本文將將一些與鼠標有關系的特效。 1、跟隨鼠標移動的彩色星星 如題&#xff0c;會根據鼠標的移動而移動&#xff0c;并在鼠標周圍隨機來回移動&#xff0c;讓人感覺在放大縮小。根據書上的代碼做了一…

Perforce使用指南_forP4V

第一章 前言 Perforce SCM System是一款構建于可伸縮客戶/服務器結構之上的軟件配置管理工具。僅僅應用 TCP/IP&#xff0c;開發人員就能夠通過多種Perforce客戶端&#xff08;幾種平臺的GUI、WEB、或命令行&#xff09;訪問 Perforce服務器。Perforce能夠被快速和容易地部署…

sql語句示例

sql語句示例&#xff1a; 選區指定的列 select 圖書編號,圖書名稱 from 圖書查詢全部信息 select * from 圖書查詢信息之后更改所獲得的列的名稱 select 姓名 as 用戶名, 電話 as 聯系電話 from 用戶也可以這樣 select 用戶名姓名,聯系電話電話 from 用戶對某些列進行計筭后在顯…