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

Linux网络编程day7 线程池and UDP

线程池

typedef struct{void*(*function)(void*);        //函数指针,回调函数void*arg;                       //上面函数的参数
}threadpool_task_t;                 //各子线程任务的结构体/*描述线程池相关信息*/struct threadpool_t{pthread_mutex_t lock;           // 用于锁住本结构体pthread_mutex_t thread_counter; //记录忙状态线程个数的锁 -- bust_thr_numpthread_cond_t queue_not_full;  //当任务队列满时 , 添加任务的线程阻塞 , 等待此条件变量pthread_cond_t queue_not_empty; //任务队列不为空时,通知等待任务的线程pthread_t *threads;             //存放线程池中每个线程的Tid . 数组pthread_t adjust_tid;           //存管理线程的tidthreadpool_task_t *task_queue;  //任务队列--数组首地址int min_thr_num;                //线程池最小线程数int max_thr_num;                //线程池最大线程数int live_thr_num;               //当前存活线程个数int busy_thr_num;               //忙状态线程个数int wait_exit_thr_num;          //要销毁的线程个数int queue_front;                //task_queue队头下标int queue_rear;                 //task_queue队尾下标int queue_size;                 //task_queue队中实际任务数int queue_max_size;             //task_queue队列可容纳任务数上限int shutdown;                   //标志位,线程池使用状态,true or false
};

线程池模块分析

1、main():创建线程池

                   向线程池中添加任务,借助回调处理任务

                   销毁线程池

int main(void)
{//threadpool_t * threadpool_create(int min_thr_num , int max_thr_num , int queue_max_size);threadpool_t *thp = threadpool_create(3 , 100 , 100);//创建线程池,最大数量100,最小数量3 ,任务队列最
大容量100.printf("pool inited");int num[20] , i;  //模拟客户端向服务器发送数据等场景for(i = 0; i < 20 ; i++){num[i] = i;printf("add task %d\n" , i);//int threadpool_add(threadpool_t *pool , void*(*function)(void*arg) , void arg);threadpool_add(thp , process , (void*)&num[i]); //向线程池中添加任务}sleep(10);  //等待子线程完成任务threadpool_destroy(thp);return 0 ;
}

2、pthreadpool_create:创建线程池结构体指针

                                        初始化线程池结构体中N个成员变量

                                        创建N个任务线程

                                        创建1个管理者线程

                                        失败时 , 释放空间

threadpool_t* threadpool_create(int min_thr_num , int max_thr_num , int queue_max_size)
{int i ;struct threadpool_t *pool = NULL; // 线程池 结构体do{if((pool = (struct threadpool_t*)malloc(sizeof(struct threadpool_t))) == NULL){printf("malloc threadpool fail");break;}pool->min_thr_num = min_thr_num;pool->max_thr_num = max_thr_num;pool->busy_thr_num = 0;pool->live_thr_num = min_thr_num; //活着的线程数 初值=最小线程数pool->wait_exit_thr_num = 0;pool->queue_size = 0; //有0个产品pool->queue_max_size = queue_max_size;//最大任务队列数pool->queue_front = 0;pool->queue_rear = 0;pool->shutdown = false; // 不关闭线程池/*根据最大线程上线数 , 给工作线程数组开辟空间,清零*/pool->threads = (pthread*)malloc(sizeof(pthread_t)*max_thr_num);if(pool->threads == NULL){printf("malloc threads fail");break;}memset(pool->threads , 0 , sizeof(pthread_t)*max_thr_num);/*给任务队列开辟空间 */pool->task_queue = (threadpool_task_t*)malloc(sizeof(threadpool_task_t)*queue_max_size);if(pool->task_queue == NULL){printf("malloc task_queue fail");break;}/*初始化互斥锁、条件变量 , 使用init动态初始化 , 加上进行返回值判断*/if(pthread_mutex_init((&pool->lock) , NULL) != 0|| pthread_mutex_init(&(pool->thread_counter) , NULL) != 0|| pthread_cond_init(&(pool->queue_not_empty) , NULL) != 0|| pthread_cond_init(&(pool->queue_not_full) , NULL) != 0){printf("init the lock or cond fail");break;}/*启动min_thr_num个work thread*/for(i = 0 ; i < min_thr_num ; i++){pthread_create(&(pool->threads[i]) , NULL , threadpool_thread , (void*)pool);//pool指向当前线>程池printf("stat thread 0x%x...\n" , (unsigned int)pool->threads[i]);}pthread_create(&(pool->adjust_tid) , NULL , adjust_thread , (void*)pool);//创建管理者线程return pool;}while(0);threadpool_free(pool); // 前面代码调用失败时,释放pool空间return NULL;
}

3、threadpool_thread():进入子线程回调函数。

                                         接收参数(void*)arg

                                         加锁--》lock--》整个结构体的锁

                                         判断条件变量--》wait

/* 线程池中各个工作线程 */
void* threadpool_thread(void* threadpool)
{struct threadpool_t *pool = (struct threadpool_t*)threadpool;threadpool_task_t task;//任务队列对象while(true){/*刚创建出线程,等待任务队列里面有队列 ,否则阻塞等待任务队列李有任务后再唤醒接收任务*/pthread_mutex_lock(&(pool->lock));//queue_size = 0说明没有任务,调用wait函数阻塞在条件变量上,若有任务,跳过whilewhile((pool->queue_size == 0) && (!pool->shutdown)){printf("thread 0x%x is waiting\n" , (unsigned int)pthread_self());pthread_cond_wait(&(pool->queue_not_empty) , &(pool->lock));//清除指定数目的空闲线程,如果要结束的线程个数大于0,结束线程if(pool->wait_exit_thr_num > 0 ){pool->wait_exit_thr_num--;//如果线程池里线程个数大于最小值时可以结束当前线程if(pool->live_thr_num > pool->min_thr_num){printf("thread 0x%x is exiting\n" , (unsigned int)pthread_self());pool_live_thr_num--;pthread_mutex_unlock(&(pool->lock));pthread_exit(NULL);}}//指定true,要关闭线程池里的每个线程,自行退出-->销毁线程池if(pool->shutdown){pthread_mutex_unlock(&(pool->lock));printf("thread 0x%x is exiting\n" , (unsigned int)pthread_self());pthread_detach(pthread_self());pthread_exit(NULL); // 线程自行结束}//从任务队列获取任务,出队操作task.function = pool->task_queue[pool->queue_front].function;task.arg = pool->task_queue[pool->queue_front].arg;pool->queue_front = (pool->queue_front + 1) % pool->queue_max_size; //出队,模拟环形pool->queue_size--;//通知可以有新的任务添加进来pthread_cond_broadcast(&(pool->queue_not_full));//任务取出后立即将线程池锁释放pthread_mutex_unlock(&(pool->lock));//执行任务printf("thread 0x%x stat working\n" , (unsigned int)pthread_self());pthread_mutex_lock(&(pool->thread_counter));    //忙状态线程数变量锁pool->busy_thr_num++;                           //忙状态线程数+1pthread_mutex_unlock(&((pool->thread_counter));(*(task.function))(task.arg);//执行回调函数//任务结束处理printf("thread 0x%x end working\n" , (unsigned int)pthread_self());pthread_mutex_lock(&(pool->thread_counter));pool->busy_thr_num--;                           //处理掉任务,忙状态线程数-1pthread_mutex_unlock(&(pool->thread_counter));}pthread_exit(NULL);
}

4、adjust_thread():进入管理者线程回调函数                                 

                                 循环10s执行一次

                                 接收参数(void*)arg

                                 加锁--》lock--》整个结构体的锁

                                 获取管理线程时需要用到的变量:live busy queue task

                                 根据既定算法,使用上述3变量判断是否应该创建、销毁线程池中的指定步长的线程。

void* adjust_thread(void* threadpool)
{int i ;struct threadpool_t *pool = (struct threadpool_t*)threadpool;while(!pool->shutdown){sleep(DEFAULT_TIME); //定时对线程池管理pthread_mutex_lock(&(pool->lock));int queue_size = pool->queue_size;int live_thr_num  = pool->live_thr_num;pthread_mutex_unlock(&(pool->lock));pthread_mutex_lock(&(pool->thread_counter));int busy_thr_num = pool->busy_thr_num;pthread_mutex_unlock(&(pool->pthread_counter));//创建新线程,任务数大于最小线程池个数,且存活线程数少于最大线程数if(queue_size >= MIN_WAIT_TASK_NUM && live_thr_num < pool->max_thr_num){pthread_mutex_lock(&(pool->lock));int add = 0;//一次增加DEFAULT_THREAD个线程for(i = 0 ; i < pool->max_thr_num && add < DEFAULT_THREAD_VARY&& pool->live_thr_num < pool_max_thr_num ; i++){pthread_create(&(pool->thread[i]) , NULL , threadpool_thread , (void*)pool);add++;pool->live_thr_num++;}pthread_mutex_unlock(&(pool->lock));}if((busy_thr_num *2) < live_thr_num && live_thr_num > pool->min_thr_num){pthread_mutex_lock(&(pool->lock));pool->wait_exit_thr_num = DEFAULT_THREAD_VARY;pthread_mutex_unlock(&(pool->lock));for(i = 0 ; i < DEFAULT_THREAD_VARY ; i++){pthread_cond_signal(&(pool->queue_not_empty));}}}return NULL;
}

5、threadpool_add:模拟产生任务 num[20]

                                  设置回调函数,处理任务sleep(1)代表处理完成

                                  初始化任务队列结构体成员 回调函数和arg

                                  利用环形队列机制实现添加任务,借助队尾指针

                                  唤醒阻塞在条件变量上的线程

//线程池中的线程,模拟处理业务
void* process(void*arg)
{printf("thread 0x%x working on task %d\n" , (unsigned int)pthread_self() , (int)arg);sleep(1);printf("task %d is end\n" , (int)arg);return NULL
}
int threadpool_add(struct threadpool_t *pool , (void*)(**function)(void*arg) , (void*)arg)
{pthread_mutex_lock(&(pool->lock));//为真 , 队列已满 , 调用wait阻塞while((pool->queue_size == pool->queue_max_size) && (!pool->shutdown)){pthread_cond_wait(&(pool->queue_not_full) , &(pool->lock));}if(pool->shutdown){pthread_cond_broadcast(&(pool->queue_not_empty));pthread_mutex_unlock(&(pool->lock));return 0 ;}//清空工作线程 调用的回调函数 的参数if(pool->task_queue[pool->queue_rear].arg != NULL){pool->task_queue[pool->queue_rear].arg = NULL;}//添加任务到任务队列pool->task_queue[pool->queue_rear].function = function;pool->task_queue[pool->queue_rear].arg = arg;pool->queue_rear = (pool->queue_rear + 1) % pool->queue_max_size;//队尾指针移动,模拟环形pool->queue_size++;//向任务队列中添加一个任务//添加完任务后,队列不为空,唤醒线程池中等待处理任务的线程pthread_cond_signal(&(pool->queue_not_empty));pthread_mutex_unlock(&(pool->lock));return 0 ;
}

6、从3中wait之后执行,处理任务:获取任务处理回调函数及参数

                        利用环形队列机制实现处理任务,借助队头指针

                        唤醒阻塞在条件变量上的server

                        修改忙线程数量++

                        执行处理任务线程

                        修改忙线程数量--

7、创建和销毁线程:管理者线程根据上述三个参数判断是否创建、销毁

                                   满足创建条件pthread_create()回调任务线程函数

                                   满足销毁条件wait_exit_thr_num赋值,signal给阻塞在条件变量上的线程发送假条件满足信号,跳转至wait阻塞,阻塞线程会被假信号唤醒,使用pthread_exit。

int threadpool_destroy(threadpool_t *pool)
{int i;if(pool == NULL)return -1;pool->shutdown = true;pthread_join(pool->adjust_tid , NULL);for(i = 0 ; i < pool->live_thr_num ; i++){pthread_cond_broadcast(&(pool->queue_not_empty));}for(i = 0; i < pool->live_thr_num ; i++){pthread_join(pool->threads[i] , NULL);}threadpool_free(pool);return 0;
}
int threadpool_free(threadpool_t *pool)
{if(pool == NULL)return -1;if(pool->task_queue)free(pool->tast_queue);if(pool->threads){free(pool->threads);pthread_mutex_lock(&(pool->lock));pthread_mutex_destroy(&(pool->lock));pthread_mutex_lock(&(pool->thread_counter));pthread_mutex_destroy(&(pool->thread_counter));pthread_cond_destroy(&(pool->queue_not_full));pthread_cond_destroy(&(pool->queue_not_empty));}free(pool);pool = NULL;return 0;
}

UDP服务器

TCP通信和UDP通信的优缺点

TCP

面向连接的,可靠数据包传输。对于不稳定的网络层,采取完全弥补的通信方式,丢包重传。

优点:稳定 数据流量稳定、速度稳定、顺序

缺点:传输速度慢、效率低,资源开销大。

使用场景:数据完整要求性较高,不追求效率

                  大数据传输、文件传输。

UDP

无连接的,不可靠的数据报传递。对于不稳定的网络层,采取完全不弥补的通信方式,默认还原网络状况。

优点:传输速度快,效率高,资源开销小。

缺点:不稳定 数据流量、速度不稳定,顺序不稳定

使用场景:对时效性要求较高场合。稳定性其次。

                  游戏、视频会议、视频电话。     

----腾讯、华为、阿里 -- 应用层添加数据校验协议,弥补UDP的不足

UDP实现的C/S模型

无三次握手建立连接,故没有accept()、connect()

recv()/send()只能用于TCP通信

server

server:
lfd = socket(AF_INET , SOCK_DGRAM , 0);   SOCK_DGRAM--->报式协议
bind();
listen(); ----可有可无
while(1){  //不使用read函数recvfrom() //涵盖accept函数中的传出地址结构sendto();
}
close();

client

cfd = socket(AF_INET , SOCK_DGRAM , 0);sendto("服务器地址结构" , 地址结构大小)recvfrom()
写屏幕
close()

recvfrom函数

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
socket:lfd
buf:缓冲区地址
len:缓冲区大小
flags:0
src_addr:传出参数,传出对端地址结构
src_addr:传入传出返回值:成功接收数据字节数
失败-1 errno   0对端关闭

sendto函数                 

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
socket:套接字
buf:存储数据的缓冲区
len:数据长度
flags:0
dest_addr:传入参数,目标地址结构
src_addr:地址结构长度返回值:成功写出数据字节数
失败-1 errno   

udp server端模型

#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<ctype.h>
#define SERV_PORT 9004
void sys_err(char*s)
{perror(s);exit(1);
}int main(int argc , char*argv[])
{int sockfd , i , n;char buf[BUFSIZ] , str[INET_ADDRSTRLEN];struct sockaddr_in serv_addr , clit_addr;socklen_t clitlen;bzero(&serv_addr , sizeof(serv_addr));serv_addr.sin_family = AF_INET;serv_addr.sin_port = htons(SERV_PORT);serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);sockfd  = socket(AF_INET , SOCK_DGRAM , 0);if(sockfd == -1)sys_err("socket error");bind(sockfd , (struct sockaddr*)&serv_addr , sizeof(serv_addr));printf("Accepting connections-----");while(1){clitlen = sizeof(clit_addr);n = recvfrom(sockfd , buf , strlen(buf) , 0 , (struct sockaddr*)clit_addr, &clitlen);if(n == -1)sys_err("recvfrom error");printf("received from %s at port%d\n" , inet_ntop(AF_INET , &clit_addr.sin_addr , str , sizeof(str)),ntohs(clit_addr.sin_port));for(i = 0 ; i < n ; i++)buf[i] = toupper(buf[i]);n = sendto(sockfd , buf , n , 0 , (struct sockaddr*)&clit_addr , sizeof(clit_addr));if(n == -1)sys_err("sendto error");}close(sockfd);return 0 ;
}

udp client端模型

#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<ctype.h>
#define SERV_PORT 9004void sys_err(char*s)
{perror(s);exit(1);
}int main(int argc , char*argv[])
{int sockfd , i , n;char buf[BUFSIZ] ;struct sockaddr_in serv_addr;bzero(&serv_addr , sizeof(serv_addr));serv_addr.sin_family = AF_INET;serv_addr.sin_port = htons(SERV_PORT);inet_pton(AF_INET , "xx.xx.x.xxx" , &serv_addr.sin_addr.s_addr);sockfd  = socket(AF_INET , SOCK_DGRAM , 0);if(sockfd == -1)sys_err("socket error");while((fgets = (buf , BUFSIZ , stdin)) != NULL){n = sendto(sockfd , buf , strlen(buf) , 0 ,(struct sockaddr*)&serv_addr , sizeof(serv_addr));if(n == -1)sys_err("sendto error");n = recvfrom(sockfd , buf , BUFSIZ , 0 , NULL , 0);if(n == -1)sys_err("recvfrom error"); write(STDOUT_FILENO , buf , n); }close(sockfd);return 0 ;
}

相关文章:

Linux网络编程day7 线程池and UDP

线程池 typedef struct{void*(*function)(void*); //函数指针&#xff0c;回调函数void*arg; //上面函数的参数 }threadpool_task_t; //各子线程任务的结构体/*描述线程池相关信息*/struct threadpool_t{pthread_mutex_t lock; …...

wsl - install RabbiqMQ

下载erlang $ sudo apt -y install erlang 安装软件包 $ sudo apt -y install rabbitmq-server 修改配置文件 $ sudo vi /etc/rabbitmq/rabbitmq-env.conf # Defaults to rabbit. This can be useful if you want to run more than one node # per machine - RABBITMQ_NODENAME…...

ABB电机保护单元通过Profibus DP主站转Modbus TCP网关实现上位机通讯

ABB电机保护单元通过Profibus DP主站转Modbus TCP网关实现上位机通讯 在工业自动化领域&#xff0c;设备之间的通信至关重要。Profibus DP是一种广泛应用的现场总线标准&#xff0c;而Modbus TCP则是一种基于以太网的常见通信协议。将Profibus DP主站转换为Modbus TCP网关&…...

深入解析二维矩阵搜索:LeetCode 74与240题的两种高效解法对比

文章目录 **引言** **一、问题背景与排序规则对比****1. LeetCode 74. 搜索二维矩阵****2. LeetCode 240. 搜索二维矩阵 II** **二、核心解法对比****方法1&#xff1a;二分查找法&#xff08;适用于LeetCode 74&#xff09;****方法2&#xff1a;线性缩小搜索范围法&#xff0…...

迪士尼机器人BD-X 概况

这些机器人代表着迪士尼故事叙述与非凡创新的完美结合。它们不仅栩栩如生&#xff0c;还配备了先进的技术。 -迪士尼幻想工程研发部高级副总裁凯尔劳克林 幕景 BDX 机器人是由华特迪士尼公司的研究和幻想工程部门利用NVIDIA人工智能技术 (AI)开发的现实世界机器人&#xff0c;…...

UE5骨骼插槽蓝图

首先在人物骨骼处添加插槽并命名&#xff0c;然后再选择添加预览资产把你要的模型&#xff08;静态网格体&#xff09;放上去。 选择绑定的骨骼再去右边相对位置、旋转等调整物体。 再去人物蓝图里面写就ok了...

移动应用开发:自定义 View 处理大量数据的性能与交互优化方案

实现 1 万条数据下流畅滑动与灵敏交互的完美平衡。 一、数据渲染优化&#xff1a;从 1 万条到丝滑体验 &#xff08;一&#xff09;视图复用机制 视图复用是提升大量数据渲染性能的关键策略。以一个简单的自定义列表视图为例&#xff0c;我们可以构建如下的复用池管理机制&a…...

绘制拖拽html

<!DOCTYPE html> <html lang"zh-CN"> <head> <meta charset"UTF-8" /> <meta name"viewport" content"widthdevice-width, initial-scale1" /> <title>拖拽绘制矩形框 - 可移动可调整大小</ti…...

C++结构体介绍

结构体的定义 在C中&#xff0c;结构体&#xff08;struct&#xff09;是一种用户定义的数据类型&#xff0c;允许将不同类型的数据组合在一起。结构体的定义使用struct关键字&#xff0c;后跟结构体名称和一对花括号{}&#xff0c;花括号内包含成员变量的声明。 struct Pers…...

ggplot2 | GO barplot with gene list

1. 效果图 2. 代码 数据是GO的输出结果&#xff0c;本文使用的是 metascape 输出的excel挑选的若干行。 # 1. 读取数据 datread.csv("E:\\research\\scPolyA-seq2\\GO-APA-Timepoint\\test.csv", sep"\t") head(dat)# 2. 选择所需要的列 dat.usedat[, c(…...

PostgreSQL 的 pg_advisory_lock 函数

PostgreSQL 的 pg_advisory_lock 函数 pg_advisory_lock 是 PostgreSQL 提供的一种应用级锁机制&#xff0c;它不锁定具体的数据库对象&#xff08;如表或行&#xff09;&#xff0c;而是通过数字键值来协调应用间的并发控制。 锁的基本概念 PostgreSQL 提供两种咨询锁(advi…...

docker 镜像的导出和导入(导出完整镜像和导出容器快照)

一、导出原始镜像 1. 使用 docker save 导出完整镜像 适用场景&#xff1a;保留镜像的所有层、元数据、标签和历史记录&#xff0c;适合迁移或备份完整镜像环境。 操作命令 docker save -o <导出文件名.tar> <镜像名:标签>示例&#xff1a;docker save -o milvu…...

系统思考:短期困境与长期收益

最近在项目中&#xff0c;一直有学员会提到一个议题&#xff0c;如何平衡当前困境和长期收益&#xff1f; 我的思考是在商业和人生的路上&#xff0c;我们常常听到“鱼和熊掌不可兼得”的说法&#xff0c;似乎短期利益和长期目标注定是对立的。但事实上&#xff0c;鱼与熊掌是…...

4.2【LLaMA-Factory实战】金融财报分析系统:从数据到部署的全流程实践

【LLaMA-Factory实战】金融财报分析系统&#xff1a;从数据到部署的全流程实践 一、引言 在金融领域&#xff0c;财报分析是投资决策的核心环节。传统分析方法面临信息提取效率低、风险识别不全面等挑战。本文基于LLaMA-Factory框架&#xff0c;详细介绍如何构建一个专业的金…...

Cjson格式解析与接入AI大模型

JSON格式的解析与构造 基本概念 JSON是JavaScript Object Notation的简称&#xff0c;中文含义为“JavaScript 对象表示法”&#xff0c;它是一种数据交换的文本格式&#xff0c;而不是一种编程语言。 JSON 是一种轻量级的数据交换格式&#xff0c;采用完全独立于编程语言的…...

基于英特尔 RealSense D455 结构光相机实现裂缝尺寸以及深度测量

目录 一&#xff0c;相机参数规格 二&#xff0c;结合YOLO实例分割实现裂缝尺寸以及深度测量 2.1 应用场景 2.2 实现流程 2.3 效果展示 2.4 精度验证 2.5 实物裂缝尺寸以及深度测量效果展示 一&#xff0c;相机参数规格 英特尔 RealSense D455 是英特尔 RealSense D400 系…...

Nacos源码—7.Nacos升级gRPC分析四

大纲 5.服务变动时如何通知订阅的客户端 6.微服务实例信息如何同步集群节点 6.微服务实例信息如何同步集群节点 (1)服务端处理服务注册时会发布一个ClientChangedEvent事件 (2)ClientChangedEvent事件的处理源码 (3)集群节点处理数据同步请求的源码 (1)服务端处理服务注册…...

TIME - MoE 模型代码 3.2——Time-MoE-main/time_moe/datasets/time_moe_dataset.py

源码&#xff1a;GitHub - Time-MoE/Time-MoE: [ICLR 2025 Spotlight] Official implementation of "Time-MoE: Billion-Scale Time Series Foundation Models with Mixture of Experts" 这段代码定义了一个用于时间序列数据处理的 TimeMoEDataset 类&#xff0c;支…...

【某OTA网站】phantom-token 1004

新版1004 phantom-token 请求头中包含phantom-token 定位到 window.signature 熟悉的vmp 和xhs一样 最新环境检测点 最新检测 canvas 下的 toDataURL方法较严 过程中 会用setAttribute给canvas 设置width height 从而使toDataURL返回不同的值 如果写死toDataURL的返回值…...

OrangePi Zero 3学习笔记(Android篇)2 - 第一个C程序

目录 1. 创建项目文件夹 2. 创建c/cpp文件 3. 创建Android.mk/Android.bp文件 3.1 Android.mk 3.2 Android.bp 4. 编译 5. adb push 6. 打包到image中 在AOSP里面添加一个C或C程序&#xff0c;这个程序在Android中需要通过shell的方式运行。 1. 创建项目文件夹 首先需…...

DeepResearch深度搜索实现方法调研

DeepResearch深度搜索实现方法调研 Deep Research 有三个核心能力 能力一&#xff1a;自主规划解决问题的搜索路径&#xff08;生成子问题&#xff0c;queries&#xff0c;检索&#xff09;能力二&#xff1a;在探索路径时动态调整搜索方向&#xff08;刘亦菲最好的一部电影是…...

使用大语言模型进行机器人规划(Robot planning with LLMs)

李升伟 编译 长期规划在机器人学领域可以从经典控制方法与大型语言模型在现实世界知识能力的结合中获益。 在20世纪80年代&#xff0c;机器人学和人工智能&#xff08;AI&#xff09;领域的专家提出了莫雷奇悖论&#xff0c;观察到人类看似简单的涉及移动和感知的任务&#x…...

【论文阅读】基于客户端数据子空间主角度的聚类联邦学习分布相似性高效识别

Efficient distribution similarity identification in clustered federated learning via principal angles between client data subspaces -- 基于客户端数据子空间主角度的聚类联邦学习分布相似性高效识别 论文来源TLDR背景与问题两个子空间之间的主角&#xff08;Principa…...

Elasticsearch知识汇总之ElasticSearch部署

五 ElasticSearch部署 部署Elasticsearch&#xff0c;可以在任何 Linux、MacOS 或 Windows 机器上运行 Elasticsearch。在Docker 容器 中运行 Elasticsearch 。使用Elastic Cloud on Kubernetes 设置和管理 Elasticsearch、Kibana、Elastic Agent 以及 Kubernetes 上的 Elasti…...

ROBOVERSE:面向可扩展和可泛化机器人学习的统一平台、数据集和基准

25年4月来自UC Berkeley、北大、USC、UMich、UIUC、Stanford、CMU、UCLA 和 北京通用 AI 研究院&#xff08;BIGAI&#xff09;的论文“ROBOVERSE: Towards a Unified Platform, Dataset and Benchmark for Scalable and Generalizable Robot Learning”。 数据扩展和标准化评…...

LVGL的核心:lv_timer_handler

文章目录 &#x1f9e0; 一句话总结 LVGL 的运行核心&#xff1a;&#x1f501; 1. while(1) 主循环中的 lv_task_handler()⏱️ 2. lv_timer_handler() 定时器调度核心✅ 并发控制✅ 关键行为流程&#xff1a;&#x1f300; 任务执行逻辑&#xff1a;&#x1f9ee; 计算下一次…...

(41)VTK C++开发示例 ---qt使用vtk最小示例

文章目录 1. 概述2. CMake链接VTK3. main.cpp文件4. 演示效果 更多精彩内容&#x1f449;内容导航 &#x1f448;&#x1f449;VTK开发 &#x1f448; 1. 概述 本文演示了在Qt中使用VTK的最小示例程序&#xff0c;使用VTK创建显示一个锥体&#xff1b; 采用Cmake作为构建工具&a…...

⭐️⭐️⭐️【课时1:大模型是什么?】学习总结 ⭐️⭐️⭐️ for《大模型Clouder认证:基于百炼平台构建智能体应用》认证

一、学习目标 概要 通过学习《课时1:大模型是什么?》,全面了解大模型的基础概念、核心特点、发展脉络及阿里云在大模型领域的布局,为后续基于百炼平台构建智能体应用的实践操作打下坚实的理论基础。 具体目标列表 理解人工智能到大模型的演变逻辑,明确大模型在AI发展历…...

OS7.【Linux】基本指令入门(6)

目录 1.zip和unzip 配置指令 使用 两个名词:打包和压缩 打包 压缩 Linux下的操作演示 压缩和解压缩文件 压缩和解压缩目录 -d选项 2.tar Linux下的打包和压缩方案简介 czf选项 xzf选项 -C选项 tzf选项 3.bc 4.uname 不带选项的uname -a选项 -r选项 -v选项…...

国标GB28181视频平台EasyCVR安防系统部署知识:如何解决异地监控集中管理和组网问题

在企业、连锁机构及园区管理等场景中&#xff0c;异地监控集中管控与快速组网需求日益迫切。弱电项目人员和企业管理者亟需整合分散监控资源&#xff0c;实现跨区域统一管理与实时查看。 一、解决方案 案例一&#xff1a;运营商专线方案​ 利用运营商专线&#xff0c;连接各分…...