1. 程式人生 > >3.6.2.阻塞式IO的困境

3.6.2.阻塞式IO的困境

實現 鼠標移動 不知道 實例代碼 memset clu 問題 TE pre

本節通過實例代碼運行結果,讓大家看到在並發式IO訪問時非阻塞IO遭遇的困境,由此引入非阻塞式IO。

3.6.2.1、程序中讀取鍵盤

include

include

include

int main(void)
{
// 讀取鍵盤
// 鍵盤就是標準輸入,stdin
char buf[100];

memset(buf, 0, sizeof(buf));
printf("before read.\n");
read(0, buf, 5);
printf("讀出的內容是:[%s].\n", buf);

return 0;

}

運行過程:

./a.out

before read.
進程被阻塞住,因為此時還沒有鍵盤輸入,此時,鍵入一個a,

before read.
a
打印一個a,然後鍵入bcdggggg,

before read.
abcdggggg
因為linux使用行緩存技術。如果在結束,則按一個Enter就可以結束這個函數。(行緩存for直到換行符到了)。
3.6.2.2、程序中讀取鼠標
鍵盤是一個標準輸入設備,所以可以直接打開。但是鼠標不是標準輸入設備,所以要先用open打開鼠標鼠標。

ls /dev/input

by-id by-path event0 event1 event2 event3 mice mouse0 mouse1

cat /dev/input/mouse1

如何判斷哪個是我們的鼠標,只要cat /dev/input/mouse1,就會阻塞,然後移動鼠標,如果有打印出來的東西,就是當前鼠標設備。

include

include

include

include <sys/types.h>

include <sys/stat.h>

include

int main(void)
{
// 讀取鼠標
int fd = -1;
char buf[200];

fd = open("/dev/input/mouse1", O_RDONLY);
if (fd < 0)
{
    perror("open:");
    return -1;
}

memset(buf, 0, sizeof(buf));
printf("before 鼠標 read.\n");
read(fd, buf, 50);
printf("鼠標讀出的內容是:[%s].\n", buf);

return 0;

}

結果分析:先前打印before 鼠標 read.阻塞住,直到鼠標移動,才打印出亂碼[(?]。打印出亂碼的原因是鼠標移動輸入二進制,但是終端以ASCII方式解析。
3.6.2.3、程序中同時讀取鍵盤和鼠標(有問題沒想明白)

include

include

include

include <sys/types.h>

include <sys/stat.h>

include

int main(void)
{
// 讀取鼠標
int fd = -1;
char buf[200];

fd = open("/dev/input/mouse1", O_RDONLY);
if (fd < 0)
{
    perror("open:");
    return -1;
}

memset(buf, 0, sizeof(buf));
printf("before 鼠標 read.\n");
read(fd, buf, 50);
printf("鼠標讀出的內容是:[%s].\n", buf);


// 讀鍵盤
memset(buf, 0, sizeof(buf));
printf("before 鍵盤 read.\n");
read(0, buf, 5);
printf("鍵盤讀出的內容是:[%s].\n", buf);


return 0;

}
3.6.2.4、問題分析

總結:阻塞式IO:函數調用會被阻塞。本質是當前進程調用了函數,進入內核裏面去後,因為當前進程的執行條件不滿足,內核無法裏面完成操作,就掛起這個進程,去執行其他進程。默認使用阻塞IO。是linux系統的常態。但是阻塞式IO有一個缺點,比如說如果要同時讀取鼠標和鍵盤的輸入(不知道鼠標動還是鍵盤動),就會遇見很糟糕的情況,這時我們可以用並發式IO解決,有三種方法可以實現:非阻塞IO,多路復用IO,異步IO。
並發式IO可以解決這個問題

3.6.2.阻塞式IO的困境