openCPU开发demo详解包括线程调度、队列等的使用

2023-05-16

OpenCPU开发例程的详细解释,包括各种功能的测试,如线程、队列等 源代码为osi_demo.c
初步学习,可能有误,仅供参考

demo详解

  • 代码
  • 部分系统函数
    • fibo_textTrace(输出日志)
    • fibo_thread_create(创建线程)
    • fibo_heapinfo_get(获取内存堆信息)
    • fibo_sem_signal(信号量操作)
    • fibo_sem_wait
    • fibo_sem_try_wait
    • fibo_malloc(申请内存)
  • 函数
    • appimg_enter(入口函数)
    • prvInvokeGlobalCtors(初始化)
    • test_sem_thread(测试线程)
    • test_sem(测试信号量)
    • test_queue2 (测试队列)

代码

/* Copyright (C) 2022 FIBOCOM Technologies Limited and/or its affiliates("FIBOCOM").
 * All rights reserved.
 *
 * This software is supplied "AS IS" without any warranties.
 * FIBOCOM assumes no responsibility or liability for the use of the software,
 * conveys no license or title under any patent, copyright, or mask work
 * right to the product. FIBOCOM reserves the right to make changes in the
 * software without notification.  FIBOCOM also make no representation or
 * warranty that such application will be suitable for the specified use
 * without further testing or modification.
 */


#define OSI_LOG_TAG OSI_MAKE_LOG_TAG('M', 'Y', 'A', 'P')

#include "fibo_opencpu.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
typedef __uint32_t uint32_t ;



static void prvInvokeGlobalCtors(void)
{
    extern void (*__init_array_start[])();
    extern void (*__init_array_end[])();

    size_t count = __init_array_end - __init_array_start;
    for (size_t i = 0; i < count; ++i)
        __init_array_start[i]();
}

static void test_ticks()
{
    UINT32 ticks = 0;
    ticks = fibo_get_sys_tick();
    fibo_textTrace("before ticks = %u", ticks);
    fibo_taskSleep(1000);
    ticks = fibo_get_sys_tick();
    fibo_textTrace("after ticks = %u", ticks);
}

uint32_t g_size;
uint32_t g_avail_size;
uint32_t g_max_block_size;
static void test_mem()
{
    char *pt = (char *)fibo_malloc(51200);
    if (pt != NULL)
    {
        fibo_textTrace("malloc address %u", (unsigned int)pt);
        fibo_free(pt);
    }

    fibo_heapinfo_get(&g_size, &g_avail_size, &g_max_block_size);
    fibo_textTrace("g_size = %u, g_avail_size = %u, g_max_block_size = %u", g_size, g_avail_size, g_max_block_size);
}

static void test_reset(int mode)
{
    if (mode == 0)
        fibo_soft_reset();
    else
        fibo_soft_power_off();
}


/* sem test begin */
UINT32 g_test_sem;
static void testSemThread(void *param)
{
    fibo_taskSleep(2000);
    fibo_textTrace("execute sem_signal...");
    fibo_sem_signal(g_test_sem);
    fibo_taskSleep(1000);
    fibo_sem_signal(g_test_sem);
    fibo_thread_delete();
}
static void test_sem()
{
    g_test_sem = fibo_sem_new(0);

    fibo_thread_create(testSemThread, "test_sem", 1024, NULL, OSI_PRIORITY_NORMAL);

    fibo_sem_wait(g_test_sem);
    fibo_textTrace("after sem_wait...");

    fibo_sem_try_wait(g_test_sem, 5000);
    fibo_textTrace("after sem_try_wait...");

    fibo_sem_try_wait(g_test_sem, 5000);
    fibo_textTrace("after sem_try_wait...");
    fibo_sem_free(g_test_sem);
}
/* sem test end */

/* mutex test begin */
UINT32 g_test_mutex;
static void test_mutex()
{
    g_test_mutex = fibo_mutex_create();
    fibo_textTrace("after mutex create...");

    fibo_mutex_lock(g_test_mutex);
    fibo_textTrace("after mutex lock...");

    fibo_mutex_unlock(g_test_mutex);
    fibo_textTrace("after mutex unlock...");

    fibo_mutex_try_lock(g_test_mutex, 3000);
    fibo_textTrace("after mutex try lock...");

    fibo_mutex_delete(g_test_mutex);
    fibo_textTrace("after mutex delete...");
}
/* mytex test end */

/* test timer begin */
void *g_test_timer = NULL;
void *g_test_timer2 = NULL;
void *g_period_timer = NULL;
void *g_period_timer2 = NULL;

void timer_function(void *arg)
{
    fibo_textTrace("timer function execute ...");
    fibo_timer_delete(g_test_timer);
}

void test_timer()
{
    g_test_timer = fibo_timer_create(timer_function, NULL, false);
    fibo_textTrace("test_timer_creat 1...");
    fibo_timer_start(g_test_timer, 6000, false);
}

void timer_function2(void *arg)
{
    fibo_textTrace("timer function2 execute ...");
    fibo_timer_delete(g_test_timer2);
}

void test_timer2()
{
    g_test_timer2 = fibo_timer_create(timer_function2, NULL, false);
    fibo_textTrace("test_timer_creat 2");

    fibo_timer_start(g_test_timer2, 6000, false);
}

void timer_function_period(void *arg)
{
    static int nr = 5;
    fibo_textTrace("timer period function execute ...");
    nr--;
    if(nr == 0)
        fibo_timer_delete(g_period_timer);
}

void test_timer_period()
{
    g_period_timer = fibo_timer_create(timer_function_period, NULL, false);
    fibo_timer_start(g_period_timer, 3000, true);
}

void timer_function_period2(void *arg)
{
    static int nr = 5;
    fibo_textTrace("timer period function2 execute cnt: %d...", nr);
    nr--;
    if(nr == 0)
    {
        fibo_timer_delete(g_period_timer2);
    }
}

void test_timer_period2()
{
    g_period_timer2 = fibo_timer_create(timer_function_period2, NULL, false);
    fibo_textTrace("test_timer_period2 ...");
    fibo_timer_start(g_period_timer2, 3000, true);
}
/* test timer end */

void test_rand()
{
    srand(1000);
    for (int i = 0; i < 10; i++)
    {
        fibo_textTrace("rand %d : %d", i, rand());
    }
}

/* test queue */
UINT32 g_queue_id = 0;
static void testQueueThread(void *param)
{
    int value = 8888;
    fibo_taskSleep(2000);
    fibo_queue_put(g_queue_id, &value, 0);
    fibo_thread_delete();
}

void test_queue()
{
    int value = 0;
    g_queue_id = fibo_queue_create(5, sizeof(int));
    fibo_thread_create(testQueueThread, "test_queue", 4096, NULL, OSI_PRIORITY_NORMAL);
    fibo_queue_get(g_queue_id, (void *)&value, 0);
    fibo_textTrace("test queue value = %d", value);
}

UINT32 g_queue_id2 = 0;
static void testQueueThread2(void *param)
{
    int i = 0;
    int value = 1111;
    fibo_taskSleep(2000);

    for (i = 1; i < 10; i++)
    {
        value = 1111 *i;
        fibo_queue_put_to_front(g_queue_id2, &value, 0);
        fibo_textTrace("test queue2 value put to front(%d) = %d", i, value);
    }

    fibo_thread_delete();
}

void test_queue2()
{
    int value = 0;
    g_queue_id2 = fibo_queue_create(10, sizeof(int));
    fibo_thread_create(testQueueThread2, "test_queue2", 4096, NULL, OSI_PRIORITY_NORMAL);

    fibo_taskSleep(5000);

    for (int i = 1; i < 10; i++)
    {
        fibo_queue_get(g_queue_id2, (void *)&value, 0);
        fibo_textTrace("test queue2 value get(%d) = %d", i, value);
    }
}

/* test queue end */

static void nullThread(void *param)
{
    for (int n = 0; n < 5; n++)
    {
        fibo_textTrace("null Thread in %d", n);
        fibo_taskSleep(1000);
    }
    fibo_thread_delete();
}


static void oc_osi_demo(void *param)
{
    fibo_textTrace("application thread enter, param 0x%x", param);
    test_ticks(); //测试时钟函数
    test_mem(); //测试内存管理函数
    test_sem(); //测试信号量函数
    test_mutex(); //测试互斥锁函数
    test_timer();  //测试定时器函数
    test_timer2();
    test_rand(); //随机数
    test_queue(); //队列
    test_queue2();
    test_timer_period(); //周期性定时函数
    test_timer_period2();
    test_reset(0); //复位函数

    for (int n = 0; n < 10; n++)
    {
        fibo_textTrace("hello world %d", n);
        fibo_taskSleep(1000);
    }
    fibo_taskSleep(1000);
    //test_reset(0);

    UINT32 thread_id = 0;
    fibo_thread_create_ex(nullThread, "nullthread",
        1024, NULL, OSI_PRIORITY_NORMAL, &thread_id); //创建一个新线程并打印线程ID
    fibo_textTrace("nullThread id = 0x%x", thread_id);

    fibo_thread_delete(); //删除线程
}

void* appimg_enter(void *param) //入口函数
{
    fibo_textTrace("application image enter, param 0x%x", param);

    prvInvokeGlobalCtors();

    fibo_thread_create(oc_osi_demo, "oc_osi_demo", 1024, NULL, OSI_PRIORITY_NORMAL);
    return 0;
}

void appimg_exit(void) //退出函数
{
    fibo_textTrace("application image exit");
}



部分系统函数

fibo_textTrace(输出日志)

INT32 fibo_textTrace
(
char *fmt, …
)

TRACE 输出的接口。从抓 LOG 的工具 coolwatcher 输出,fmt 字符串长度最大 255。

fibo_thread_create(创建线程)

(
void* pvTaskCode,
INT8 * pcName,
UINT32 usStackDepth,
void *pvParameters,
UINT32 uxPriority
)

任务函数接口
任务名称
任务栈大小,接口 U32 类型数据,理论可申请0xFFFFFFFF 这么大的栈空间,实际单个最大可 250K 左右,内存一般剩余 2M 多空间

任务函数输入参数
任务优先级

fibo_heapinfo_get(获取内存堆信息)

  • 是一个函数,它用于获取当前系统内存堆的信息,返回值是一个指向结构体 fibo_heap_info_t 的指针,结构体 fibo_heap_info_t 包含以下字段:
  • total_size:表示当前系统内存堆的总大小(单位:字节)。
  • used_size:表示当前系统内存堆已被使用的大小(单位:字节)。
  • max_free_size:表示当前系统内存堆中最大可用内存块的大小(单位:字节)。
  • frag_size:表示当前系统内存堆中内存碎片的大小(单位:字节)。

调用 fibo_heapinfo_get() 函数可以获取当前系统内存堆的信息,方便开发者进行内存管理和优化。通常在调试和优化阶段使用该函数,可以帮助开发者发现内存泄漏、内存碎片等问题。

fibo_sem_signal(信号量操作)

信号量+1,信号量为一个 UINT8 的值,使用时需要保证其不会溢出

fibo_sem_wait

信号量-1,当信号量为0时产生进程调度操作

fibo_sem_try_wait

与上述一致,但是增加了超时机制

fibo_malloc(申请内存)

举例:char *pt = (char *)fibo_malloc(51200);

获取内存地址:fibo_textTrace(“malloc address %u”, (unsigned int)pt);

释放内存:fibo_free(pt);

函数

appimg_enter(入口函数)

void* appimg_enter(void *param)
{
    fibo_textTrace("application image enter, param 0x%x", param);

    prvInvokeGlobalCtors();//初始化全局静态构造函数

    fibo_thread_create(oc_osi_demo, "oc_osi_demo", 1024, NULL, OSI_PRIORITY_NORMAL);
    return 0;
}

所有代码都会从入口函数开始执行,先初始化,再创建主线程

prvInvokeGlobalCtors(初始化)

static void prvInvokeGlobalCtors(void)
{
    extern void (*__init_array_start[])();
    extern void (*__init_array_end[])();

    size_t count = __init_array_end - __init_array_start;
    for (size_t i = 0; i < count; ++i)
        __init_array_start[i]();
}

这段代码的作用是调用全局静态构造函数(Global Static Constructor),也被称为初始化函数。全局静态构造函数是在程序启动时自动调用的一些函数,它们用于初始化全局静态变量或执行一些其他的初始化工作。

这段代码中,首先声明了两个外部变量 __init_array_start[]__init_array_end[],它们是在链接器脚本(Linker Script)中定义的符号,用于指示存储在程序的 .init_array 段中的初始化函数的起始地址和结束地址。在 C++ 中,全局静态构造函数是按照它们在 .init_array 段中出现的顺序来调用的。

接下来,代码计算了存储在 .init_array 段中的初始化函数的数量(即 count = __init_array_end - __init_array_start)。然后,通过一个 for 循环依次调用这些初始化函数,从而完成全局静态构造函数的调用过程。

这段代码是用于调用全局静态构造函数的,一般来说在标准 C/C++ 环境下编写的程序中都会包含这段代码。但是在嵌入式开发中,是否必须依赖于具体的开发环境和目标平台。

test_sem_thread(测试线程)

static void testSemThread(void *param)
{
    fibo_taskSleep(2000);
    fibo_textTrace("execute sem_signal...");
    fibo_sem_signal(g_test_sem);
    fibo_taskSleep(1000);
    fibo_sem_signal(g_test_sem);
    fibo_thread_delete();
}

test_sem(测试信号量)

static void test_sem()
{
    g_test_sem = fibo_sem_new(0);

    fibo_thread_create(testSemThread, "test_sem", 1024, NULL, OSI_PRIORITY_NORMAL);

    fibo_sem_wait(g_test_sem);
    fibo_textTrace("after sem_wait...");

    fibo_sem_try_wait(g_test_sem, 5000);
    fibo_textTrace("after sem_try_wait...");

    fibo_sem_try_wait(g_test_sem, 5000);
    fibo_textTrace("after sem_try_wait...");
    fibo_sem_free(g_test_sem);
}
  1. 这段代码的执行顺序如下:
    1. 主线程中创建一个初始值为0的信号量g_test_sem。
    2. 主线程创建一个名为"test_sem"的新线程testSemThread,并将信号量g_test_sem作为参数传递给该线程。
    3. testSemThread线程等待2秒钟,然后执行第一次信号量信号操作:使用fibo_sem_signal函数释放g_test_sem信号量。
    4. 主线程中调用fibo_sem_wait函数等待信号量g_test_sem。
    5. 当testSemThread释放g_test_sem信号量时,主线程的fibo_sem_wait函数返回,主线程输出"after sem_wait…"。
    6. 主线程中使用fibo_sem_try_wait函数尝试等待g_test_sem信号量,等待时间为5秒。
    7. testSemThread线程执行第二次信号量信号操作:使用fibo_sem_signal函数再次释放g_test_sem信号量。
    8. 主线程的fibo_sem_try_wait函数尝试等待g_test_sem信号量时,因为信号量已经被释放,所以不会等待,fibo_sem_try_wait函数返回0,主线程输出"after sem_try_wait…"。
    9. 主线程中再次使用fibo_sem_try_wait函数尝试等待g_test_sem信号量,等待时间为5秒。
    10. 因为g_test_sem信号量已经被释放,主线程的fibo_sem_try_wait函数不会等待,直接返回0,主线程输出"after sem_try_wait…"。
    11. 主线程释放g_test_sem信号量,并使用fibo_sem_free函数释放信号量内存。
    12. testSemThread线程调用fibo_thread_delete函数结束线程的执行。

test_queue2 (测试队列)

UINT32 g_queue_id2 = 0;
static void testQueueThread2(void *param)
{
    int i = 0;
    int value = 1111;
    fibo_taskSleep(2000);

    for (i = 1; i < 10; i++)
    {
        value = 1111 *i;
        fibo_queue_put_to_front(g_queue_id2, &value, 0);
        fibo_textTrace("test queue2 value put to front(%d) = %d", i, value);
    }

    fibo_thread_delete();
}

void test_queue2()
{
    int value = 0;
    g_queue_id2 = fibo_queue_create(10, sizeof(int));
    fibo_thread_create(testQueueThread2, "test_queue2", 4096, NULL, OSI_PRIORITY_NORMAL);

    fibo_taskSleep(5000);

    for (int i = 1; i < 10; i++)
    {
        fibo_queue_get(g_queue_id2, (void *)&value, 0);
        fibo_textTrace("test queue2 value get(%d) = %d", i, value);
    }
}

程序实现了在主线程中创建一个线程,在该线程中创建队列后返回主线程打印的功能

执行顺序为

  1. 在主线程中创建一个队列 g_queue_id2,大小为 10,元素类型为 int;
  2. 在主线程中创建一个名为 testQueueThread2 的线程,优先级为正常优先级,栈大小为 4096;
  3. testQueueThread2 线程启动,等待 2s 后开始执行以下循环: a. 将 value 设为 1111*i; b. 将 value 放入队列 g_queue_id2 的队首; c. 打印输出 “test queue2 value put to front(%d) = %d”;
  4. 主线程等待 5s;
  5. 在主线程中进行以下循环,共执行 9 次: a. 从队列 g_queue_id2 的队首取出一个元素,存储到 value 中; b. 打印输出 “test queue2 value get(%d) = %d”;
  6. 程序执行结束。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

openCPU开发demo详解包括线程调度、队列等的使用 的相关文章

  • go gRPC 服务端推送给客户端流demo

    具体文件目录看上一篇的grpc xff0c 这个demo演示的是服务端以流的形式推送给客户端 pb hello proto syntax span class token operator 61 span span class token
  • SpringBoot整合shiro——简单的demo

    结构目录 前端页面代码部分 index html span class token doctype span class token punctuation lt span span class token doctype tag DOCT
  • 一个简单的springboot整合shiro的demo

    index html span class token operator lt span span class token operator span DOCTYPE html span class token operator gt sp
  • NVIDIA Jetson TX2 查看系统相关+运行demo

    1 查看Jetson TX2 L4T版本 xff1a head n 1 etc nv tegra release 2 查看系统版本 xff1a cat etc lsb release 3 查看系统内核 xff1a uname a 4 查看内
  • 合宙ESP32S3 CameraWebServe 测试demo

    合宙ESP32S3 CameraWebServe 合宙ESP32S3 CameraWebServe测试 xff0c 我们需要一个OV2640的摄像头模组用来采集图像传输给ESP32的 xff0c 这里使用的OV2640是之前安信可十周年的白
  • Cropper的一个demo

    1 摸鱼大法第一招 Cropper Cropper 就是基于canvas做的小插件 xff0c 下面做的是一个图片裁剪 xff0c 各位看官看看就行 xff0c 有什么意见多提 A code block import Cropper fro
  • springboot整合shiro的小demo(一)

    刚学shiro整合springboot xff0c 在此做一个笔记 xff0c 以便后期忘了查阅 本文分以下几个方面进行整合以及验证 xff1a 1 springboot项目搭建整合thymeleaf实现页面访问 2 springboot整
  • Android仿淘宝购物车demo

    夏的热情渐渐退去 xff0c 秋如期而至 xff0c 丰收的季节 xff0c 小编继续着实习之路 xff0c 走着走着 xff0c 就走到了购物车 xff0c 逛过淘宝或者是京东的小伙伴都知道购物车里面的宝贝可不止一件 xff0c 对于爱购
  • 鸿蒙wifi Demo运行

    title 鸿蒙Wi Fi Demo运行 date 2021 1 1 22 25 10 categories harmony 本文首发于LHM s notes 欢迎关注我的博客 坑有点多 由于之前没有看过wifi的内核态代码 xff0c 所
  • tf-faster-rcnn跑demo.py出现InvalidArgumentError (see above for traceback): Assign requires shapes of bo

    基于tf faster rcnn做图像识别时 xff0c 使用自己的数据集 训练过程没有问题 xff0c 然后跑demo的时候报 xff1a InvalidArgumentError see above for traceback Assi
  • FreeRTOS的源代码个人分析(基于KEIL下STM32F103的Demo) 四

    开始任务的实现分析 xff1a xPortStartScheduler 函数 FreeRTOS里开始任务是在main里调用vTaskStartScheduler函数来开始任务的 xff0c 在调用这个函数后 xff0c 系统会先自动的创建一
  • 川崎duAro机器人 ROS_moveit demo

    说明 demo cpp Author hiics include lt ros ros h gt include lt iostream gt MoveIt include lt moveit move group interface mo
  • linux服务端下的c++ udp socket demo

    linux服务端 udp socket demo 如下 xff1a 创建接受数据的socket int iSock 61 socket PF INET SOCK DGRAM 0 printf 34 socket ss d n 34 iSoc
  • HTTP学习(5)--demo编写(1)

    一个基于Java的HTTP服务器demo 前面几篇博客 xff0c 大致介绍了几个方面的例子 xff0c 例如报文解析 报文组装等 现在打算将这些东西集合起来 xff0c 编写一个小HTTP服务器demo 期间遇到了很多问题 xff0c 也
  • opencv将16位灰度图片转化为8位

    大家在加载灰度图时 一定要看准图片存储格式位数 opencv默认为8位读取 如果该图为16位 则读取为全0 导致程序出错 以下代码只需修改路径 可以批量处理图片 include
  • 今天这个是mybatis与spring的整合

    今天这个是mybatis与spring的整合 依旧是一个查询的demo 首先是demo的结构 然后是我的jdbc properties jdbc driverClassName com mysql jdbc Driver jdbc url
  • Tornado websocket 演示的 Nginx 配置?

    有人可以向我提供 Tornado websocket 聊天演示的 Nginx 配置吗 该演示位于 tornado demos websocket 像这样的配置将起作用 events worker connections 1024 http
  • requirejs Angular 似乎没有注册控制器/服务/等

    我有一个非常简单的 requirejs 和 Angular 演示应用程序 当我运行代码时 就好像 Angular 没有注册 homeController 即使文件确实运行并输出 来自家庭控制器的 Hello 令人沮丧的是几乎没有关于如何解决
  • 什么是好的头像电子邮件示例?

    在 Ember js 文档中看到类似的演示后 我刚刚做了一个演示 该演示根据您的电子邮件获取您的头像 我目前正在使用 电子邮件受保护 cdn cgi l email protection作为默认值 但这似乎是错误的 因为它是一个 React
  • OpenCPU 上的自定义 R 包/找到包,但没有可见的函数

    CI 为 OpenCPU 编写了一个 R 包 并希望在我自己的云服务器上使用它 即使包本身被识别并且可以更新 我也无法访问任何功能 并且我可以通常通过 POST 和 GET 访问其他 非自定义 例如基本或统计 包 我已经安装了自定义包以及所

随机推荐

  • C++【类与对象】——友元

    文章目录 一 全局函数作友元1 友元2 code格式3 作用 二 友元类1 code格式2 作用3 拓展 三 成员函数作友元1 code格式2 作用 总结 Note i 视频为 黑马程序员C 43 43 视频 xff08 118 120 x
  • C++【类与对象】——运算符重载

    文章目录 一 运算符重载1 定义 二 加号运算符重载1 code格式 xff08 1 xff09 通过成员函数实现加号运算符重载 xff08 2 xff09 通过全局函数实现加号运算符重载 2 作用3 拓展 xff08 1 xff09 运算
  • C++【类与对象】——继承

    文章目录 一 基本语法1 code格式2 作用 二 继承方式1 图解 xff08 核心 xff09 2 总结 三 继承中的对象模型1 总结 四 构造和析构顺序1 引入2 总结 五 同名成员访问1 引入2 同名成员属性访问方式3 同名成员函数
  • 【ROS基础指令】ROS基础指令、基本知识快速查询

    ROS学习 ROS相关指令积累1 ros基础指令2 ros常用工具指令关于rviz关于rqt关于gazebo关于launch关于run关于PX4 如何自定义数据类型仿真 ROS相关指令积累 1 ros基础指令 功能指令初始化创建工作空间ca
  • 【cartographer_slam源码阅读】4-6激光雷达数据的转换

    HandleLaserScanMessage 函数 作用 xff1a 利用 ToPointCloudWithIntensities函数 将ros中的数据转换为carto中定义的数据类型 xff1b 传入 HandleLaserScan 函数
  • prometheus二次开发之HTTP api(一)

    Prometheus在 api v1的路径下开放了HTTP接口 xff0c 用户可以通过这些接口进行二次开发 这篇笔记挑选了此次监控平台可能会用到的接口进行解析 1 请求 amp 响应格式 1 JSON响应格式 以JSON格式进行响应 若A
  • prometheus二次开发之HTTP api(二)

    接以上prometheus二次开发之HTTP api xff08 一 xff09 xff1a https blog csdn net weixin 44723434 article details 104282636 最近做监控方案发现可能
  • 从 JavaScript 中的数组中删除空对象

    从数组中删除空对象 xff1a 使用 Array filter 方法遍历数组 将每个对象传递给 Object keys 方法并检查键的长度是否不等于 0 filter 方法将返回一个不包含空对象的新数组 span class token k
  • 耦合,紧耦合,松耦合,解耦

    一 耦合 耦合是两个或多个模块之间的相互关联 在软件工程中 xff0c 两个模块之间的耦合度越高 xff0c 维护成本越高 因此 xff0c 在系统架构的设计过程中 xff0c 应减少各个模块之间的耦合度 xff0c 以提高应用的可维护性
  • 实习日记之SNMPV3不难

    SNMPv3 的连接 snmpwalk v 3 u a a MD5 A Qaz1234567 x AES X Qaz1234567 l authPriv 10 0 31 132 1 3 6 1 2 1 6 前面 v 3 xff0c 意思是在
  • 一些控制算法学习

    pid LQR xff08 LQG xff09 xff0c 鲁棒控制 xff08 H无穷 xff09 xff0c 自适应控制 xff08 包含滑膜 xff0c 反步法 xff0c mrac模型参考 xff0c L1自适应 xff09 xff
  • Qt和其它GUI库的对比

    Windows 下的 GUI 库 Windows 下的 GUI 解决方案比较多 xff1a 基于 C 43 43 的有 Qt MFC WTL wxWidgets DirectUI Htmlayout xff1b 基于 C 的有 WinFor
  • stm32初学 Keil debug断点调试的步骤

    网上没搜到 xff0c 自己简单写一个 xff0c 希望对大家有用 1 在debug模式下 xff0c 将需要观察的变量选中 xff0c 右键Add to添加到 Watch 1中 原本Watch应该位置在右下角见图二 xff0c 是我拖到了
  • 关于a++和++a

    作者 xff1a Huya天涯过客 写此博文的初衷是想将自己的心得体会与Java初学者进行分享 xff0c 已在该领域纵横多年的技术大佬请自行跳过 刚学到数据类型以及变量赋值的同学们肯定会接触到自增运算符这个知识点 xff0c 绝对有很多人
  • Nuttx学习笔记(一)——Nuttx系统开发环境搭建

    最近刚开始接触Nuttx xff0c 在配置环境的时候踩了一些坑 xff0c 写下这篇博客记录一下 本人搭建开发环境的时候 xff0c 参考了官方文档和YouTube上的一个大佬的视频 xff0c 链接如下 xff1a 官方文档 http
  • Linux驱动_驱动设计的思想(面向对象、设备树)

    一 Linux驱动 驱动设计的思想 xff08 面向对象 分层 分离 xff09 总则 xff1a Linux驱动 61 驱动框架 43 硬件操作 61 驱动框架 43 单片机 1 面向对象就是用结构体表示某个对象 2 分层 3 分离 事实
  • 2惠普暗影精灵恢复出厂设置

    因为之前把电脑送去惠普售后店维修了 xff08 寻找惠普官方售后店的方法 xff1a 关注微信公众号惠普服务 xff09 xff0c 拿回来的时候系统被店里的人重装了 xff0c 不但C盘只剩下十几G的空间 xff0c 而且多了阴魂不散的3
  • Ubuntu18.04屏幕自动旋转解决方法

    Ubuntu屏幕突然自己旋转 xff0c 大概率是因为开了重力感应 xff0c 电脑倾角变动后 xff0c 屏幕跟随旋转 首先先把屏幕转回来 终端输入 xrandr span class token operator span q 查看连接
  • 傅里叶与图像特征简介

    傅里叶变换在图像处理中有着广泛的应用 xff0c 主要应用方向有 xff1a 图像增强与去噪 边缘检测 特征提取 图像压缩等 其核心思想是使用傅里叶变换将图像由空间域转换至频率域 xff0c 通过对频率域进行不同的运算操作 xff0c 实现
  • openCPU开发demo详解包括线程调度、队列等的使用

    OpenCPU开发例程的详细解释 xff0c 包括各种功能的测试 xff0c 如线程 队列等 源代码为osi demo c 初步学习 xff0c 可能有误 xff0c 仅供参考 demo详解 代码部分系统函数fibo textTrace 输