TCP多线程模型、IO模型(select、poll、epoll)

我要成为嵌入式高手之3月11日Linux高编第十九天!!
————————————————————————————

TCP并发模型

一、TCP多线程模型:

缺点:创建线程会带来资源开销,能够现的并发量比较有限

二、IO模型:

1、阻塞IO

        没有数据到来时,可以让任务挂起,节省CPU资源开销,提升系统效率

2、非阻塞IO

        fcntl

        程序未接收到数据时一直执行,效率很低

3、异步IO

        只能绑定一个文件描述符用来读取数据

4、多路复用IO

        多个IO用一个函数接口监测

        select

                1、select监听的集合中的文件描述符有上限限制

                2、select有内核层向用户层数据空间拷贝的过程,占用系统资源开销

                3、select必须轮询检测产生事件的文件描述符

                4、select只能工作在水平触发模式,无法工作在边沿触发(高速模式)

       /* 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 select(int nfds, fd_set *readfds, fd_set *writefds,
                  fd_set *exceptfds, struct timeval *timeout);

        功能:监听文件描述符中是否有文件描述符变成ready状态

        参数:

                nfds:最大文件描述符的值+1;

                readfds:读文件描述符的首地址

                writefds:写文件描述符的首地址

                exceptfds:其余文件描述符集合

                timeout:等待的市场,NULL一直等待

        返回值:成功返回文件描述符集合中文件描述符的个数,失败返回-1;

       void FD_CLR(int fd, fd_set *set);

        功能:将文件描述符fd从集合中清除

        int  FD_ISSET(int fd, fd_set *set);

        功能:判断文件描述符fd是否能在集合中

        void FD_SET(int fd, fd_set *set);

        功能:将文件描述符fd加入到集合中

        void FD_ZERO(fd_set *set);

        将文件描述符集合清0;

写端:

#include "head.h"int main(void)
{int fd = 0;char tmpbuff[4096] = {0};mkfifo("/tmp/myfifo", 0777);fd = open("/tmp/myfifo", O_WRONLY);if (-1 == fd){perror("fail to open");return -1;}while (1){gets(tmpbuff);write(fd, tmpbuff, strlen(tmpbuff));}close(fd);return 0;
}

读端:

#include "head.h"int main(void)
{int fd = 0;int flags = 0;char *pret = NULL;ssize_t nsize = 0;char tmpbuff[4096] = {0};fd_set rdfds;fd_set tmpfds;int ret = 0;mkfifo("/tmp/myfifo", 0664);fd = open("/tmp/myfifo", O_RDONLY);if (-1 == fd){perror("fail to open");return -1;}FD_ZERO(&rdfds);//将文件描述符集合清0FD_SET(fd, &rdfds);//将文件描述符fd加入到文件描述符集合中FD_SET(0, &rdfds);//将文件描述符0加入到文件描述符集合中while (1){tmpfds = rdfds;ret = select(fd+1, &tmpfds, NULL, NULL, NULL);if (-1 == ret){perror("fail to select");return -1;}if (FD_ISSET(fd, &tmpfds))//判断文件描述符fd是否还在文件描述符集合中{memset(tmpbuff, 0, sizeof(tmpbuff));read(fd, tmpbuff, sizeof(tmpbuff));printf("FIFO:%s\n", tmpbuff);}if (FD_ISSET(0, &tmpfds)){memset(tmpbuff, 0, sizeof(tmpbuff));gets(tmpbuff);printf("STDIN:%s\n", tmpbuff);}}close(fd);return 0;
}

 结果:

poll 

        1、poll监听的文件描述符没有上限的限制(内部实现是个链表)

        2、有内核层向用户层数据空间拷贝的过程,占用系统资源开销

        3、必须轮询检测产生事件的文件描述符

        4、只能工作在水平触发模式,无法工作在边沿触发(高速模式)

#include <poll.h>

int poll(struct pollfd *fds, nfds_t nfds, int timeout);

功能:监听文件描述符集合是否有事件发生

参数:

        fds:监听文件描述符集合数组的空间首地址

        nfds:监听文件描述符集合元素个数

        timeout:等待的时间(-1 一直等待)

返回值:成功返回产生事件的文件描述符的个数,失败返回-1;

           struct pollfd {
               int   fd;              /* file descriptor */(监听的文件描述符)
               short events;     /* requested events */(要监听的事件)
                        POLLIN:是否可读
                        POLLOUT:是否可写
               short revents;    /* returned events */(实际产生的事件)
           };

读端:

#include "head.h"int main(void)
{int fd = 0;int flags = 0;char *pret = NULL;ssize_t nsize = 0;char tmpbuff[4096] = {0};struct pollfd fds[2];int nready = 0;mkfifo("/tmp/myfifo", 0664);fd = open("/tmp/myfifo", O_RDONLY);if (-1 == fd){perror("fail to open");return -1;}fds[0].fd = fd;fds[0].events = POLLIN;fds[1].fd = 0;fds[1].events = POLLIN;while (1){nready = poll(fds, 2, -1);if (-1 == nready){perror("fail to poll");return -1;}if (fds[0].revents & POLLIN){memset(tmpbuff, 0, sizeof(tmpbuff));read(fd, tmpbuff, sizeof(tmpbuff));printf("FIFO:%s\n", tmpbuff);}if (fds[1].revents & POLLIN){memset(tmpbuff, 0, sizeof(tmpbuff));gets(tmpbuff);printf("STDIN:%s\n", tmpbuff);}}close(fd);
}

写端:

#include "head.h"int main(void)
{int fd = 0;char tmpbuff[4096] = {0};mkfifo("/tmp/myfifo", 0664);fd = open("/tmp/myfifo", O_WRONLY);if (-1 == fd){perror("fail to open");return -1;}while (1){gets(tmpbuff);write(fd, tmpbuff, strlen(tmpbuff));}close(fd);return 0;
}

结果:

 epoll

1、epoll没有文件描述符上限限制

2、epoll创建内核监听事件表,所以只需要在内核空间完成数据拷贝即可

3、epoll会将产生事件的文件描述符对应的事件直接返回(retenv)

4、epoll不仅可以工作在水平触发模式(默认低速模式),还可以触发在边沿触发模式(高速模式)(EPOLLIN | EPOLLET)

1、epoll_create

#include <sys/epoll.h>

int epoll_create(int size);

功能:创建一张内核事件表

参数:size:事件的个数

返回值:成功返回文件描述符,失败返回-1;

2、epoll_ctl

#include <sys/epoll.h>

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

功能:维护epoll事件表

参数:

        epfd:事件表的文件描述符

        op:

                EPOLL_CTL_ADD添加事件

                EPOLL_CTL_MOD修改事件

                EPOLL_CTL_DEL删除事件

        fd:操作的文件描述符

        event:事件对应的事件

           typedef union epoll_data {
               void           *ptr;
               int              fd;
               uint32_t     u32;
               uint64_t     u64;
           } epoll_data_t;

           struct epoll_event {
               uint32_t     events;        /* Epoll events */
               epoll_data_t data;        /* User data variable */
           };

返回值:成功0,失败-1;

events:

data:要操作的文件的文件描述符 

3、epoll_wait

#include <sys/epoll.h>

int epoll_wait(int epfd, struct epoll_event *events,int maxevents, int timeout);

功能:监听事件表中的事件

参数:

        epfd:事件表的文件描述符

        events:存放实际产生事件的数组空间首地址

        maxevents:最多存放事件的个数

        timeout:设定监听的时间(超过该时间不再监听)-1一直监听直到有事件发生

返回值:

        成功返回实际产生事件的文件描述符的个数

        时间到达还没有事件产生返回0

        失败返回-1

read.c

#include "head.h"int main(void)
{int fd = 0;int epfd = 0;struct epoll_event env;//epoll_ctl需要的事件的结构体int nready = 0;struct epoll_event retenv[2];int i = 0;ssize_t nsize = 0;char *pret = NULL;char tmpbuff[4096] = {0};mkfifo("/tmp/myfifo", 0664);fd = open("/tmp/myfifo", O_RDONLY);if (-1 == fd){perror("fail to open");return -1;}/*创建一张2个事件的内核事件表*/epfd = epoll_create(2);if (epfd == -1){perror("fail to create");return -1;}/*设置事件结构体的属性*/env.events = EPOLLIN;env.data.fd = fd;/*操作事件*/epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &env);env.events = EPOLLIN;env.data.fd = 0;epoll_ctl(epfd, EPOLL_CTL_ADD, 0, &env);while (1){/*监听事件表中的事件*/nready = epoll_wait(epfd, retenv, 2, -1);//第二个参数是存放实际产生事件的结构体, 最多存放的个数, 设置监听时间,-1一直监听直到有事件发生if (-1 == nready){perror("fail to nready");return -1;}for (i = 0; i < nready; ++i){if (retenv[i].data.fd == 0)//判断要操作的流是否为从终端输入{memset(tmpbuff, 0, sizeof(tmpbuff));gets(tmpbuff);printf("STDIN: %s\n", tmpbuff);}if (retenv[i].data.fd == fd){memset(tmpbuff, 0, sizeof(tmpbuff));read(fd, tmpbuff, sizeof(tmpbuff));printf("FIFO: %s\n", tmpbuff);}}}close(fd);return 0;
}

write.c

#include "head.h"int main(void)
{int fd = 0;char tmpbuff[4096] = {0};mkfifo("/tmp/myfifo", 0664);fd = open("/tmp/myfifo", O_WRONLY);if (-1 == fd){perror("fail to open");return -1;}while (1){gets(tmpbuff);write(fd, tmpbuff, strlen(tmpbuff));}close(fd);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2870190.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

科研绘图二:箱线图(抖动散点)

R语言绘图系列—箱线图抖动散点 &#xff08;二&#xff09;: 科研绘图一&#xff1a;箱线图&#xff08;抖动散点&#xff09; 文章目录 R语言绘图系列---箱线图抖动散点&#xff08;二&#xff09;: 科研绘图一&#xff1a;箱线图&#xff08;抖动散点&#xff09; 前言一、…

鸿蒙Harmony应用开发—ArkTS声明式开发(基础手势:Web)下篇

onRequestSelected onRequestSelected(callback: () > void) 当Web组件获得焦点时触发该回调。 示例&#xff1a; // xxx.ets import web_webview from ohos.web.webviewEntry Component struct WebComponent {controller: web_webview.WebviewController new web_webv…

蓝桥集训之糖果

蓝桥集训之糖果 核心思想&#xff1a;dfs 剪枝 重复覆盖问题 暴搜 直到所有列都覆盖优化&#xff1a; 1.迭代加深 答案从1开始 2.逻辑简化 每次从可选行数最少得一列开始 3.可行性剪枝 添加估值函数h(),表示至少还需要选几行 与剩余行数的大小比较 4.**位运算 **将每包糖果…

wsl ubuntu 安装cuda nvcc环境

wsl ubuntu 安装cuda环境&#xff1a; CUDA Toolkit 11.6 Downloads | NVIDIA DeveloperDownload CUDA Toolkit 11.6 for Linux and Windows operating systems.https://developer.nvidia.com/cuda-11-6-0-download-archive?target_osLinux&target_archx86_64&Distri…

22-分支和循环语句_while语句(下)(初阶)

该代码输出什么&#xff1f; int main() {char ch \0;while ((ch getchar()) ! EOF){if (ch < 0 || ch>9){continue;}putchar(ch);}return 0; } 结果&#xff1a;该代码只打印数字字符 附&#xff1a;ASCII码表

C语言项目:数组与函数实践:扫雷游戏

目录 目录&#xff1a; 1.扫雷游戏分析与设计 1.1扫雷游戏的功能说明&#xff1a; 1.1.1使用控制台实现经典扫雷的游戏 1.1.2游戏可以通过菜单实现继续玩或者退出游戏 1.1.3扫雷棋盘是9*9的格子 1.1.4默认随机布置10个雷 1.1.5 可以排查雷 2.扫雷游戏的代码实现 1.遇到的问题…

【PyTorch】进阶学习:一文详细介绍 load_state_dict() 的应用场景、实战代码示例

【PyTorch】进阶学习&#xff1a;一文详细介绍 load_state_dict() 的应用场景、实战代码示例 &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入…

特殊文件——属性文件、XML文件

目录 特殊文件 ——属性文件、XML文件 特殊文件的作用 需要掌握的知识点 Properties文件 ​编辑 构造器与方法​编辑 使用Properties 把键值对数据写出到属性文件中 ​编辑 XML文件​编辑 XML文件的作用和应用场景 解析XML文件 使用Dom4J框架解析出XML文件——下载…

windows使用nvm对node进行版本管理切换

在使用之前各位务必卸载掉自己安装过的nvm或者node版本包括环境变量之类的&#xff0c;要保证自己的电脑完全没有node环境&#xff0c;下面这些配置会自动配置node环境和安装node 参考视频 https://github.com/coreybutler/nvm-windows 访问以上链接到github去下载 点击release…

matlab simulink 一阶倒立摆LQR控制

1、内容简介 略 80-可以交流、咨询、答疑 一阶倒立摆LQR控制 2、内容说明 略 一级倒立摆系统的数学模型 系统的组成系统由小 车、小球和轻质杆组成。 倒摆通过转动关节安装在 驱动小车上&#xff0c;杆子的一端 固定在小车上&#xff0c;另一端可 以自由的左右倒下。通过 …

Ribbon简单使用

Ribbon是Netflix发布的云中间层服务开源项目&#xff0c;其主要功能是提供客户端实现负载均衡算法。Ribbon客户端组件提供一系列完善的配置项如连接超时&#xff0c;重试等。简单的说&#xff0c;Ribbon是一个客户端负载均衡器&#xff0c;我们可以在配置文件中Load Balancer后…

【Miniconda】一文了解conda虚拟环境的作用

【Miniconda】一文了解conda虚拟环境的作用 &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程&#x1f448; 希望得到您的订阅和支持~ &am…

【原创】java+swing+mysql报修管理系统设计与实现

前言&#xff1a; 为了满足居民和学生生活的需求&#xff0c;方便社区居民或者学生等用户进行报修&#xff0c;我们根据实际情况。首先&#xff0c;通过市场需求&#xff0c;我们确定了报修管理系统的基本功能。我们今天要用javaswing去开发一个C/S架构的报修管理系统&#xf…

数据结构-队列java实现

队列 队列(queue)1.队列的特点2.数组模拟队列JAVA代码3.上述过程优化 博文主要是自己学习的笔记&#xff0c;供自己以后复习使用&#xff0c; 参考的主要教程是B站的 尚硅谷数据结构和算法 队列(queue) 1.队列的特点 1&#xff09;队列是一个有序列表&#xff0c;可以用数组…

集成学习 | 集成学习思想:Bagging思想

目录 一. Bagging思想1. Bagging 算法2. 随机森林(Random Forest)算法 在正文开始之前&#xff0c;我们先来聊一聊什么是集成学习&#xff1f; 集成学习是一种算法思想&#xff1a;将若干个弱学习器分组之后&#xff0c;产生一个新的学习器 弱学习器指预测误差在50%以下的学习器…

计算机组成原理 第五章(计算机的运算方法)—第五节(浮点四则运算)

写在前面&#xff1a; 本系列笔记主要以《计算机组成原理&#xff08;唐朔飞&#xff09;》为参考&#xff0c;大部分内容出于此书&#xff0c;笔者的工作主要是挑其重点展示&#xff0c;另外配合下方视频链接的教程展开思路&#xff0c;在笔记中一些比较难懂的地方加以自己的…

c++实现简单搜索二叉树<K,V>形

文章目录 搜索二叉树节点类BSTreeNode(节点类的构造) BSTree(功能实现类)Insert(插入)Erase(删除)Find(查找这个节点) 搜索二叉树 搜索二叉树本质:左节点比我小 右节点比我大 节点类 BSTreeNode:给自身节点封装一个类 用这个类来添加节点的操作 我们写的是一个key.value型的搜…

稀碎从零算法笔记Day19-LeetCode:相交链表

题型&#xff1a;链表基本操作 链接&#xff1a;160. 相交链表 - 力扣&#xff08;LeetCode&#xff09; 来源&#xff1a;LeetCode 题目描述 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&…

vue3项目

案例用到的知识点如下&#xff1a; ① vite 创建项目 ② 组件的封装与注册 ③ props ④ 样式绑定 ⑤ 计算属性 ⑥ 自定义事件 ⑦ 组件上的 v-model 效果如下图&#xff1b; 页面2 项目结构&#xff1a; 初始化项目 在终端运行以下的命令&#xff0c;初始化 vite 项目&#xf…

前端跨平台开发框架:简化多端开发的利器

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…