当前位置: 首页 > news >正文

嵌入式系统学习Day31(多路IO复用)

IO模型
1、阻塞IO
2、非阻塞IO EAGAIN 忙等待 errno
3、信号驱动IOSIGIO 用的相对少(了解)
4、并行模型进程,线程
5, IO多路复用 select、poll、epoll
1、阻塞IO ===》最常用 默认设置
2、非阻塞IO ===》在阻塞IO的基础上调整其为不再阻塞等待。
在程序执行阶段调整文件的执行方式为非阻塞:
===》fcntl(===>动态调整文件的阻塞属性
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, .. /* arg */ );
功能:修改指定文件的属性信息。
参数:fd 要调整的文件描述符
cmd 要调整的文件属性宏名称
可变长的属性值参数。
返回值:成功不一定,看cmd
失败-1;

select
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
void FD_CLR(int fd, fd_set *set); 
int FD_ISSET(int fd, fd_set *set);
void FD_SET(int fd, fd_set *set); 
void FD_ZERO(fd_set *set);
select的调用一般要注意几点:
readfds等是指针结果参数,会被函数修改,所以一般会另外定义一个allread_fdset,保持全部要监听读的句柄,将它的拷贝传递给select函数,返回可读的句柄集合,类型fdset
支持赋值运算符=;

要注意计算nfds,当新增监听句柄时比较容易修改,当减少监听句柄时较麻烦些,如果要精确修改需要遍历或者采用最大堆等数据结构维护这个句柄集,以方便的找到第二大的
句柄,或者干脆在减少监听句柄时不管nfds ;
③ timeout如果为NULL表示阻塞等,如果timeout指向的时间为O,表示非阻塞,否则表示select的超时时间;
④ select返回-1表示错误,返回0表示超时时间到没有监听到的事件发生,返回正数表示监听到的所有事件数(包括可读,可写,异常),通常在处理事件时
会利用这个返回值来提高效率,避免不必要的事件触发检查。(比如总共只有一个事件,已经在可读集合中处理了一个事件,则可写和异常就没必要再去遍历句柄集
判断是否发生事件了);
③ Linux的实现中select返回时会将timeout修改为剩余时间,所以重复使用timeout需要注意。
select的缺点在于:
① 由于描述符集合set的限制,每个set最多只能监听FD_SETSIZE(在Linux上是1024)个句柄(不同机器可能不一样);
② 返回的可读集合是个fdset类型,需要对所有的监听读句柄一一进行FD_ISSET的测试来判断是否可读;

nfds的存在就是为了解决select的效率问题(select遍历nfds个文件描述符,判断每个描述符是否是自己关心的,对关心的描述符判断是否发生事件)。但是解决不彻底,比如如
果只监听0和1000两个句柄,select需要遍历1001个句柄来检查事件。

1.阻塞模型blockIO

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char *argv[])
{int ret = mkfifo("myfifo", 0666);if (-1 == ret){if (EEXIST == errno){}else{perror("mkfifo error\n");return 1;}}int fd = open("myfifo", O_WRONLY);if (-1 == fd){perror("open error\n");return 1;}while (1){char buf[512] = "hello,this is fifo tested...\n";write(fd, buf, strlen(buf) + 1);sleep(3);}close(fd);return 0;
}
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char *argv[])
{int ret = mkfifo("myfifo", 0666);if (-1 == ret){if (EEXIST == errno){}else{perror("mkfifo error\n");return 1;}}int fd = open("myfifo", O_RDONLY);if (-1 == fd){perror("open error\n");return 1;}while (1){char buf[512] = {0};read(fd, buf, sizeof(buf));printf("fifo :%s\n", buf);bzero(buf,sizeof(buf));fgets(buf,sizeof(buf),stdin);printf("terminal:%s",buf);fflush(stdout);}close(fd);// remove("myfifo");return 0;
}

2.非阻塞模型nonblockIO

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char *argv[])
{int ret = mkfifo("myfifo", 0666);if (-1 == ret){if (EEXIST == errno){}else{perror("mkfifo error\n");return 1;}}int fd = open("myfifo", O_WRONLY);if (-1 == fd){perror("open error\n");return 1;}while (1){char buf[512] = "hello,this is fifo tested...\n";write(fd, buf, strlen(buf) + 1);sleep(3);}close(fd);return 0;
}
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char *argv[])
{int ret = mkfifo("myfifo", 0666);if (-1 == ret){if (EEXIST == errno){}else{perror("mkfifo error\n");return 1;}}int fd = open("myfifo", O_RDONLY);if (-1 == fd){perror("open error\n");return 1;}int flag = fcntl(fd, F_GETFL, 0);fcntl(fd, F_SETFL, flag | O_NONBLOCK);flag = fcntl(fileno(stdin), F_GETFL, 0);fcntl(0, F_SETFL, flag | O_NONBLOCK);while (1){char buf[512] = {0};if (read(fd, buf, sizeof(buf)) > 0){printf("fifo :%s\n", buf);}bzero(buf, sizeof(buf));if (fgets(buf, sizeof(buf), stdin)){printf("terminal:%s", buf);fflush(stdout);}}close(fd);// remove("myfifo");return 0;
}

3.信号驱动IO

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char *argv[])
{int ret = mkfifo("myfifo", 0666);if (-1 == ret){if (EEXIST == errno){}else{perror("mkfifo error\n");return 1;}}int fd = open("myfifo", O_WRONLY);if (-1 == fd){perror("open error\n");return 1;}while (1){char buf[512] = "hello,this is fifo tested...\n";write(fd, buf, strlen(buf) + 1);sleep(3);}close(fd);return 0;
}
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int fd;
void myhandle(int num)
{char buf[512] = {0};read(fd, buf, sizeof(buf));printf("fifo :%s\n", buf);
}
int main(int argc, char *argv[])
{signal(SIGIO, myhandle);int ret = mkfifo("myfifo", 0666);if (-1 == ret){if (EEXIST == errno){}else{perror("mkfifo error\n");return 1;}}fd = open("myfifo", O_RDONLY);if (-1 == fd){perror("open error\n");return 1;}int flag = fcntl(fd, F_GETFL);fcntl(fd, F_SETFL, flag | O_ASYNC);fcntl(fd, F_SETOWN, getpid());while (1){char buf[512] = {0};bzero(buf, sizeof(buf));fgets(buf, sizeof(buf), stdin);printf("terminal:%s", buf);fflush(stdout);}close(fd);// remove("myfifo");return 0;
}

4.IO多路复用

1.select

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char *argv[])
{int ret = mkfifo("myfifo", 0666);if (-1 == ret){if (EEXIST == errno){}else{perror("mkfifo error\n");return 1;}}int fd = open("myfifo", O_WRONLY);if (-1 == fd){perror("open error\n");return 1;}while (1){char buf[512] = "hello,this is fifo tested...\n";write(fd, buf, strlen(buf) + 1);sleep(3);}close(fd);return 0;
}
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
/* According to POSIX.1-2001, POSIX.1-2008 */
#include <sys/select.h>/* According to earlier standards */
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>int main(int argc, char *argv[])
{int ret = mkfifo("myfifo", 0666);if (-1 == ret){if (EEXIST == errno){}else{perror("mkfifo error\n");return 1;}}int fd = open("myfifo", O_RDONLY);if (-1 == fd){perror("open error\n");return 1;}// 1 create setfd_set rd_set,tmp_set;  // read setFD_ZERO(&rd_set);FD_ZERO(&tmp_set);// 2 add fdFD_SET(0, &tmp_set);FD_SET(fd, &tmp_set);while (1){rd_set = tmp_set;select(fd + 1, &rd_set, NULL, NULL, NULL);char buf[512] = {0};if (FD_ISSET(fd,&rd_set)){read(fd, buf, sizeof(buf));printf("fifo :%s\n", buf);}if (FD_ISSET(0, &rd_set)){bzero(buf, sizeof(buf));fgets(buf, sizeof(buf), stdin);printf("terminal:%s", buf);fflush(stdout);}}close(fd);// remove("myfifo");return 0;
}

2.epoll

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char *argv[])
{int ret = mkfifo("myfifo", 0666);if (-1 == ret){if (EEXIST == errno){}else{perror("mkfifo error\n");return 1;}}int fd = open("myfifo", O_WRONLY);if (-1 == fd){perror("open error\n");return 1;}while (1){char buf[512] = "hello,this is fifo tested...\n";write(fd, buf, strlen(buf) + 1);sleep(3);}close(fd);return 0;
}
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/epoll.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>int add_fd(int epfd, int fd)
{struct epoll_event ev;ev.events = EPOLLIN;ev.data.fd = fd;int ret = epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev);if (-1 == ret){perror("add fd");return 1;}
}
int main(int argc, char *argv[])
{int ret = mkfifo("myfifo", 0666);if (-1 == ret){if (EEXIST == errno){}else{perror("mkfifo error\n");return 1;}}int fd = open("myfifo", O_RDONLY);if (-1 == fd){perror("open error\n");return 1;}struct epoll_event rev[2];// 1 create setint epfd = epoll_create(2);if (-1 == epfd){perror("epoll_create");return 1;}// 2 add fdadd_fd(epfd, 0);add_fd(epfd, fd);while (1){char buf[512] = {0};int ep_ret = epoll_wait(epfd, rev, 2, -1);for (int i = 0; i < ep_ret; i++){if (rev[i].data.fd == fd){read(fd, buf, sizeof(buf));printf("fifo :%s\n", buf);}else if (0 == rev[i].data.fd){bzero(buf, sizeof(buf));fgets(buf, sizeof(buf), stdin);printf("terminal:%s", buf);fflush(stdout);}}}close(fd);// remove("myfifo");return 0;
}

http://www.xdnf.cn/news/1465507.html

相关文章:

  • Android Studio新版本编译release版本apk实现
  • 在Ubuntu 20.04的服务器上查找的服务器的IP地址
  • 2025最全的软件测试面试八股文(含答案+文档)
  • 属性关键字
  • Kubernetes(k8s) po 配置持久化挂载(nfs)
  • Ansible 角色使用指南
  • js设计模式-状态模式
  • 腾讯最新开源HunyuanVideo-Foley本地部署教程:端到端TV2A框架,REPA策略+MMDiT架构,重新定义视频音效新SOTA!
  • 2025精选5款AI视频转文字工具,高效转录秒变文字!
  • MySQL集群——主从复制
  • MongoDB 源码编译与调试:深入理解存储引擎设计
  • solidity的高阶语法
  • 【Linux】网络安全管理:SELinux 和 防火墙联合使用 | Redhat
  • 红黑树 + 双链表最小调度器原型
  • 【JMeter】分布式集群压测
  • 解锁上下文的力量:大型语言模型中的上下文工程全解析
  • Java基础篇02:基本语法
  • CAD:修改
  • 23.【C++进阶】异常(try、catch、throw)
  • SQL表一共有几种写入方式
  • 零基础入门AI: YOLOv5 详解与项目实战
  • 数据库存储大量的json文件怎么样高效的读取和分页,利用文件缓存办法不占用内存
  • 数据结构:排序
  • 【Day21】146.LRU缓存 (Least Recently Used)
  • 详细解读Docker
  • STC携手VEX发起全球首个碳资产RWA生态,泰国峰会即将引爆绿色金融
  • 飞算JavaAI炫技赛:电商系统开发全流程实战解析
  • 卫星在轨光压计算详解
  • openharmony之AV_CodeC音视频编解码模块详解(二)
  • (未完待续...)如何编写一个用于构建python web项目镜像的dockerfile文件