消息队列LiteQueue

news2024/11/27 21:39:21

文章目录

  • 一、简介
  • 二、设计
    • 2.1 队列结构设计
    • 2.2 队列接口设计
  • 三、实现
    • 3.1 队列锁的实现
    • 3.2 创建队列
    • 3.3 写入队列
    • 3.4 读出数据
    • 3.5 判断队列是否为空
    • 3.6 判断队列是否为满
    • 3.7 清空队列
    • 3.8 删除队列
  • 四、测试
  • 参考

一、简介

  • 收到消息时先把接收到的消息放到队列中。
  • 在任务中从队列获取数据。
  • 如果解析过程中再来一帧数据,这帧数据会先存放在消息队列中。
  • 当队列中的上一帧数据解析完成后,任务会从队列中的下一条数据开始解析处理,以此循环,直到队列中的消息解析处理完毕。

二、设计

2.1 队列结构设计

有头尾指针分别指向写入的位置和读出的位置
需要配置队列中最多能存储几帧数据即几个列表项,每一项有多大的空间去保存接收到的数据
在这里插入图片描述
LiteQueue相当于是头部,后面紧跟着的是数据,而且每一个数据的存储大小都是确定的。
考虑到多线程不能同时读或者写,要互斥访问,因此还需要加一个读写锁

/*
LiteQueue : Structure describing queue parameters.
item_num_x: Number of items.
item_size : The size of each list item set when creating the queue,
            unit: bytes, used to store data received in the queue.
item_size : The counter of items
*/
typedef struct {    
    volatile uint8_t  queue_write_lock;
    volatile uint8_t  queue_read_lock;
    
    uint8_t   *head;    
    uint8_t   *tail;
    size_t    item_num;    
    size_t    item_size;
    size_t    item_count; 
}LiteQueue,   *pLiteQueue;

2.2 队列接口设计

使用队列前必定先要创建队列,并确定创建队列的大小,其次是读写队列的接口,以及判断队列是否为空/满、清空队列、删除队列

LiteQueue *LiteQueue_Create(size_t item_num, size_t item_size);  
LiteQueue_Status Write_To_LiteQueue(LiteQueue *queue, uint8_t *buff);  
LiteQueue_Status Read_From_LiteQueue(LiteQueue *queue, uint8_t *buff);
LiteQueue_Status isLiteQueue_Empty(LiteQueue *queue);
LiteQueue_Status LiteQueue_Clear(LiteQueue *queue);
LiteQueue_Status LiteQueue_Delete(LiteQueue *queue);
LiteQueue_Status isLiteQueue_Full(LiteQueue *queue); 
LiteQueue_Status isLiteQueue_Empty(LiteQueue *queue); 

队列的状态用一个枚举类型实现

typedef enum{    
    LITE_QUEUE_IDLE = 0,    
    LITE_QUEUE_BUSY,   
    LITE_QUEUE_ERR,    
    LITE_QUEUE_OK,
    LITE_QUEUE_EMPTY,   
    LITE_QUEUE_NONEMPTY,
    LITE_QUEUE_FULL,
    LITE_QUEUE_NONFULL
}LiteQueue_Status;

三、实现

3.1 队列锁的实现

队列锁使用宏定义的方式实现

typedef enum{    
    LITE_QUEUE_UNLOCK = 0, 
    LITE_QUEUE_LOCK,
}LiteQueueLock;

#define  LITE_QUEUE_WRITE_LOCK(__QUEUE__) do{            \
    if((__QUEUE__)->queue_write_lock == LITE_QUEUE_LOCK){\
        return LITE_QUEUE_BUSY;                          \
    } else {                                             \
        (__QUEUE__)->queue_write_lock = LITE_QUEUE_LOCK; \
    }                                                    \
}while(0) 

#define  LITE_QUEUE_WRITE_UNLOCK(__QUEUE__) do{          \
    (__QUEUE__)->queue_write_lock = LITE_QUEUE_UNLOCK;   \
}while(0)                                                  
       
#define  LITE_QUEUE_READ_LOCK(__QUEUE__) do{             \
    if((__QUEUE__)->queue_read_lock == LITE_QUEUE_LOCK){ \
        return LITE_QUEUE_BUSY;                          \
    } else {                                             \
        (__QUEUE__)->queue_read_lock = LITE_QUEUE_LOCK;  \
    }                                                    \
}while(0)       

#define  LITE_QUEUE_READ_UNLOCK(__QUEUE__) do{           \
    (__QUEUE__)->queue_read_lock = LITE_QUEUE_UNLOCK;    \
}while(0)  

3.2 创建队列

/**
* @ brief : Create message queue.
* @ param : {size_t     } item_num : The number of list items in the queue.
            {size_t     } item_size: The size of each list item, unit: bytes.
* @ return: {LiteQueue *} queue    : Message queue handle pointer.
* @ note  : Create a queue and initialize the queue items to 0, with the head and tail pointers pointing to the starting position of the list items.
*/
LiteQueue *LiteQueue_Create(size_t item_num, size_t item_size){
    if((item_num < 1) || (item_size < 1)){
        return NULL;
    }
    
    LiteQueue *queue = (LiteQueue *)malloc(sizeof(LiteQueue) + item_num * item_size);
    
    if( queue == NULL ) {
        printf("LiteQueue malloc failed.\r\n");
        return NULL;
    }
    
    memset((uint8_t *)queue, 0, sizeof(LiteQueue) + item_num * item_size);
    queue->head = (uint8_t *)((uint8_t *)queue + sizeof(LiteQueue));
    queue->tail = queue->head;
    queue->item_num = item_num;
    queue->item_size = item_size;
    queue->item_count = 0;
    queue->queue_read_lock = LITE_QUEUE_UNLOCK;
    queue->queue_write_lock = LITE_QUEUE_UNLOCK;
    
    return queue;
}

3.3 写入队列

/**
* @ brief : Write data to the queue.
* @ param : {LiteQueue      *} queue: Message queue handle pointer.
            {uint8_t        *} buff : Data to be written to the queue.
* @ return: {LiteQueue_Status} Returns the status of the queue.
* @ note  : Writing data when the queue is full will automatically overwrite the first frame of data.
*/
LiteQueue_Status Write_To_LiteQueue(LiteQueue *queue, uint8_t *buff){
    if((queue == NULL) || (buff == NULL)){
        return LITE_QUEUE_ERR;
    }
    
    LITE_QUEUE_WRITE_LOCK(queue);
    
    if(isLiteQueue_Full(queue) == LITE_QUEUE_FULL){
            return LITE_QUEUE_FULL;
        }
    
    memcpy(queue->tail, buff, queue->item_size);
    
    if(queue->tail == (uint8_t *)queue + sizeof(LiteQueue) + (queue->item_num - 1) * queue->item_size){
        queue->tail = (uint8_t *)queue + sizeof(LiteQueue);
    }else{
        queue->tail += queue->item_size;
    }
    queue->item_count += 1;
    
    LITE_QUEUE_WRITE_UNLOCK(queue);
    return LITE_QUEUE_OK;
}

3.4 读出数据

/**
* @ brief : Read data from queue.
* @ param : {LiteQueue      *} queue: Message queue handle pointer.
            {uint8_t        *} buff : Data to be read from the queue.
* @ return: {LiteQueue_Status} Returns the status of the queue.
* @ note  : Read data starting from the position of the head pointer and save it to the buff.
*/
LiteQueue_Status Read_From_LiteQueue(LiteQueue *queue, uint8_t *buff){
    if((queue == NULL) || (buff == NULL) || (isLiteQueue_Empty(queue) == LITE_QUEUE_EMPTY)){
        return LITE_QUEUE_ERR;
    }
    
    LITE_QUEUE_READ_LOCK(queue);
    if(isLiteQueue_Empty(queue) == LITE_QUEUE_EMPTY){
            return LITE_QUEUE_EMPTY;
        }
    memcpy(buff, queue->head, queue->item_size);  
    if(queue->head == (uint8_t *)queue + sizeof(LiteQueue) + (queue->item_num - 1) * queue->item_size){
        queue->head = (uint8_t *)queue + sizeof(LiteQueue);
    }else{
        queue->head += queue->item_size;
    }
    
    queue->item_count -= 1;
    LITE_QUEUE_READ_UNLOCK(queue);
    return LITE_QUEUE_OK;  
}

3.5 判断队列是否为空

/**
* @ brief : Determine whether the queue is empty.
* @ param : {LiteQueue      *} queue: Message queue handle pointer.
* @ return: {LiteQueue_Status} Returns the status of the queue.
* @ note  : Determine whether the head and tail pointers are the same. If they are the same,             
            it means there is no data in the queue, otherwise it means there is still data that has not been read out.
*/
inline LiteQueue_Status isLiteQueue_Empty(LiteQueue *queue){
    if(queue == NULL){
        return LITE_QUEUE_ERR;
    }
    
    if( queue->item_count == 0 ) {
        return LITE_QUEUE_EMPTY;
    }else{
        return LITE_QUEUE_NONEMPTY;
    } 
}

3.6 判断队列是否为满

/**
* @ brief : Determine whether the queue is full.
* @ param : {LiteQueue      *} queue: Message queue handle pointer.
* @ return: {LiteQueue_Status} Returns the status of the queue.
* @ note  : Determine whether the head and tail pointers are the same. If they are the same,             
            it means there is no data in the queue, otherwise it means there is still data that has not been read out.
*/
inline LiteQueue_Status isLiteQueue_Full(LiteQueue *queue){
    if(queue == NULL){
        return LITE_QUEUE_ERR;
    }
    
    if( queue->item_count == queue->item_num) {
            return LITE_QUEUE_FULL;
    }else{
            return LITE_QUEUE_NONFULL;
    } 
}

3.7 清空队列

/**
* @ brief : Clear the message queue.
* @ param : {LiteQueue      *} queue: Message queue handle pointer.
* @ return: {LiteQueue_Status} Returns the status of the queue.
* @ note  : Determine whether the head and tail pointers are the same. 
            If they are the same,it means there is no data in the queue, otherwise it means there is still data that has not been read out.
*/
LiteQueue_Status LiteQueue_Clear(LiteQueue *queue){
    if(queue == NULL) {
        return LITE_QUEUE_ERR;
    }
    LITE_QUEUE_WRITE_LOCK(queue);
    queue->head = (uint8_t *)((uint8_t *)queue + sizeof(LiteQueue));
    queue->tail = queue->head;
    queue->item_count = 0;
    
    memset(queue->head, 0, queue->item_num * queue->item_size);
    LITE_QUEUE_WRITE_UNLOCK(queue);
    return LITE_QUEUE_OK;
}

3.8 删除队列

/**
* @ brief : Clear the message queue.
* @ param : {LiteQueue      *} queue: Message queue handle pointer.
* @ return: {LiteQueue_Status} Returns the status of the queue.
* @ note  : Determine whether the head and tail pointers are the same. 
            If they are the same,it means there is no data in the queue, otherwise it means there is still data that has not been read out.
*/
LiteQueue_Status LiteQueue_Delete(LiteQueue *queue){
    if(queue == NULL) {
        return LITE_QUEUE_ERR;
    }
    //memset((uint8_t *)queue, 0, sizeof(LiteQueue) + queue->item_num * queue->item_size);
    free(queue);
    queue = NULL;
    return LITE_QUEUE_OK;
}

四、测试

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef unsigned char uint8_t;
typedef unsigned int  uint32_t;

/*
LiteQueue : Structure describing queue parameters.
item_num_x: Number of items.
item_size : The size of each list item set when creating the queue,
            unit: bytes, used to store data received in the queue.
*/
typedef struct {    
    volatile uint8_t  queue_write_lock;
    volatile uint8_t  queue_read_lock;
    
    uint8_t   *head;    
    uint8_t   *tail;
    size_t    item_num;    
    size_t    item_size;
    size_t    item_count; 
}LiteQueue,   *pLiteQueue;

typedef enum{    
    LITE_QUEUE_IDLE = 0,    
    LITE_QUEUE_BUSY,   
    LITE_QUEUE_ERR,    
    LITE_QUEUE_OK,
    LITE_QUEUE_EMPTY,   
    LITE_QUEUE_NONEMPTY,
    LITE_QUEUE_FULL,
    LITE_QUEUE_NONFULL
}LiteQueue_Status;

typedef enum{    
    LITE_QUEUE_UNLOCK = 0, 
    LITE_QUEUE_LOCK,
}LiteQueueLock;

#define  LITE_QUEUE_WRITE_LOCK(__QUEUE__) do{            \
    if((__QUEUE__)->queue_write_lock == LITE_QUEUE_LOCK){\
        return LITE_QUEUE_BUSY;                          \
    } else {                                             \
        (__QUEUE__)->queue_write_lock = LITE_QUEUE_LOCK; \
    }                                                    \
}while(0) 

#define  LITE_QUEUE_WRITE_UNLOCK(__QUEUE__) do{          \
    (__QUEUE__)->queue_write_lock = LITE_QUEUE_UNLOCK;   \
}while(0)                                                  
       
#define  LITE_QUEUE_READ_LOCK(__QUEUE__) do{             \
    if((__QUEUE__)->queue_read_lock == LITE_QUEUE_LOCK){ \
        return LITE_QUEUE_BUSY;                          \
    } else {                                             \
        (__QUEUE__)->queue_read_lock = LITE_QUEUE_LOCK;  \
    }                                                    \
}while(0)       

#define  LITE_QUEUE_READ_UNLOCK(__QUEUE__) do{           \
    (__QUEUE__)->queue_read_lock = LITE_QUEUE_UNLOCK;    \
}while(0)   


LiteQueue *LiteQueue_Create(size_t item_num, size_t item_size);  
LiteQueue_Status Write_To_LiteQueue(LiteQueue *queue, uint8_t *buff);  
LiteQueue_Status Read_From_LiteQueue(LiteQueue *queue, uint8_t *buff);
LiteQueue_Status isLiteQueue_Empty(LiteQueue *queue);
LiteQueue_Status LiteQueue_Clear(LiteQueue *queue);
LiteQueue_Status LiteQueue_Delete(LiteQueue *queue);
LiteQueue_Status isLiteQueue_Full(LiteQueue *queue); 
LiteQueue_Status isLiteQueue_Empty(LiteQueue *queue); 

/**
* @ brief : Create message queue.
* @ param : {size_t     } item_num : The number of list items in the queue.
            {size_t     } item_size: The size of each list item, unit: bytes.
* @ return: {LiteQueue *} queue    : Message queue handle pointer.
* @ note  : Create a queue and initialize the queue items to 0, with the head and tail pointers pointing to the starting position of the list items.
*/
LiteQueue *LiteQueue_Create(size_t item_num, size_t item_size){
    if((item_num < 1) || (item_size < 1)){
        return NULL;
    }
    
    LiteQueue *queue = (LiteQueue *)malloc(sizeof(LiteQueue) + item_num * item_size);
    
    if( queue == NULL ) {
        printf("LiteQueue malloc failed.\r\n");
        return NULL;
    }
    
    memset((uint8_t *)queue, 0, sizeof(LiteQueue) + item_num * item_size);
    queue->head = (uint8_t *)((uint8_t *)queue + sizeof(LiteQueue));
    queue->tail = queue->head;
    queue->item_num = item_num;
    queue->item_size = item_size;
    queue->item_count = 0;
    queue->queue_read_lock = LITE_QUEUE_UNLOCK;
    queue->queue_write_lock = LITE_QUEUE_UNLOCK;
    
    return queue;
}

/**
* @ brief : Write data to the queue.
* @ param : {LiteQueue      *} queue: Message queue handle pointer.
            {uint8_t        *} buff : Data to be written to the queue.
* @ return: {LiteQueue_Status} Returns the status of the queue.
* @ note  : Writing data when the queue is full will automatically overwrite the first frame of data.
*/
LiteQueue_Status Write_To_LiteQueue(LiteQueue *queue, uint8_t *buff){
    if((queue == NULL) || (buff == NULL)){
        return LITE_QUEUE_ERR;
    }
    
    LITE_QUEUE_WRITE_LOCK(queue);
    
    if(isLiteQueue_Full(queue) == LITE_QUEUE_FULL){
            return LITE_QUEUE_FULL;
        }
    
    memcpy(queue->tail, buff, queue->item_size);
    
    if(queue->tail == (uint8_t *)queue + sizeof(LiteQueue) + (queue->item_num - 1) * queue->item_size){
        queue->tail = (uint8_t *)queue + sizeof(LiteQueue);
    }else{
        queue->tail += queue->item_size;
    }
    queue->item_count += 1;
    
    LITE_QUEUE_WRITE_UNLOCK(queue);
    return LITE_QUEUE_OK;
}

/**
* @ brief : Read data from queue.
* @ param : {LiteQueue      *} queue: Message queue handle pointer.
            {uint8_t        *} buff : Data to be read from the queue.
* @ return: {LiteQueue_Status} Returns the status of the queue.
* @ note  : Read data starting from the position of the head pointer and save it to the buff.
*/
LiteQueue_Status Read_From_LiteQueue(LiteQueue *queue, uint8_t *buff){
    if((queue == NULL) || (buff == NULL) || (isLiteQueue_Empty(queue) == LITE_QUEUE_EMPTY)){
        return LITE_QUEUE_ERR;
    }
    
    LITE_QUEUE_READ_LOCK(queue);
    if(isLiteQueue_Empty(queue) == LITE_QUEUE_EMPTY){
            return LITE_QUEUE_EMPTY;
        }
    memcpy(buff, queue->head, queue->item_size);  
    if(queue->head == (uint8_t *)queue + sizeof(LiteQueue) + (queue->item_num - 1) * queue->item_size){
        queue->head = (uint8_t *)queue + sizeof(LiteQueue);
    }else{
        queue->head += queue->item_size;
    }
    
    queue->item_count -= 1;
    LITE_QUEUE_READ_UNLOCK(queue);
    return LITE_QUEUE_OK;  
}

/**
* @ brief : Determine whether the queue is empty.
* @ param : {LiteQueue      *} queue: Message queue handle pointer.
* @ return: {LiteQueue_Status} Returns the status of the queue.
* @ note  : Determine whether the head and tail pointers are the same. If they are the same,             
            it means there is no data in the queue, otherwise it means there is still data that has not been read out.
*/
inline LiteQueue_Status isLiteQueue_Empty(LiteQueue *queue){
    if(queue == NULL){
        return LITE_QUEUE_ERR;
    }
    
    if( queue->item_count == 0 ) {
            return LITE_QUEUE_EMPTY;
        }else{
                return LITE_QUEUE_NONEMPTY;
        } 
}

/**
* @ brief : Determine whether the queue is full.
* @ param : {LiteQueue      *} queue: Message queue handle pointer.
* @ return: {LiteQueue_Status} Returns the status of the queue.
* @ note  : Determine whether the head and tail pointers are the same. If they are the same,             
            it means there is no data in the queue, otherwise it means there is still data that has not been read out.
*/
inline LiteQueue_Status isLiteQueue_Full(LiteQueue *queue){
    if(queue == NULL){
        return LITE_QUEUE_ERR;
    }
    
    if( queue->item_count == queue->item_num) {
            return LITE_QUEUE_FULL;
        }else{
                return LITE_QUEUE_NONFULL;
        } 
}

/**
* @ brief : Clear the message queue.
* @ param : {LiteQueue      *} queue: Message queue handle pointer.
* @ return: {LiteQueue_Status} Returns the status of the queue.
* @ note  : Determine whether the head and tail pointers are the same. 
            If they are the same,it means there is no data in the queue, otherwise it means there is still data that has not been read out.
*/
LiteQueue_Status LiteQueue_Clear(LiteQueue *queue){
    if(queue == NULL) {
        return LITE_QUEUE_ERR;
    }
    LITE_QUEUE_WRITE_LOCK(queue);
    queue->head = (uint8_t *)((uint8_t *)queue + sizeof(LiteQueue));
    queue->tail = queue->head;
    queue->item_count = 0;
    
    memset(queue->head, 0, queue->item_num * queue->item_size);
    LITE_QUEUE_WRITE_UNLOCK(queue);
    return LITE_QUEUE_OK;
}

/**
* @ brief : Clear the message queue.
* @ param : {LiteQueue      *} queue: Message queue handle pointer.
* @ return: {LiteQueue_Status} Returns the status of the queue.
* @ note  : Determine whether the head and tail pointers are the same. 
            If they are the same,it means there is no data in the queue, otherwise it means there is still data that has not been read out.
*/
LiteQueue_Status LiteQueue_Delete(LiteQueue *queue){
    if(queue == NULL) {
        return LITE_QUEUE_ERR;
    }
    //memset((uint8_t *)queue, 0, sizeof(LiteQueue) + queue->item_num * queue->item_size);
    free(queue);
    queue = NULL;
    return LITE_QUEUE_OK;
}

/**
* @ brief : Print the contents of each list item in the queue.
* @ param : {LiteQueue *} queue: Message queue handle pointer.
* @ return: None.
*/
static void PrintLiteQueue(LiteQueue *queue){
    if(queue == NULL){
        return ;
    }
    
    for(int i = 0; i < queue->item_num; i++){
        printf("[item_num:%d] ", i);
        for(int n = 0; n < queue->item_size; n++){
            printf("%d ", *((uint8_t *)queue + sizeof(LiteQueue) + i * queue->item_size + n));
        }
        printf("\r\n");
    }
}

/**
* @ brief : Print the data in buff.
* @ param : {LiteQueue *} queue: Message queue handle pointer.
* @ return: None.
* @ note  : Used to observe buff data changes and test to verify the correctness of written or read data.
*/
static void PrintBuff(uint8_t *buff, size_t len){
    if((buff == NULL) || (len < 1)){
        return ;
    }
    printf("Read buff<<<:");
    for(size_t i = 0; i < len; i++){
        printf("%d ", buff[i]);
    }
    printf("\r\n\r\n");
}

int main(){
    uint8_t writebuff[10] = {0};
    uint8_t readbuff[10]  = {0};
     /* Create message queue, 4 list items, each list item has 10 bytes of memory space */
    pLiteQueue msgQueue = LiteQueue_Create(4, 10);
    PrintLiteQueue(msgQueue);
    printf("\r\n");
    /* Simulate writing and reading to the queue 6 times, and observe the data in the queue by printing */
    for(int i=0;i<6;i++ ) {
        /* Simulate data, change the writebuff data and write it to the queue */
        for(int n = 0; n < msgQueue->item_size; n++){
            writebuff[n] = (i * msgQueue->item_size + n) % 256;
        }
        
        /* Data is written to the queue */
        Write_To_LiteQueue(msgQueue, writebuff);
        PrintLiteQueue(msgQueue);
        
        /* Read data from queue */
        Read_From_LiteQueue(msgQueue, readbuff);
        PrintBuff(readbuff, sizeof(readbuff));
    }
    return 0;
}

在这里插入图片描述

参考

https://mp.weixin.qq.com/s/vI3g4JmSXMyKrpnIV1vjbg

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

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

相关文章

360高级java面试真题

今年IT寒冬&#xff0c;大厂都裁员或者准备裁员&#xff0c;作为开猿节流主要目标之一&#xff0c;我们更应该时刻保持竞争力。为了抱团取暖&#xff0c;林老师开通了《知识星球》&#xff0c;并邀请我阿里、快手、腾讯等的朋友加入&#xff0c;分享八股文、项目经验、管理经验…

问界M9激光雷达解说

什么是激光雷达 激光雷达(英文:Lidar),是一种通过发射激光束来测量目标位置、速度等特征量的雷达系统。其工作原理是将激光光束照射到目标物体上,然后通过测量激光光束从发射到反射回来的时间,来计算目标物体的距离、位置、速度等参数。激光雷达通常用于测量地形、地貌、…

关键字:throw关键字

在 Java 中&#xff0c;throw关键字用于抛出异常。当程序执行过程中发生意外情况&#xff0c;如错误的输入、资源不足、错误的逻辑等&#xff0c;导致程序无法正常执行下去时&#xff0c;可以使用throw关键字抛出异常。 以下是使用throw关键字的一些示例&#xff1a; 抛出异常…

事务失效的十种常见场景

学习事务失效场景 1 概述 事务的传播类型isolationTransactionnal注解属性 事务方法未被Spring管理方法使用final类型修饰非public修饰的方法同一个类中的方法相互调用方法的事务传播类型不支持事务异常被内部catch&#xff0c;程序生吞异常数据库不支持事务未配置开启事务错…

用python做猴子摘桃的题目,java猴子爬台阶算法

本篇文章给大家谈谈猴子爬山算法java完整代码&#xff0c;以及用python做猴子摘桃的题目&#xff0c;希望对各位有所帮助&#xff0c;不要忘了收藏本站喔。 """ 一天一只猴子想去从山脚爬到山顶&#xff0c;途中经过一个有N个台阶的阶梯&#xff0c;但是这猴子有…

Matlab技巧[绘画逻辑分析仪产生的数据]

绘画逻辑分析仪产生的数据 逻分上抓到了ADC数字信号,一共是10Bit,12MHZ的波形: 这里用并口协议已经解析出数据: 导出csv表格数据(这个数据为补码,所以要做数据转换): 现在要把这个数据绘制成波形,用Python和表格直接绘制速度太慢了,转了一圈发现MATLAB很好用,操作方法如下:…

Koordinator 助力云原生应用性能提升:小红书混部技术实践

作者&#xff1a;宋泽辉&#xff08;小红书&#xff09;、张佐玮&#xff08;阿里云&#xff09; 编者按&#xff1a; Koordinator 是一个开源项目&#xff0c;是基于阿里巴巴内部多年容器调度、混部实践经验孵化诞生&#xff0c;是行业首个生产可用、面向大规模场景的开源混…

科荣AIO UtilServlet存在任意文件读取漏洞

文章目录 产品简介漏洞概述指纹识别漏洞利用修复建议 产品简介 科荣AIO是一款企业管理软件&#xff0c;提供企业一体化管理解决方案。它整合了ERP&#xff08;如进销存、财务管理&#xff09;、OA&#xff08;办公自动化&#xff09;、CRM&#xff08;客户关系管理&#xff09…

MySQL 数值函数,字符串函数与多表查询

MySQL像其他语言一样,也提供了很多库函数,分为单行函数和分组函数(聚合函数),我们这里先简易介绍一些函数,熟悉就行,知道怎么使用即可. 数值函数 三角函数 指数与对数函数 进制间的转换函数 字符串函数 注:LPAD函数是右对齐,RPAD函数是左对齐 多表查询 注:如果为表起了别名,就…

微服务(11)

目录 51.pod的重启策略是什么&#xff1f; 52.描述一下pod的生命周期有哪些状态&#xff1f; 53.创建一个pod的流程是什么&#xff1f; 54.删除一个Pod会发生什么事情&#xff1f; 55.k8s的Service是什么&#xff1f; 51.pod的重启策略是什么&#xff1f; 可以通过命令kub…

47、激活函数 - sigmoid

今天在看一个比较常见的激活函数,叫作 sigmoid 激活函数,它的数学表达式为: 其中,x 为输入,画出图来看更直观一些。 Sigmoid 函数的图像看起来像一个 S 形曲线,我们先分析一下这个函数的特点。 Sigmoid 函数的输出范围在 (0, 1) 之间,并且不等于0或1。 Sigmoid 很明显是…

每日算法打卡:递归实现指数型枚举 day 1

文章目录 原题链接题目描述输入格式输出格式数据范围输入样例&#xff1a;输出样例&#xff1a; 题目分析 原题链接 92. 递归实现指数型枚举 题目难度&#xff1a;简单 题目描述 从 1 ∼ n 1 \sim n 1∼n 这 n 个整数中随机选取任意多个&#xff0c;输出所有可能的选择方案…

字节高级Java面试真题

今年IT寒冬&#xff0c;大厂都裁员或者准备裁员&#xff0c;作为开猿节流主要目标之一&#xff0c;我们更应该时刻保持竞争力。为了抱团取暖&#xff0c;林老师开通了《知识星球》&#xff0c;并邀请我阿里、快手、腾讯等的朋友加入&#xff0c;分享八股文、项目经验、管理经验…

240101-5步MacOS自带软件无损快速导出iPhone照片

硬件准备&#xff1a; iphone手机Mac电脑数据线 操作步骤&#xff1a; Step 1: 找到并打开MacOS自带的图像捕捉 Step 2: 通过数据线将iphone与电脑连接Step 3&#xff1a;iphone与电脑提示“是否授权“&#xff1f; >>> “是“Step 4&#xff1a;左上角选择自己的设…

C++程序编译

GCC编译器 文章目录 GCC编译器 源文件 为 Main.cpp 注意cpp文件 一定要用g命令 否则没办法执行 预处理&#xff08;Pre-Processing&#xff09;&#xff1a;首先会经过预处理器将程序中的预编译指令进行处理&#xff0c;然后把源文件中的注释这些没用的东西都给扬了。 g -E Mai…

数据结构期末复习(3)栈和队列

堆栈&#xff08;stack&#xff09; 堆栈&#xff08;stack&#xff09;是一种基于后进先出&#xff08;LIFO&#xff0c;Last In First Out&#xff09;原则的数据结构。它模拟了现实生活中的堆栈&#xff0c;类似于一摞盘子或一堆书。 堆栈有两个基本操作&#xff1a;入栈&a…

StratifiedKFold解释和代码实现

StratifiedKFold解释和代码实现 文章目录 一、StratifiedKFold是什么&#xff1f;二、 实验数据设置2.1 实验数据生成代码2.2 代码结果 三、实验代码3.1 实验代码3.2 实验结果3.3 结果解释3.4 数据打乱对这种交叉验证的影响。 四、总结 一、StratifiedKFold是什么&#xff1f; …

Serverless Framework:开发无服务器应用的最佳工具 | 开源日报 No.133

serverless/serverless Stars: 45.6k License: MIT 该项目是 Serverless Framework&#xff0c;它是一个命令行工具&#xff0c;使用简单易懂的 YAML 语法部署代码和云基础设施以满足各种无服务器应用程序需求。支持 Node.js、Typescript、Python、Go 等多种编程语言&#xff…

Mysql体系结构一次讲清

Mysql进阶 Mysql体系结构 大体来说&#xff0c;MySQL 可以分为 Server 层和存储引擎层两部分。 Server层 主要包括连接器、查询缓存、分析器、优化器、执行器等&#xff0c;涵盖 MySQL 的大多数核心服务功能&#xff0c;以及所有的内 置函数&#xff08;如日期、时间、数…

我的512天创作者纪念日总结:高效、高现

文章目录 512天创作者纪念日&#xff1a;2023年的12月31日CSDN的512天消息提醒第一篇文章&#xff0c;最后一篇文章总计847篇文章&#xff0c;每月发文分布512天&#xff0c;各专栏文章统计512天&#xff0c;互动总成绩 512天创作者纪念日&#xff1a;2023年的12月31日 2023年…