termios 线程 poll epoll进化 二叉AVL红黑树

struct termios tio 是什么

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>#define SERIAL_PORT "/dev/ttyS0"
#define BUF_SIZE    256int main(void)
{int fd;struct termios tio;/* 1. 打开串口 */fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY | O_SYNC);if (fd < 0) {perror("open");return 1;}/* 2. 配置串口:115200 8N1,无流控 */memset(&tio, 0, sizeof(tio));cfsetospeed(&tio, B115200);cfsetispeed(&tio, B115200);tio.c_cflag &= ~PARENB;        /* 无校验 */tio.c_cflag &= ~CSTOPB;        /* 1 停止位 */tio.c_cflag &= ~CSIZE;tio.c_cflag |= CS8;            /* 8 数据位 */tio.c_cflag |= (CLOCAL | CREAD);tio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /* 原始模式 */tio.c_iflag &= ~(IXON | IXOFF | IXANY);         /* 无软件流控 */tio.c_oflag &= ~OPOST;                          /* 原始输出 */tcflush(fd, TCIOFLUSH);tcsetattr(fd, TCSANOW, &tio);/* 3. 写入数据 */char *tx = "hello world\n";if (write(fd, tx, strlen(tx)) < 0) {perror("write");close(fd);return 1;}/* 4. 循环读取并查找 "flush" */char buf[BUF_SIZE];int len, total = 0;char line[BUF_SIZE * 2] = {0};while (1) {len = read(fd, buf, sizeof(buf));if (len < 0) {perror("read");break;}if (len == 0)continue;/* 把新数据追加到 line 缓冲区 */if (total + len < sizeof(line) - 1) {memcpy(line + total, buf, len);total += len;line[total] = '\0';}/* 判断是否出现 "flush" */if (strstr(line, "flush")) {printf("Received \"flush\", exit.\n");break;}/* 打印刚收到的数据(可选) */printf("Rx[%d]: %.*s", len, len, buf);fflush(stdout); //立即刷新缓冲区//把 C 标准库 为 `stdout`(通常是终端)维护的用户态缓冲区立即刷到内核,确保之前 `printf/puts` 的内容立刻出现在屏幕上}close(fd);return 0;
}
  • pthread_create
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <pthread.h>#define SERIAL_PORT "/dev/ttyS0"
#define BUF_SIZE    256static int stop = 0;            /* 线程退出标志 */
static pthread_t tid;/* 串口初始化:115200 8N1,阻塞读 */
static int open_serial(void)
{int fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY);if (fd < 0) {perror("open " SERIAL_PORT);return -1;}struct termios tio;tcgetattr(fd, &tio);cfmakeraw(&tio);cfsetispeed(&tio, B115200);cfsetospeed(&tio, B115200);tcflush(fd, TCIOFLUSH);tcsetattr(fd, TCSANOW, &tio);return fd;
}/* 线程函数:一直读串口直到看到 "flush" */
static void *rx_thread(void *arg)
{int fd = (long)arg;char buf[BUF_SIZE];char line[BUF_SIZE * 2] = {0};int total = 0;while (!stop) {int n = read(fd, buf, sizeof(buf));if (n <= 0) continue;/* 追加到行缓冲区并检查子串 */if (total + n < sizeof(line) - 1) {memcpy(line + total, buf, n);total += n;line[total] = '\0';}if (strstr(line, "flush")) {printf("[RX-THREAD] Found \"flush\", exiting.\n");break;}}close(fd);return NULL;
}int main(void)
{int fd = open_serial();if (fd < 0) return 1;/* 创建接收线程 */if (pthread_create(&tid, NULL, rx_thread, (void *)(long)fd) != 0) {perror("pthread_create");close(fd);return 1;}/* 主线程可以干别的事,这里简单等待用户输入 */printf("Press Enter to quit...\n");getchar();/* 通知线程退出并等待结束 */stop = 1;pthread_cancel(tid);    /* 若线程阻塞在 read(),可强制唤醒 */pthread_join(tid, NULL);printf("Main thread exit.\n");return 0;
}
  • poll
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <poll.h>#define SERIAL_PORT "/dev/ttyS0"
#define BUF_SIZE    256static int open_serial(void)
{int fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY | O_NONBLOCK);if (fd < 0) { perror("open"); return -1; }struct termios tio;tcgetattr(fd, &tio);cfmakeraw(&tio);cfsetispeed(&tio, B115200);cfsetospeed(&tio, B115200);tcflush(fd, TCIOFLUSH);tcsetattr(fd, TCSANOW, &tio);return fd;
}int main(void)
{int fd = open_serial();if (fd < 0) return 1;char line[BUF_SIZE * 2] = {0};int total = 0;struct pollfd pfd = { .fd = fd, .events = POLLIN };while (1) {int ret = poll(&pfd, 1, -1);        /* 无限等待可读 */if (ret < 0) { perror("poll"); break; }if (pfd.revents & POLLIN) {char buf[BUF_SIZE];int n = read(fd, buf, sizeof(buf));if (n <= 0) continue;/* 追加到行缓冲并检查 */if (total + n < sizeof(line) - 1) {memcpy(line + total, buf, n);total += n;line[total] = '\0';}if (strstr(line, "flush")) {printf("Got flush, exit.\n");break;}}}close(fd);return 0;
}
  • epoll
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/epoll.h>#define SERIAL_PORT "/dev/ttyS0"
#define BUF_SIZE    256
#define MAX_EVENTS  1static int open_serial(void)
{int fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY | O_NONBLOCK);if (fd < 0) { perror("open"); return -1; }struct termios tio;tcgetattr(fd, &tio);cfmakeraw(&tio);cfsetispeed(&tio, B115200);cfsetospeed(&tio, B115200);tcflush(fd, TCIOFLUSH);tcsetattr(fd, TCSANOW, &tio);return fd;
}int main(void)
{int fd = open_serial();if (fd < 0) return 1;int epfd = epoll_create1(0);if (epfd < 0) { perror("epoll_create1"); return 1; }struct epoll_event ev = { .events = EPOLLIN, .data.fd = fd };if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) < 0) {perror("epoll_ctl"); return 1;}char line[BUF_SIZE * 2] = {0};int total = 0;struct epoll_event events[MAX_EVENTS];while (1) {int nfds = epoll_wait(epfd, events, MAX_EVENTS, -1);if (nfds < 0) { perror("epoll_wait"); break; }for (int i = 0; i < nfds; ++i) {if (events[i].events & EPOLLIN) {char buf[BUF_SIZE];int n = read(fd, buf, sizeof(buf));if (n <= 0) continue;if (total + n < sizeof(line) - 1) {memcpy(line + total, buf, n);total += n;line[total] = '\0';}if (strstr(line, "flush")) {printf("Got flush, exit.\n");goto out;}}}}
out:close(fd);close(epfd);return 0;
}

深入浅出理解select、poll、epoll的实现

selectpollepoll
性能随着连接数的增加,性能急剧下降,处理成千上万的并发连接数时,性能很差随着连接数的增加,性能急剧下降,处理成千上万的并发连接数时,性能很差随着连接数的增加,性能基本没有变化
连接数一般1024无限制无限制
内存拷贝每次调用select拷贝每次调用poll拷贝fd首次调用epoll_ctl拷贝,每次调用epoll_wait不拷贝
数据结构bitmap数组红黑树
内在处理机制线性轮询线性轮询FD挂在红黑树,通过事件回调callback
时间复杂度O(n)O(n)O(1)

目前支持I/O多路复用的系统调用有select,pselect,poll,epoll

  • 在Linux的缓存IO机制中,操作系统会将IO的数据缓存在文件系统的页缓存(page cache)。也就是说,数据会先被拷贝到操作系统内核的缓冲区中,然后才会从操作系统内核的缓存区拷贝到应用程序的地址空间中

![[Pasted image 20250815160249.png]]

select

  • select存在三个问题
    • 每次调用select,都需要把被监控的fds集合从用户态空间拷贝到内核态空间
    • 能监听端口的数量有限,单个进程所能打开的最大连接数由FD_SETSIZE宏定义
    • 被监控的fds集合中,只要有一个有数据可读,整个socket集合就会被遍历一次调用skpoll函数收集可读事件

![[1755245325283-349279b4-9119-11eb-85d0-1278b449b310.gif]]

poll

  • 针对select遗留的三个问题中(问题(2)是fd限制问题,问题(1)和(3)则是性能问题)
  • poll只是使用pollfd结构而不是select的fd_set结构,这就解决了select的问题(2)fds集合大小1024限制问题

epoll

  • 红黑树

![[1755245323731-346e30f4-9119-11eb-bb4a-4a238cf0c417.gif]]

二叉树

![[Pasted image 20250815174938.png]]

![[Pasted image 20250815175425.png]]

![[Pasted image 20250815181924.png]]

AVL树 - 平衡因子

![[Pasted image 20250815181940.png]]

![[Pasted image 20250815183433.png]]

红黑树

  • 理解左旋右旋,实现插入

![[Pasted image 20250815173105.png]]

![[Pasted image 20250815174129.png]]

文档链接说明

  • 参考47
    (99+ 封私信 / 57 条消息) IO多路复用——深入浅出理解select、poll、epoll的实现 - 知乎

  • 参考48
    5分钟学二叉搜索树(手机动画版)_哔哩哔哩_bilibili
    二叉搜索树的删除操作(手机动画版)_哔哩哔哩_bilibili

  • 参考49
    红黑树的旋转操作_哔哩哔哩_bilibili
    红黑树的插入算法_哔哩哔哩_bilibili

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++设计模式:类间关系

类封装了数据和行为&#xff0c;是面向对象的重要组成部分&#xff0c;它是具有相同属性、操作、关系的对象集合的总称。在系统中&#xff0c;每个类都具有一定的职责&#xff0c;职责指的是类要完成什么样子的功能&#xff0c;要承担什么样子的义务。一个类可以有多种职责&…

MSYS2+CMake配置C/C++开发环境

目录一、MSYS2是什么1.1 核心架构与组件​​1.1.1 背景介绍1.1.1.1 Cygwin1.1.1.2 MinGW和Mingw-w641.1.1.3MSYS和MSYS21.1.2 技术基础​​1.1.3 多环境支持​​1.2 核心功能​​1.2.1 类Unix开发环境​​1.2.2 开发工具链​​1.2.3 软件仓库与包管理​​二、安装和配置2.1 配置…

Vue 3 + TypeScript:package.json 示例 / 详细注释说明

一、示例 / 详细注释说明 {// 项目基础信息"name": "vite-project", // 项目名称&#xff08;建议使用 kebab-case 格式&#xff09;"private": true, // 标记为私有项目&#xff0c;避免意外发布到 npm"version": "1.0.…

SpatialVLM和SpatialRGPT论文解读

目录 一、SpatialVLM 1、概述 2、方法 3、实验 二、SpatialRGPT 1、概述 2、方法 3、训练方法 4、实验 一、SpatialVLM 1、概述 SpatialVLM是最早的依赖传统VLMs实现3D空间推理能力的论文&#xff0c;在24年1月由DeepMind团队提出&#xff0c;当时对比的还是GPT4v&am…

理解GPU架构:基础与关键概念

GPU 基础概述&#xff1a;从图形渲染到 AI 与高性能计算的核心 Graphics Processing Units&#xff08;GPU&#xff09;已从专用的图形渲染硬件演进为 AI、科学计算与高性能任务的中坚力量。本文将介绍 GPU 架构的基础知识&#xff0c;包括其组成部分、内存层次结构&#xff0c…

订单状态定时处理(Spring Task 定时任务)

订单状态定时处理 如果最后一秒刚好支付了咋办?如何补偿? 需要将支付状态和订单状态一起考虑,或者直接使用状态机 Spring Task 是Spring框架提供的任务调度工具,可以按照约定的时间自动执行某个代码逻辑。 **定位:**定时任务框架 **作用:**定时自动执行某段Java代码 …

职得AI简历-免费AI简历生成工具

本文转载自&#xff1a;职得AI简历-免费AI简历生成工具 - Hello123工具导航 ** 一、核心功能解析 职得 AI 简历是 AI 驱动的智能求职平台&#xff0c;通过深度学习算法分析百万优质简历数据&#xff0c;提供从简历生成到面试准备的全流程服务&#xff0c;显著提升求职竞争力。…

8.14 机器学习(1)

机器学习基础一、什么是机器学习定义&#xff1a;让计算机利用大量数据在特定任务上持续改进性能的过程&#xff0c;可以让任务完成的更好。机器学习的领域很多。二、机器学习基本术语数据集、样本、特征&#xff08;属性&#xff09;、属性空间、向量表示、训练集&#xff08;…

给电脑升级内存,自检太慢,以为出错

公司电脑是16G内存&#xff0c;用虚拟机时非常吃力。于是跟领导说&#xff0c;买了32G内存和1T SSD。电脑有两个SATA数据线&#xff0c;SATA电源头只有一个。于是买了几个1转2&#xff0c;顺利接上。把原来的16G拔下&#xff0c;换上32G内存。结果开机没反应。心里就有点嘀咕&a…

Effective C++ 条款43:学习处理模板化基类内的名称

Effective C 条款43&#xff1a;学习处理模板化基类内的名称核心思想&#xff1a;模板化基类&#xff08;templatized base classes&#xff09;中的名称在派生类模板中默认不可见&#xff0c;需要通过this->前缀、using声明或显式基类限定来引入。这是因为编译器在解析模板…

Mybatis简单练习注解sql和配置文件sql+注解形式加载+配置文件加载

项目结构 d:\test\runjar\data\static\data\mybatis_helloworld\Mybatis\ ├── lib\ │ ├── asm-3.3.1.jar │ ├── c3p0-0.9.1.2.jar │ ├── cglib-2.2.2.jar │ ├── commons-logging-1.1.1.jar │ ├── ehcache-core-2.6.8.jar │ ├── javassi…

抗日胜利80周年 | HTML页面

飞翔的和平鸽&#xff1b;屹立的人民英雄纪念碑&#xff1b;倒下的日本国旗&#xff1b;旋转的金色勋章无不代表着我们胜利了&#xff01;&#xff01;&#xff01;HTML源代码&#xff1a; <!DOCTYPE html> <html lang"zh-CN"> <head><meta cha…

web仿写网站

一、完成自己学习的官网&#xff0c;至少三个不同的页面。1、界面1&#xff08;1&#xff09;代码<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-wid…

基于element-plus和IndexedDB数据库的基础表单

本文介绍了基于Vue 3和Element Plus的表单项目配置页面实现。页面包含搜索栏、操作按钮、数据表格和分页组件&#xff0c;使用IndexedDB进行本地数据存储。主要功能包括&#xff1a;1) 通过模糊查询搜索项目&#xff1b;2) 分页显示项目数据&#xff1b;3) 添加/编辑/删除项目操…

paimon实时数据湖教程-主键表更新机制

在上一章&#xff0c;我们学习了 Paimon 如何保证每一次写入的原子性和一致性。但数据仓库的核心需求不仅是写入&#xff0c;更重要的是更新。想象一个场景&#xff1a;我们需要实时更新用户的最新信息&#xff0c;或者实时累加计算用户的消费总额。传统的 Hive 数据湖对此无能…

第十六届蓝桥杯青少组C++省赛[2025.8.9]第二部分编程题(4、矩阵圈层交错旋转)

参考程序&#xff1a;#include <bits/stdc.h> using namespace std;const int MAXN 105; int a[MAXN][MAXN];int main() {int n;if (!(cin >> n)) return 0;for (int i 0; i < n; i)for (int j 0; j < n; j)cin >> a[i][j];int layers n / 2; // 每…

【FastGTP✨】[01] 使用 FastGPT 搭建简易 AI 应用

简易应用&#xff1a;英语单词解释 例句 1. 前言 FastGPT 是一个低代码 AI 应用构建平台&#xff0c;可以通过简单配置快速创建自己的 AI 应用。 本文将带你用 FastGPT 搭建一个 英语单词解释 例句 的 AI 工具&#xff0c;输入英文单词后&#xff0c;输出&#xff1a; 单词…

【Mysql语句练习】

MysqlMysql语句练习一、建库建表二、插入数据三、查询Mysql语句练习 一、建库建表 1、创建数据库mydb11_stu&#xff0c;并使用数据库 # 创建数据库mydb11_stu mysql> create database mydb11_stu; Query OK, 1 row affected (0.00 sec) # 使用数据库 mysql> use mydb1…

用Python Scrapy征服网络爬虫(反爬技术深入剖析)

目录 第1章:Scrapy是个啥?为什么它是你爬虫路上的最佳拍档? 1.1 Scrapy的核心亮点 1.2 啥时候用Scrapy? 1.3 安装Scrapy 第2章:动手写你的第一个Scrapy爬虫 2.1 创建Scrapy项目 2.2 定义数据结构(Items) 2.3 编写爬虫逻辑 2.4 运行爬虫 2.5 小技巧:调试爬虫 …

解决Electron透明窗口点击不影响其他应用

遇到的问题&#xff1a;在electron透明窗口点击&#xff0c;影响窗口下的应用接受不到点击事件解决方案&#xff1a;CSSIgnoreMouseEvents实现原理&#xff1a;主进程默认设置禁用目标窗口鼠标事件&#xff08;禁用之后能检测到mousemove&#xff09;&#xff0c;UI进程检测页面…