3.6.2.阻塞式IO的困境
本節通過實例代碼運行結果,讓大家看到在並發式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的困境