linux檔案裝置與I/O:read/write函數 與 阻塞 Block

來源:互聯網
上載者:User
一,read 函數從開啟的裝置或檔案中讀取資料

#include <unistd.h>
       ssize_t read(int fd, void *buf, size_t count);
       傳回值:成功返回讀取的位元組數,出錯返回-1並設定errno,如果在調read之前已到達檔案末尾,則這次
read返回0

      讀上來的資料儲存在緩衝區buf 中,同時檔案的當前讀寫位置向後移。注意這個讀寫位置和使用C標準I/O庫時的讀寫位置有可能不同,這個讀寫位置是記在核心中的,而使用C標準I/O庫時的讀寫位置是使用者空間I/O緩衝區中的位置。

二,write 函數向開啟的裝置或檔案中寫資料

    #include <unistd.h>
       ssize_t write(int fd, const void *buf, size_t count);
       傳回值:成功返回寫入的位元組數,出錯返回-1並設定errno

三,阻塞(Block)
       當進程調用一個阻塞的系統函數時,該進程被置於睡眠(Sleep)狀態,這時核心調度其它進程運行,直到該進程等待的事件發生了(比如網路上接收到資料包,或者調用sleep 指定的睡眠時間到了)它才有可能繼續運行。
       睡眠狀態相對的是運行(Running)狀態,在Linux核心中,處於運行狀態的進程分為兩種情況:正在被調度執行和就緒狀態。

   假設同時監視多個裝置,如果read(裝置1)是阻塞的,那麼只要裝置1沒有資料到達就會一直阻塞在裝置1的read 調用上,即使裝置2有資料到達也不能處理,使用非阻塞I/O就可以避免裝置2得不到及時處理。
   在open 一個裝置時指定了O_NONBLOCK 標誌,read / write 就不會阻塞。以read 為例,如果裝置暫時沒有資料可讀就返回-1,同時置errno 為EWOULDBLOCK(或者EAGAIN,這兩個宏定義的值相同),表示本來應該阻塞在這裡(would block,虛擬語氣),事實上並沒有阻塞而是直接返回錯誤,調用者應該試著再讀一次(again)。這種行為方式稱為輪詢(Poll),調用者只是查詢一下,而不是阻塞在這裡死等,這樣可以同時監視多個裝置。

      非阻塞I/O有一個缺點,如果所有裝置都一直沒有資料到達,調用者需要反覆查詢做無用功,如果阻塞在那裡,作業系統可以調度別的進程執行,就不會做無用功了。
          select(2) 函數可以阻塞地同時監視多個裝置,還可以設定阻塞等待的逾時時間,從而圓滿地解決了這個問題。

四,阻塞與非阻塞讀終端執行個體

非阻塞讀終端

   程式開始執行時在0、1、2檔案描述符上自動開啟的檔案就是終端,但是沒有O_NONBLOCK 標誌。所以,讀標準輸入是阻塞的。我們可以重新開啟一遍裝置檔案/dev/tty (表示當前終端),在開啟時指O_NONBLOCK 標誌。

#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;
}

阻塞讀終端

#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;}
原文:http://blog.chinaunix.net/space.php?uid=22086460&do=blog&id=404970

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.