日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

高级IO(文件的读写)——并发式IO的解决方案(解决多路阻塞式IO的方案)

發布時間:2023/12/20 编程问答 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 高级IO(文件的读写)——并发式IO的解决方案(解决多路阻塞式IO的方案) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

以下內容源于朱有鵬《物聯網大講堂》課程的學習整理,如有侵權,請告知刪除。


一、并發式IO的解決方案

  • 所謂并發式IO,即上節中提及的鼠標和鍵盤都已經啟動。

1、非阻塞式IO

  • 使用fcntl函數, 將上節中阻塞式的鼠標和鍵盤讀取改為非阻塞式的。
  • 性能不是很好。

#include <stdio.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h>int main(void) {// 讀取鼠標int fd = -1;int flag = -1;char buf[200];int ret = -1;fd = open("/dev/input/mouse1", O_RDONLY | O_NONBLOCK);if (fd < 0){perror("open:");return -1;}// 把0號文件描述符(stdin)變成非阻塞式的flag = fcntl(0, F_GETFL); // 先獲取原來的flagflag |= O_NONBLOCK; // 添加非阻塞屬性fcntl(0, F_SETFL, flag); // 更新flag// 這3步之后,0就變成了非阻塞式的了while (1){// 讀鼠標memset(buf, 0, sizeof(buf));ret = read(fd, buf, 50);if (ret > 0){printf("鼠標讀出的內容是:[%s].\n", buf);}// 讀鍵盤memset(buf, 0, sizeof(buf));ret = read(0, buf, 5);if (ret > 0){printf("鍵盤讀出的內容是:[%s].\n", buf);}}return 0; }/* int main(void) {// 讀取鼠標int fd = -1;char buf[200];fd = open("/dev/input/mouse1", O_RDONLY | O_NONBLOCK);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; } *//* int main(void) {// 讀取鍵盤// 鍵盤就是標準輸入,stdinchar buf[100];int flag = -1;// 把0號文件描述符(stdin)變成非阻塞式的flag = fcntl(0, F_GETFL); // 先獲取原來的flagflag |= O_NONBLOCK; // 添加非阻塞屬性fcntl(0, F_SETFL, flag); // 更新flag// 這3步之后,0就變成了非阻塞式的了memset(buf, 0, sizeof(buf));printf("before read.\n");read(0, buf, 5);printf("讀出的內容是:[%s].\n", buf);return 0; } */

2、多路復用IO

3、異步通知(異步IO)


二、IO多路復用原理

1、何為IO多路復用?

(1)英文為:IO multiplexing

(2)用在什么地方?

  • 用于解決并發式IO,多路阻塞式的。

(3)涉及select函數、poll函數。

  • 兩個函數設計思想一樣,外部特征不一樣。

(4)實現原理:外部阻塞式(select函數本身是阻塞式的),內部非阻塞式自動輪詢select自動輪詢時A,B多路阻塞式IO(鍵盤A,鼠標B,這兩者本身是阻塞式的)。

  • 只要AB至少有一個輸入,則select由阻塞返回。

2、select函數介紹


3、poll函數介紹


4、多路復用實踐

(1)用poll函數實現同時讀取鍵盤鼠標



#include <stdio.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <poll.h>int main(void) {// 讀取鼠標int fd = -1, ret = -1;char buf[200];struct pollfd myfds[2] = {0};fd = open("/dev/input/mouse1", O_RDONLY);if (fd < 0){perror("open:");return -1;}// 初始化我們的pollfdmyfds[0].fd = 0; // 鍵盤myfds[0].events = POLLIN; // 等待讀操作myfds[1].fd = fd; // 鼠標myfds[1].events = POLLIN; // 等待讀操作ret = poll(myfds, fd+1, 10000);if (ret < 0){perror("poll: ");return -1;}else if (ret == 0){printf("超時了\n");}else{// 等到了一路IO,然后去監測到底是哪個IO到了,處理之if (myfds[0].events == myfds[0].revents){// 這里處理鍵盤memset(buf, 0, sizeof(buf));read(0, buf, 5);printf("鍵盤讀出的內容是:[%s].\n", buf);}if (myfds[1].events == myfds[1].revents){// 這里處理鼠標memset(buf, 0, sizeof(buf));read(fd, buf, 50);printf("鼠標讀出的內容是:[%s].\n", buf);}}return 0; }

(2)用select函數實現同時讀取鍵盤鼠標

  • 設置超時時間,即阻塞的時間不能太長,如果很久都沒有IO來激活select,則表明超時了。

#include <stdio.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/select.h> #include <sys/time.h>int main(void) {// 讀取鼠標int fd = -1, ret = -1;char buf[200];fd_set myset;struct timeval tm;//設置超時時間,即阻塞的時間不能太長,如果很久都沒有IO來激活select,則表明超時了。fd = open("/dev/input/mouse1", O_RDONLY);if (fd < 0){perror("open:");return -1;}// 當前有2個fd,一共是fd一個是0// 處理mysetFD_ZERO(&myset);FD_SET(fd, &myset);FD_SET(0, &myset);tm.tv_sec = 10;tm.tv_usec = 0;ret = select(fd+1, &myset, NULL, NULL, &tm);//+1,是因為0~fd,則共有fd+1個文件描述符if (ret < 0)//錯誤{perror("select: ");return -1;}else if (ret == 0)//表明超時{printf("超時了\n");}else//>0表示有一路IO激活了{// 等到了一路IO,然后去監測到底是哪個IO到了,處理之if (FD_ISSET(0, &myset)){// 這里處理鍵盤memset(buf, 0, sizeof(buf));read(0, buf, 5);printf("鍵盤讀出的內容是:[%s].\n", buf);}if (FD_ISSET(fd, &myset)){// 這里處理鼠標memset(buf, 0, sizeof(buf));read(fd, buf, 50);printf("鼠標讀出的內容是:[%s].\n", buf);}}return 0; }

三、異步IO

1、何為異步IO?

(1)幾乎可以認為,異步IO就是操作系統用軟件實現的一套中斷響應系統。類比硬件中斷。

(2)異步IO的工作方法

  • 當前進程注冊一個異步IO事件(使用signal注冊一個信號SIGIO的處理函數),然后當前進程可以正常處理自己的事情;
  • 當異步事件發生后,當前進程會收到一個SIGIO信號,從而執行綁定的處理函數,來處理這個異步事件。

2、涉及的函數

(1)fcntl函數,主要設置異步通知。

  • 涉及的命令有F_GETFL(獲取flag)、F_SETFL、O_ASYNC(表明可以接收異步通知)、F_SETOWN(設置通知誰(一般都是通知當前進程));

(2)signal或sigaction函數(SIGIO)

3、代碼實踐

#include <stdio.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <signal.h>int mousefd = -1;// 綁定到SIGIO信號,在函數內處理異步通知事件 void func(int sig) {char buf[200] = {0};if (sig != SIGIO)return;read(mousefd, buf, 50);printf("鼠標讀出的內容是:[%s].\n", buf); }int main(void) {// 讀取鼠標char buf[200];int flag = -1;mousefd = open("/dev/input/mouse1", O_RDONLY);if (mousefd < 0){perror("open:");return -1;} // 把鼠標的文件描述符設置為可以接受異步IOflag = fcntl(mousefd, F_GETFL);flag |= O_ASYNC;fcntl(mousefd, F_SETFL, flag);// 把異步IO事件的接收進程設置為當前進程fcntl(mousefd, F_SETOWN, getpid());// 注冊當前進程的SIGIO信號捕獲函數signal(SIGIO, func);// 讀鍵盤,在這里是當前進程while (1){memset(buf, 0, sizeof(buf));read(0, buf, 5);printf("鍵盤讀出的內容是:[%s].\n", buf);}return 0; }

四、存儲映射IO


1、反映在mmap函數

  • 把一個文件和一段內存映射起來。比如LCD設備文件和顯存的對應。

2、例子

  • LCD顯示,IPC之共享內存

3、存儲映射IO的特點

(1)共享而不是復制,減少內存操作。

(2)處理大文件時效率高(一般用于視頻處理),小文件不劃算。


總結

以上是生活随笔為你收集整理的高级IO(文件的读写)——并发式IO的解决方案(解决多路阻塞式IO的方案)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。