嵌入式Linux串口和 poll() 函数的使用

一、poll() 函数的介绍

在这里插入图片描述

  poll() 函数用于监控多个文件描述符的变化的函数。它可以用来检查一个或多个文件描述符的状态是否改变,比如是否可读、可写或有错误发生。它常用于处理 I/O 多路复用,这在需要同时处理多个网络连接或文件操作时非常有用。

头文件

#include <poll.h>  

函数原型

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

fds:一个指向 pollfd 结构数组的指针,每个 pollfd 结构代表一个要监控的文件描述符。
nfds:fds 数组中的元素数量。
timeout:等待的超时时间(毫秒)。如果设置为 -1,则 poll() 会一直等待,直到某个文件描述符的状态改变或捕获到信号。如果设置为 0,则 poll() 会立即返回,不会等待。
struct pollfd 结构

struct pollfd {  int fd;          // 文件描述符  short events;    // 感兴趣的事件  short revents;   // 返回的事件  
};

fd:要监控的文件描述符。
events:用户感兴趣的事件,可以是以下值的组合:
POLLIN:数据可读
POLLOUT:数据可写
POLLPRI:优先级数据可读
POLLERR:发生错误
POLLHUP:挂起(只用于流)
POLLNVAL:请求无效的文件描述符
revents:返回时,这个字段包含了实际发生的事件。
返回值
成功时,返回更改状态的文件描述符数量。
如果超时,返回 0。
失败时,返回 -1 并设置 errno。
示例
下面是一个简单的 poll() 使用示例,它监控标准输入(stdin)是否可读:

#include <stdio.h>  
#include <stdlib.h>  
#include <unistd.h>  
#include <poll.h>  int main() {  struct pollfd fds[1];  int ret;  // 设置要监控的文件描述符和事件  fds[0].fd = STDIN_FILENO; // 标准输入的文件描述符  fds[0].events = POLLIN;   // 监控读事件  // 使用 poll 监控文件描述符  ret = poll(fds, 1, -1); // 无限等待,直到有事件发生  if (ret == -1) {  perror("poll");  exit(EXIT_FAILURE);  }  // 检查哪个文件描述符的状态发生了改变  if (fds[0].revents & POLLIN) {  printf("Standard input is readable.\n");  // 这里可以读取标准输入的数据  }  return 0;  
}

在这里插入图片描述

  这个示例程序会等待用户从标准输入(通常是键盘)输入数据。一旦有数据可读,poll() 就会返回,并设置 fds[0].revents 为 POLLIN,表示标准输入现在可读。然后程序会打印一条消息。注意,这个示例并没有实际读取输入数据,只是检测了输入是否可读。如果需要读取数据,你可以使用如 read() 或 fgets() 等函数来从标准输入读取数据。

二、串口使用poll()函数测试代码

  测试代码基于文章 <嵌入式Linux开发板测试esp8266模块> 进行修改测试,文章链接如下:
http://t.csdnimg.cn/y31It
修改后代码如下:

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <termios.h>
#include <sys/select.h>
#include <poll.h>#define REV_OK		0	//接收完成标志
#define REV_WAIT	1	//接收未完成标志
#define UART_BUF    128 // 串口缓冲区#define ESP8266_AP_INFO         "AT+CWSAP=\"ATK-8266\",\"12345678\",1,4\r\n"
#define ESP8266_JAP_INFO          "AT+CWJAP=\"TP-LINK_xxxx\",\"123456789\"\r\n"
#define ESP8266_TCP_SERVER_INFO "AT+CIPSTART=\"TCP\",\"192.168.1.182\",8080\r\n"#define u8 unsigned charunsigned short esp8266_cnt = 0, esp8266_cntPre = 0;
unsigned char buf[UART_BUF] = {0};/* 实现ms级延时 */
static void delay_xms(unsigned int secs)
{struct timeval tval;tval.tv_sec=secs/1000;tval.tv_usec=(secs*1000)%1000000;select(0,NULL,NULL,NULL,&tval);
}typedef struct uart_hardware_cfg {unsigned int baudrate;  /* 波特率 */unsigned char dbit;     /* 数据位 */char parity;    /* 奇偶校验 */unsigned char sbit; /* 停止位 */
}uart_cfg_t;static struct termios old_cfg; /* 用于保存终端的配置参数 */
static int fd; /* 串口终端对应的文件描述符 *//* 串口初始化 
打开串口文件描述符,即对应的串口终端的设备节点 */
static int uart_init(const char *device)
{/* 打开串口 *//* O_NOCTTY 如果欲打开的文件为终端机设备时, 则不会将该终端机当成进程控制终端机 */fd = open(device, O_RDWR | O_NOCTTY); if (fd < 0){fprintf(stderr, "open error:%s:%s\n", device, strerror(errno));return -1;}/* 获取串口当前的配置参数 */if (0 > tcgetattr(fd, &old_cfg)) {fprintf(stderr, "tcgetattr error: %s\n", strerror(errno));close(fd);return -1;}return 0;
}/**** 串口配置** 参数cfg指向一个uart_cfg_t结构体对象**/
static int uart_cfg(const uart_cfg_t *cfg)
{struct termios new_cfg = {0};   //将new_cfg对象清零speed_t speed;/* 设置为原始模式 */cfmakeraw(&new_cfg);/* 使能接收 */new_cfg.c_cflag |= CREAD;/* 设置波特率 */switch (cfg->baudrate) {case 1200: speed = B1200;break;case 1800: speed = B1800;break;case 2400: speed = B2400;break;case 4800: speed = B4800;break;case 9600: speed = B9600;break;case 19200: speed = B19200;break;case 38400: speed = B38400;break;case 57600: speed = B57600;break;case 115200: speed = B115200;break;case 230400: speed = B230400;break;case 460800: speed = B460800;break;case 500000: speed = B500000;break;default:    //默认配置为115200speed = B115200;printf("default baud rate: 115200\n");break;}if (0 > cfsetspeed(&new_cfg, speed)) {fprintf(stderr, "cfsetspeed error: %s\n", strerror(errno));return -1;}/* 设置数据位大小 */new_cfg.c_cflag &= ~CSIZE;  //将数据位相关的比特位清零switch (cfg->dbit) {case 5:new_cfg.c_cflag |= CS5;break;case 6:new_cfg.c_cflag |= CS6;break;case 7:new_cfg.c_cflag |= CS7;break;case 8:new_cfg.c_cflag |= CS8;break;default:    //默认数据位大小为8new_cfg.c_cflag |= CS8;
//        printf("default data bit size: 8\n");break;}/* 设置奇偶校验 */switch (cfg->parity) {case 'N':       //无校验new_cfg.c_cflag &= ~PARENB;new_cfg.c_iflag &= ~INPCK;break;case 'O':       //奇校验new_cfg.c_cflag |= (PARODD | PARENB);new_cfg.c_iflag |= INPCK;break;case 'E':       //偶校验new_cfg.c_cflag |= PARENB;new_cfg.c_cflag &= ~PARODD; /* 清除PARODD标志,配置为偶校验 */new_cfg.c_iflag |= INPCK;break;default:    //默认配置为无校验new_cfg.c_cflag &= ~PARENB;new_cfg.c_iflag &= ~INPCK;
//        printf("default parity: N\n");break;}/* 设置停止位 */switch (cfg->sbit) {case 1:     //1个停止位new_cfg.c_cflag &= ~CSTOPB;break;case 2:     //2个停止位new_cfg.c_cflag |= CSTOPB;break;default:    //默认配置为1个停止位new_cfg.c_cflag &= ~CSTOPB;
//        printf("default stop bit size: 1\n");break;}/* 将MIN和TIME设置为0 */new_cfg.c_cc[VTIME] = 0;new_cfg.c_cc[VMIN] = 0;/* 清空缓冲区 */if (0 > tcflush(fd, TCIOFLUSH)) {fprintf(stderr, "tcflush error: %s\n", strerror(errno));return -1;}/* 写入配置、使配置生效 */if (0 > tcsetattr(fd, TCSANOW, &new_cfg)) {fprintf(stderr, "tcsetattr error: %s\n", strerror(errno));return -1;}/* 配置OK 退出 */return 0;
}//==========================================================
//	函数名称:	ESP8266_Clear
//
//	函数功能:	清空缓存
//
//	入口参数:	无
//
//	返回参数:	无
//
//	说明:		
//==========================================================
void ESP8266_Clear(void)
{memset(buf, 0, sizeof(buf));esp8266_cnt = 0;
}/**** 信号处理函数,当串口有数据可读时,会跳转到该函数执行**/
static void io_handler(int sig, siginfo_t *info, void *context)
{if(SIGRTMIN != sig)return;/* 判断串口是否有数据可读 */if (POLL_IN == info->si_code) {if (esp8266_cnt >= sizeof(buf)){// esp8266_cnt = 0; //防止串口被刷爆// memset(buf,0,sizeof(buf));ESP8266_Clear();}esp8266_cnt = read(fd, buf+esp8266_cnt, sizeof(buf)-esp8266_cnt);printf("esp8266_cnt=%d\r\n", esp8266_cnt);printf("io_handler=%s\r\n", buf);}
}/**** 异步I/O初始化函数**/
static void async_io_init(void)
{struct sigaction sigatn;int flag;/* 使能异步I/O */flag = fcntl(fd, F_GETFL);  //使能串口的异步I/O功能flag |= O_ASYNC;fcntl(fd, F_SETFL, flag);/* 设置异步I/O的所有者 */fcntl(fd, F_SETOWN, getpid());/* 指定实时信号SIGRTMIN作为异步I/O通知信号 */fcntl(fd, F_SETSIG, SIGRTMIN);/* 为实时信号SIGRTMIN注册信号处理函数 */sigatn.sa_sigaction = io_handler;   //当串口有数据可读时,会跳转到io_handler函数sigatn.sa_flags = SA_SIGINFO;sigemptyset(&sigatn.sa_mask);sigaction(SIGRTMIN, &sigatn, NULL);
}void Uart4_Init(unsigned int baud, char *device)
{uart_cfg_t cfg = {0};if (NULL == device) {fprintf(stderr, "Error: the device no found!\n");exit(EXIT_FAILURE);}/* 串口初始化 */if (uart_init(device))exit(EXIT_FAILURE);/* 设置波特率 */cfg.baudrate = baud;/* 串口配置 */if (uart_cfg(&cfg)) {tcsetattr(fd, TCSANOW, &old_cfg);   //恢复到之前的配置close(fd);exit(EXIT_FAILURE);}
}void Uart5_Init(unsigned int baud, char *device)
{uart_cfg_t cfg = {0};if (NULL == device) {fprintf(stderr, "Error: the device no found!\n");exit(EXIT_FAILURE);}/* 串口初始化 */if (uart_init(device))exit(EXIT_FAILURE);/* 设置波特率 */cfg.baudrate = baud;/* 串口配置 */if (uart_cfg(&cfg)) {tcsetattr(fd, TCSANOW, &old_cfg);   //恢复到之前的配置close(fd);exit(EXIT_FAILURE);}
}//==========================================================
//	函数名称:	ESP8266_WaitRecive
//
//	函数功能:	等待接收完成
//
//	入口参数:	char *res
//
//	返回参数:	REV_OK-接收完成		REV_WAIT-接收超时未完成
//
//	说明:		循环调用检测是否接收完成
//==========================================================
_Bool ESP8266_WaitRecive(char *res)
{int err=0,nbytes=0,i=0;struct pollfd fds[] = {{.fd	= fd,.events	= POLLIN,},};err = poll(fds, 1, 5000);//5sswitch(err){case -1://出错printf("\n poll read error =%d \n", err);nbytes=0;break;case 0://超时printf("\n poll read error =%d \n", err);nbytes=0;break;default:nbytes = read(fd, buf+esp8266_cnt, sizeof(buf)-esp8266_cnt);break;}esp8266_cnt += nbytes;if(esp8266_cnt == 0) 							//如果接收计数为0 则说明没有处于接收数据中,所以直接跳出,结束函数return REV_WAIT;if( strstr((const char *)buf, res) != NULL || esp8266_cnt == esp8266_cntPre)				//如果上一次的值和这次相同,则说明接收完毕{// for (i = 0; i < esp8266_cnt; i++)//     printf(" 0x%02x", buf[i]);// printf("\n");printf("***********************\n");printf("%s",buf);printf("***********************\n");esp8266_cnt = 0;							//清0接收计数esp8266_cntPre=0;return REV_OK;								//返回接收完成标志}esp8266_cntPre = esp8266_cnt;					//置为相同return REV_WAIT;								//返回接收未完成标志}int ESP8266_Recive(void)
{int err=0,nbytes=0,i=0;struct pollfd fds[] = {{.fd	= fd,.events	= POLLIN,},};memset(buf,0,sizeof(buf));err = poll(fds, 1, 1000);//1sswitch(err){case -1://出错printf("\n poll read error =%d \n", err);nbytes=0;break;case 0://超时printf("\n poll read error =%d \n", err);nbytes=0;break;default:nbytes = read(fd, buf, sizeof(buf));break;}if(nbytes>0){return nbytes;}return -1;}//==========================================================
//	函数名称:	ESP8266_SendCmd
//
//	函数功能:	发送命令
//
//	入口参数:	cmd:命令
//				res:需要检查的返回指令
//
//	返回参数:	0-成功	1-失败
//
//	说明:		
//==========================================================
_Bool ESP8266_SendCmd(char *cmd, char *res)
{int ret = 0,err,nbytes;unsigned int timeOutCnt = 3;ESP8266_Clear();ret = write(fd, (unsigned char *)cmd, strlen((const char *)cmd));if (ret == 0)   printf("write err!\r\n");
//	printf("UartBuf:%s, Len:%d\r\n", buf, esp8266_cnt);while(timeOutCnt--){if(ESP8266_WaitRecive(res) == REV_OK)							//如果收到数据{
//			printf("ESP8266_SendCmd Function:%s\r\n", buf);if(strstr((const char *)buf, res) != NULL)		//如果接收到的数据是在给定数据的范围内,则不为NULL{ESP8266_Clear();									//清空缓存return 0;}}//delay_xms(10);//10s内让串口2中断函数循环接收到的数据}return 1;}//==========================================================
//	函数名称:	ESP8266_SendData
//
//	函数功能:	发送数据
//
//	入口参数:	data:数据
//				len:长度
//
//	返回参数:	无
//
//	说明:		
//==========================================================
void ESP8266_SendData(unsigned char *data, unsigned short len)
{char cmdBuf[32];ESP8266_Clear();								//清空接收缓存// sprintf(cmdBuf, "AT+CIPSEND=0,%d\r\n", len);		//发送命令  多连接sprintf(cmdBuf, "AT+CIPSEND=%d\r\n", len);		//发送命令  单连接if(!ESP8266_SendCmd(cmdBuf, ">"))				//收到‘>’时可以发送数据,改不得{write(fd, data, len);		//发送设备连接请求数据}}_Bool Esp8266_Init()
{ESP8266_Clear();printf("1. AT\r\n");while(ESP8266_SendCmd("AT\r\n", "OK"))delay_xms(500);printf("2. CWMODE\r\n");while(ESP8266_SendCmd("AT+CWMODE=2\r\n", "OK"))delay_xms(500);printf("2.1 AT+RST\r\n");while(ESP8266_SendCmd("AT+RST\r\n", "OK"))delay_xms(2000);printf("3. CWSAP\r\n");while(ESP8266_SendCmd(ESP8266_AP_INFO, "OK")){delay_xms(500);}printf("4. AT+CIPMUX\r\n");// 启动多连接while(ESP8266_SendCmd("AT+CIPMUX=1\r\n", "OK")){delay_xms(500);}printf("5. CIPSERVER\r\n");while(ESP8266_SendCmd("AT+CIPSERVER=1,8080\r\n", "OK"))delay_xms(500);printf("6. CIFSR\r\n");while(ESP8266_SendCmd("AT+CIFSR\r\n", "OK"))delay_xms(500);printf("6. ESP8266 Init OK\r\n");return 0;
}
_Bool Esp8266_Init_One_TCP_Client()
{ESP8266_Clear();printf("1. CWMODE\r\n");while(ESP8266_SendCmd("AT+CWMODE=1\r\n", "OK"))delay_xms(5000);// printf("1.1 CWDHCP\r\n");// while(ESP8266_SendCmd("AT+CWDHCP=1,1\r\n", "OK"))// 		delay_xms(5000);printf("1.1 CIPSTA\r\n");while(ESP8266_SendCmd("AT+CIPSTA=\"192.168.1.87\",\"192.168.1.1\",\"255.255.255.0\"\r\n", "OK"))delay_xms(5000);//printf("2. CWJAP\r\n");while(ESP8266_SendCmd(ESP8266_JAP_INFO, "OK"))//WIFI CONNECTED ;// OKdelay_xms(5000);// printf("2.1 AT+RST\r\n");// while(ESP8266_SendCmd("AT+RST\r\n", "OK"))// 		delay_xms(20000);printf("3. CIFSR\r\n");while(ESP8266_SendCmd("AT+CIFSR\r\n", "OK"))delay_xms(5000);printf("4. CIPSTART\r\n");while(ESP8266_SendCmd(ESP8266_TCP_SERVER_INFO, "ERROR")==0)delay_xms(5000*10);printf("4. ESP8266 Init OK\r\n");return 0;
}int main(int argc, char *argv[])
{u8 test_buf[] = "esp8266 $$$$$!\r\n";// Uart4_Init(115200, argv[1]); // 初始化串口4Uart5_Init(115200, argv[1]); // 初始化串口5//async_io_init(); // 异步IO初始化,相当于STM32的外部中断配置的初始化,不过STM32下应该是硬件中断,这里是软件中断 // while (Esp8266_Init())// {//     printf("Esp8266 Init Failed!!!\r\n");// }while (Esp8266_Init_One_TCP_Client()){printf("Esp8266 Init Failed!!!\r\n");}while (1){if(ESP8266_Recive() == -1){sleep(1); continue;}/* 通信测试 */if (strstr((const char*)buf, "AA")){ESP8266_SendData(test_buf,strlen(test_buf));ESP8266_Clear();}else if(strstr((const char*)buf, "end")){sleep(1); ESP8266_Clear();break;}}/* 退出 */tcsetattr(fd, TCSANOW, &old_cfg);   //恢复到之前的配置close(fd);exit(EXIT_SUCCESS);
}

三、测试结果

初始化部分

1. CWMODE
***********************
AT+CWMODE=1OK
***********************
1.1 CIPSTA
***********************
AT+CIPSTA="192.168.1.87","192.168.1.1","255.255.255.0"OK
***********************
2. CWJAP
***********************
AT+CWJAP="TP-LINK_xxxx","123456789"
WIFI DISCONNECT
WIFI CONNECTED
WIFI GOT IPOK
***********************
3. CIFSR
***********************
AT+CIFSR
+CIFSR:STAIP,"192.168.1.87"
+CIFSR:STAMAC,"34:94:54:7f:d4:71"OK
***********************
4. CIPSTARTpoll read error =0
***********************
AT+CIPSTART="TCP","192.168.1.182",8080
CONNECTOK
***********************
4. ESP8266 Init OK

主函数循环接收,接收到AA,返回 esp8266 $$$$$!,接收到end,则结束。
在这里插入图片描述
在这里插入图片描述

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

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

相关文章

CentOS 7.6安装部署Seafile服务器

今天飞飞和你们分享CentOS 7.6上安装基于MySQL/MariaDB的Seafile服务器的方法&#xff0c;包括下载和安装7.0.5版本、配置数据库、启动服务器等步骤。安装成功后&#xff0c;需要通过nginx反向代理才能访问seafile服务。 通过预编译好的安装包来安装并运行基于 MySQL/MariaDB …

高吞吐SFTP连接池设计方案

背景 在现代的数据驱动环境中&#xff0c;安全文件传输协议&#xff08;SFTP&#xff09;扮演着至关重要的角色&#xff0c;它提供了一种安全、可靠的文件传输方式。我们目前项目是一个大型数据集成平台&#xff0c;跟上下游有很多文件对接是通过SFTP协议&#xff0c;当需要处…

果蔬作物疾病防治系统|基于Springboot的果蔬作物疾病防治系统设计与实现(源码+数据库+文档)

果蔬作物疾病防治系统目录 目录 基于Springboot的果蔬作物疾病防治系统设计与实现 一、前言 二、系统设计 三、系统功能设计 1、果蔬百科列表 2、公告信息管理 3、公告类型管理 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、最新计算机毕设选题推…

【蓝桥·算法双周赛】第七场分级赛——小白入门赛

2.霓虹【算法赛】 - 蓝桥云课 (lanqiao.cn) st数组用来存第i个位置&#xff0c;这个字母有没有编号j #include<bits/stdc.h> const int N1e610; using lllong long; std::map<std::string,std::string> mp;std::string a,aa; int st[N][10];// int stt[N][10];//对…

Qt 拖动事件

文章目录 1 自定义控件 TextEdit2 实现打开文件功能3 实现鼠标滚轮放大字体 QEvent::DragEnter 当拖动文件进入到窗口/控件中时&#xff0c;触发该事件&#xff0c;它对应的子类是QDragEnterEvent QEvent::DragLeave 当拖动文件离开窗口/控件时&#xff0c;触发该事件&#xff…

WordPress高端后台美化WP Adminify Pro优化版

后台UI美化WP Adminify Pro修改自定义插件&#xff0c;适合建站公司和个人使用&#xff0c;非常高大上&#xff0c;下载地址&#xff1a;WP Adminify Pro优化版 修复记录&#xff1a; 1、修复已知BUG 2、修复手机版兼容问题 3、修复打开速度&#xff0c;原版打开速度太慢 4…

自动裁剪人脸:简化你的数字人素材准备

在做数字人时,需要对采集的数据进行预处理,然后才能进行模型训练, 预处理常用的操作有:去背景 音频重采样 视频裁剪 音频特征提取等等,今天我们来分享一个自动化脚本: 对原图/视频进行人脸检测并根据目标尺寸以人脸为中心进行裁剪. 目录 1. 效果 2. 对图片进行裁剪 3.对视频…

DeepLearning in Pytorch|共享单车预测NN详解(思路+代码剖析)

目录 概要 一、代码概览 二、详解 基本逻辑 1.数据准备 2.设计神经网络 初版 改进版 测试 总结 概要 原文链接&#xff1a;DeepLearning in Pytorch|我的第一个NN-共享单车预测 我的第一个深度学习神经网络模型---利用Pytorch设计人工神经网络对某地区租赁单车的使用…

umi4 项目使用 keepalive 缓存页面(umi-plugin-keep-alive、react-activation)

umi4使用keepalive 配置文件config\config.ts export default defineConfig({plugins: [umi-plugin-keep-alive], });安装add umi-plugin-keep-alive yarn add umi-plugin-keep-alive页面 A import { KeepAlive, history, useAliveController } from umijs/max; const Page…

CSAPP Malloc lab

CSAPP Malloc Lab 目标 实现一个简单的动态存储分配器。 评分标准 空间利用率应当减少internal 和 external fragmentation. memory utilization memory utilization payload / heap size fragmentation internal fragmentation external fragmentation throughput T 越接…

【深度学习笔记】6_9 深度循环神经网络deep-rnn

注&#xff1a;本文为《动手学深度学习》开源内容&#xff0c;部分标注了个人理解&#xff0c;仅为个人学习记录&#xff0c;无抄袭搬运意图 6.9 深度循环神经网络 本章到目前为止介绍的循环神经网络只有一个单向的隐藏层&#xff0c;在深度学习应用里&#xff0c;我们通常会用…

嵌入式Qt 制作一个登录对话框

一.登录对话框需求分析 二.代码实现 main.c&#xff1a; #include <QtGui/QApplication> #include "widget.h"int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); }Widget.h&#xff1a; #ifndef _WIDGET_H_…

为什么选择 Flink 做实时处理

优质博文&#xff1a;IT-BLOG-CN 为什么选择 Flink 【1】流数据更真实地反映了我们的生活方式&#xff08;实时聊天&#xff09;&#xff1b; 【2】传统的数据架构是基于有限数据集的&#xff08;Spark 是基于微批次数据处理&#xff09;&#xff1b; 【3】我们的目标&#xf…

ELK-介绍及Elasticsearch集群搭建

ELK是三个开源软件的缩写&#xff0c;分别为Elasticsearch、Logstash、kibana它们都是开源软件。后来新增了一个FileBeat&#xff0c;它是一个轻量及的日志收集处理工具&#xff0c;因为Logstash由java程序开发&#xff0c;比较消耗内存资源&#xff0c;后来将Logstash使用go语…

【论文阅读】(2024.03.05-2024.03.15)论文阅读简单记录和汇总

(2024.03.05-2024.03.15)论文阅读简单记录和汇总 2024/03/05&#xff1a;随便简单写写&#xff0c;以后不会把太详细的记录在CSDN&#xff0c;有道的Markdown又感觉不好用。 目录 &#xff08;ICMM 2024&#xff09;Quality Scalable Video Coding Based on Neural Represent…

.net6Api后台+uniapp导出Excel

之前的这个是vue3写法&#xff0c;后端是.net6Api.net6Api后台VUE3前端实现上传和下载文件全过程_vue3 下载文件-CSDN博客 在现在看来似乎搞的复杂了&#xff0c;本次记录一下.net6Api后台uniapp导出Excel。 后端和之前的不一样&#xff0c;前端也和之前的不一样&#xff0c;…

【C语言】深入理解指针(进阶篇)

一、数组名的理解 数组名就是地址&#xff0c;而且是数组首元素的地址。 任务&#xff1a;运行以下代码&#xff0c;看数组名是否是地址。 #include <stdio.h> int main() {int arr[] { 1,2,3,4,5,6,7,8,9,0 };printf("&arr[0] %p\n", &arr[0]);pri…

IntelliJ IDEA Dev 容器

​一、dev 容器 开发容器&#xff08;dev 容器&#xff09;是一个 Docker 容器&#xff0c;配置为用作功能齐全的开发环境。 IntelliJ IDEA 允许您使用此类容器来编辑、构建和运行您的项目。 IntelliJ IDEA 还支持多个容器连接&#xff0c;这些连接可以使用 Docker Compose …

从零开始:神经网络(1)——神经元和梯度下降

声明&#xff1a;本文章是根据网上资料&#xff0c;加上自己整理和理解而成&#xff0c;仅为记录自己学习的点点滴滴。可能有错误&#xff0c;欢迎大家指正。 一. 神经网络 1. 神经网络的发展 先了解一下神经网络发展的历程。从单层神经网络&#xff08;感知器&#xff09;开…

HCIP --- BGP 综合实验

实验拓扑图&#xff1a; 实验要求&#xff1a; 1.AS1存在两个环回&#xff0c;一个地址为192.168.1.0/24该地址不能 在任何协议中宣告 AS3中存在两个环回&#xff0c;一个地址为192.168.2.0/24该地址不能在任何协议中宣告&#xff0c;最终要求这两个环回可以互相通讯. 2.整个…