How to use CCS to debug a running M4F core that was started by Linux?

news2025/1/23 11:25:54

参考FAQ:AM62x & AM64x: How to use CCS to debug a running M4F core that was started by Linux?

问题记录:

1.使用SD卡启动模式,板上运行Linux。
当Linux系统启动后,9表示M4F core:

am64xx-evm login: root
root@am64xx-evm:~# rpmsg_char_simple -r 9 -n 3
Created endpt device rpmsg-char-9-1035, fd = 3 port = 1024
Exchanging 3 messages with rpmsg device ti.ipc4.ping-pong on rproc id 9 ...

Sending message #0: hello there 0!
Receiving message #0: hello there 0!
Sending message #1: hello there 1!
Receiving message #1: hello there 1!
Sending message #2: hello there 2!
Receiving message #2: hello there 2!

Communicated 3 messages successfully on rpmsg-char-9-1035

TEST STATUS: PASSED

下面的输出怀疑存在问题:

root@am64xx-evm:~# rpmsg_char_simple -r 2 -n 3
Created endpt device rpmsg-char-2-1042, fd = 3 port = 1024
Exchanging 3 messages with rpmsg device ti.ipc4.ping-pong on rproc id 2 ...

Sending message #0: hello there 0!
Receiving message #0:
Sending message #1: hello there 1!
Receiving message #1:
Sending message #2: hello there 2!
Receiving message #2:

Communicated 3 messages successfully on rpmsg-char-2-1042

TEST STATUS: PASSED

接下来在CCS端进行Debug,选择hello_world_am64x-evm_m4fss0-0_nortos_ti-arm-clang例程
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
运行后卡在0xfd38
结束调试后在Linux终端执行:仍然能正确输出

root@am64xx-evm:~# rpmsg_char_simple -r 9 -n 3
Created endpt device rpmsg-char-9-1573, fd = 3 port = 1024
Exchanging 3 messages with rpmsg device ti.ipc4.ping-pong on rproc id 9 ...

Sending message #0: hello there 0!
Receiving message #0: hello there 0!
Sending message #1: hello there 1!
Receiving message #1: hello there 1!
Sending message #2: hello there 2!
Receiving message #2: hello there 2!

Communicated 3 messages successfully on rpmsg-char-9-1573

TEST STATUS: PASSED

接下来采用Load Program的方式:可以正确加载程序并输出
在这里插入图片描述
但是在Linux终端执行,程序会卡死

root@am64xx-evm:~# rpmsg_char_simple -r 9 -n 3
Created endpt device rpmsg-char-9-1720, fd = 3 port = 1024
Exchanging 3 messages with rpmsg device ti.ipc4.ping-pong on rproc id 9 ...

Sending message #0: hello there 0!


在这里插入图片描述

正确做法:

  1. 在CCS中构建remote core project(ipc_rpmsg_echo_linux_am64x-evm_m4fss0-0_freertos_ti-arm-clang)

  2. 将生成的.out文件拷贝到Linux filesystem下的/lib/firmware,并更新links。

    root@am64xx-evm:~# head /sys/class/remoteproc/remoteproc*/name
    ==> /sys/class/remoteproc/remoteproc0/name <==5000000.m4fss  //可以确定M4F的remoteproc是0
    ...
    root@am64xx-evm:~# echo stop > /sys/class/remoteproc/remoteproc0/state
    [  263.325676] remoteproc remoteproc0: stopped remote processor 5000000.m4fss
    
    root@am64xx-evm:/lib/firmware# ln -sf /lib/firmware/ipc_rpmsg_echo_linux_am64x-evm_m4fss0-0_freertos_ti-arm-clang.out am64-mcu-m4f0_0-fw
    
    root@am64xx-evm:/lib/firmware# ls -l /lib/firmware/
    total 32452
    
    lrwxrwxrwx 1 root root      79 Dec 14 12:22 am64-mcu-m4f0_0-fw -> /lib/firmware/ipc_rpmsg_echo_linux_am64x-		evm_m4fss0-0_freertos_ti-arm-clang.out
    
    
    
  3. 重启EVM,并测试RPMsg example is running properly

    root@am64xx-evm:~# rpmsg_char_simple -r 9 -n 3
    Created endpt device rpmsg-char-9-1034, fd = 3 port = 1024
    Exchanging 3 messages with rpmsg device ti.ipc4.ping-pong on rproc id 9 ...
    
    Sending message #0: hello there 0!
    Receiving message #0: hello there 0!
    Sending message #1: hello there 1!
    Receiving message #1: hello there 1!
    Sending message #2: hello there 2!
    Receiving message #2: hello there 2!
    
    Communicated 3 messages successfully on rpmsg-char-9-1034
    
    TEST STATUS: PASSED
    
    
  4. 启动AM64 Target Configuration. Connect to the core BLAZAR_Cortex_M4F_0, Load Symbols
    在这里插入图片描述
    在这里打断点,并启动程序:
    在这里插入图片描述
    并在linux端启动:
    在这里插入图片描述
    在CCS里单步运行可以看到,Linux同步输出
    在这里插入图片描述
    代码解析:
    main.c

#include <stdlib.h>
#include <kernel/dpl/DebugP.h>
#include "ti_drivers_config.h"
#include "ti_board_config.h"
#include "FreeRTOS.h"
#include "task.h"

#define MAIN_TASK_PRI  (configMAX_PRIORITIES-1)//代表最高优先级

#define MAIN_TASK_SIZE (16384U/sizeof(configSTACK_DEPTH_TYPE))//4096
StackType_t gMainTaskStack[MAIN_TASK_SIZE] __attribute__((aligned(32)));

StaticTask_t gMainTaskObj;
TaskHandle_t gMainTask;

void ipc_rpmsg_echo_main(void *args);

void freertos_main(void *args)
{
    ipc_rpmsg_echo_main(NULL);

    vTaskDelete(NULL);
}


int main(void)
{
    /* init SOC specific modules */
    System_init();
    Board_init();

    /* This task is created at highest priority, it should create more tasks and then delete itself */
    gMainTask = xTaskCreateStatic( freertos_main,   /* Pointer to the function that implements the task. */
                                  "freertos_main", /* Text name for the task.  This is to facilitate debugging only. */
                                  MAIN_TASK_SIZE,  /* Stack depth in units of StackType_t typically uint32_t on 32b CPUs */
                                  NULL,            /* We are not using the task parameter. */
                                  MAIN_TASK_PRI,   /* task priority, 0 is lowest priority, configMAX_PRIORITIES-1 is highest */
                                  gMainTaskStack,  /* pointer to stack base */
                                  &gMainTaskObj ); /* pointer to statically allocated task object memory */
    configASSERT(gMainTask != NULL);

    /* Start the scheduler to start the tasks executing. */
    vTaskStartScheduler();

    /* The following line should never be reached because vTaskStartScheduler()
    will only return if there was not enough FreeRTOS heap memory available to
    create the Idle and (if configured) Timer tasks.  Heap management, and
    techniques for trapping heap exhaustion, are described in the book text. */
    DebugP_assertNoLog(0);

    return 0;
}

ipc_rpmsg_echo.c

#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <kernel/dpl/ClockP.h>
#include <kernel/dpl/DebugP.h>
#include <kernel/dpl/TaskP.h>
#include <drivers/ipc_notify.h>
#include <drivers/ipc_rpmsg.h>
#include "ti_drivers_open_close.h"
#include "ti_board_open_close.h"

/* This example shows message exchange bewteen Linux and RTOS/NORTOS cores.
 * This example also does message exchange between the RTOS/NORTOS cores themselves
 *
 * The Linux core initiates IPC with other core's by sending it a message.
 * The other cores echo the same message to the Linux core.
 *
 * At the same time all RTOS/NORTOS cores, also send messages to each others
 * and reply back to each other. i.e all CPUs send and recevive messages from each other
 *
 * This example can very well have been NORTOS based, however for convinience
 * of creating two tasks to talk to two clients on linux side, we use FreeRTOS
 * for the same.
 */

/*
 * Remote core service end point
 *
 * pick any unique value on that core between 0..RPMESSAGE_MAX_LOCAL_ENDPT-1
 * the value need not be unique across cores
 *
 * The service names MUST match what linux is expecting
 */
/* This is used to run the echo test with linux kernel */
#define IPC_RPMESSAGE_SERVICE_PING        "ti.ipc4.ping-pong"
#define IPC_RPMESSAGE_ENDPT_PING          (13U)

/* This is used to run the echo test with user space kernel */
#define IPC_RPMESSAGE_SERVICE_CHRDEV      "rpmsg_chrdev"
#define IPC_RPMESSAGE_ENDPT_CHRDEV_PING   (14U)

/* Use by this to receive ACK messages that it sends to other RTOS cores */
#define IPC_RPMESSAGE_RNDPT_ACK_REPLY     (11U)

/* maximum size that message can have in this example */
#define IPC_RPMESSAGE_MAX_MSG_SIZE        (96u)

/*
 * Number of RP Message ping "servers" we will start,
 * - one for ping messages for linux kernel "sample ping" client
 * - and another for ping messages from linux "user space" client using "rpmsg char"
 */
#define IPC_RPMESSAGE_NUM_RECV_TASKS         (2u)

/* RPMessage object used to recvice messages */
RPMessage_Object gIpcRecvMsgObject[IPC_RPMESSAGE_NUM_RECV_TASKS];

/* RPMessage object used to send messages to other non-Linux remote cores */
RPMessage_Object gIpcAckReplyMsgObject;

/* Task priority, stack, stack size and task objects, these MUST be global's */
#define IPC_RPMESSAFE_TASK_PRI         (8U)
#define IPC_RPMESSAFE_TASK_STACK_SIZE  (8*1024U)
uint8_t gIpcTaskStack[IPC_RPMESSAGE_NUM_RECV_TASKS][IPC_RPMESSAFE_TASK_STACK_SIZE] __attribute__((aligned(32)));
TaskP_Object gIpcTask[IPC_RPMESSAGE_NUM_RECV_TASKS];

/* number of iterations of message exchange to do */
uint32_t gMsgEchoCount = 100000u;
/* non-Linux cores that exchange messages among each other */
#if defined (SOC_AM64X)
uint32_t gRemoteCoreId[] = {
    CSL_CORE_ID_R5FSS0_0,
    CSL_CORE_ID_R5FSS0_1,
    CSL_CORE_ID_R5FSS1_0,
    CSL_CORE_ID_R5FSS1_1,
    CSL_CORE_ID_M4FSS0_0,
    CSL_CORE_ID_MAX /* this value indicates the end of the array */
};
#endif

#if defined (SOC_AM62X)
uint32_t gRemoteCoreId[] = {
    CSL_CORE_ID_M4FSS0_0,
    CSL_CORE_ID_MAX /* this value indicates the end of the array */
};
#endif

void ipc_recv_task_main(void *args)
{
    int32_t status;
    char recvMsg[IPC_RPMESSAGE_MAX_MSG_SIZE+1]; /* +1 for NULL char in worst case */
    uint16_t recvMsgSize, remoteCoreId, remoteCoreEndPt;
    RPMessage_Object *pRpmsgObj = (RPMessage_Object *)args;

    DebugP_log("[IPC RPMSG ECHO] Remote Core waiting for messages at end point %d ... !!!\r\n",
        RPMessage_getLocalEndPt(pRpmsgObj)
        );

    /* wait for messages forever in a loop */
    while(1)
    {
        /* set 'recvMsgSize' to size of recv buffer,
        * after return `recvMsgSize` contains actual size of valid data in recv buffer
        */
        recvMsgSize = IPC_RPMESSAGE_MAX_MSG_SIZE;
        status = RPMessage_recv(pRpmsgObj,
            recvMsg, &recvMsgSize,
            &remoteCoreId, &remoteCoreEndPt,
            SystemP_WAIT_FOREVER);
        DebugP_assert(status==SystemP_SUCCESS);

        /* echo the same message string as reply */
        #if 0 /* not logging this so that this does not add to the latency of message exchange */
        recvMsg[recvMsgSize] = 0; /* add a NULL char at the end of message */
        DebugP_log("%s\r\n", recvMsg);
        #endif

        /* send ack to sender CPU at the sender end point */
        status = RPMessage_send(
            recvMsg, recvMsgSize,
            remoteCoreId, remoteCoreEndPt,
            RPMessage_getLocalEndPt(pRpmsgObj),
            SystemP_WAIT_FOREVER);
        DebugP_assert(status==SystemP_SUCCESS);
    }
    /* This loop will never exit */
}

void ipc_rpmsg_send_messages(void)
{
    RPMessage_CreateParams createParams;
    uint32_t msg, i, numRemoteCores;
    uint64_t curTime;
    char msgBuf[IPC_RPMESSAGE_MAX_MSG_SIZE];
    int32_t status;
    uint16_t remoteCoreId, remoteCoreEndPt, msgSize;

    RPMessage_CreateParams_init(&createParams);
    createParams.localEndPt = IPC_RPMESSAGE_RNDPT_ACK_REPLY;
    status = RPMessage_construct(&gIpcAckReplyMsgObject, &createParams);
    DebugP_assert(status==SystemP_SUCCESS);

    numRemoteCores = 0;
    for(i=0; gRemoteCoreId[i]!=CSL_CORE_ID_MAX; i++)
    {
        if(gRemoteCoreId[i] != IpcNotify_getSelfCoreId()) /* dont count self */
        {
            numRemoteCores++;
        }
    }

    DebugP_log("[IPC RPMSG ECHO] Message exchange started with RTOS cores !!!\r\n");

    curTime = ClockP_getTimeUsec();

    for(msg=0; msg<gMsgEchoCount; msg++)
    {
        snprintf(msgBuf, IPC_RPMESSAGE_MAX_MSG_SIZE-1, "%d", msg);
        msgBuf[IPC_RPMESSAGE_MAX_MSG_SIZE-1] = 0;
        msgSize = strlen(msgBuf) + 1; /* count the terminating char as well */

        /* send the same messages to all cores */
        for(i=0; gRemoteCoreId[i]!=CSL_CORE_ID_MAX; i++ )
        {
            if(gRemoteCoreId[i] != IpcNotify_getSelfCoreId()) /* dont send message to self */
            {
                status = RPMessage_send(
                    msgBuf, msgSize,
                    gRemoteCoreId[i], IPC_RPMESSAGE_ENDPT_CHRDEV_PING,
                    RPMessage_getLocalEndPt(&gIpcAckReplyMsgObject),
                    SystemP_WAIT_FOREVER);
                DebugP_assert(status==SystemP_SUCCESS);
            }
        }
        /* wait for response from all cores */
        for(i=0; gRemoteCoreId[i]!=CSL_CORE_ID_MAX; i++ )
        {
            if(gRemoteCoreId[i] != IpcNotify_getSelfCoreId()) /* dont send message to self */
            {
                /* set 'msgSize' to size of recv buffer,
                * after return `msgSize` contains actual size of valid data in recv buffer
                */
                msgSize = sizeof(msgBuf);
                status = RPMessage_recv(&gIpcAckReplyMsgObject,
                    msgBuf, &msgSize,
                    &remoteCoreId, &remoteCoreEndPt,
                    SystemP_WAIT_FOREVER);
                DebugP_assert(status==SystemP_SUCCESS);
            }
        }
    }

    curTime = ClockP_getTimeUsec() - curTime;

    DebugP_log("[IPC RPMSG ECHO] All echoed messages received by main core from %d remote cores !!!\r\n", numRemoteCores);
    DebugP_log("[IPC RPMSG ECHO] Messages sent to each core = %d \r\n", gMsgEchoCount);
    DebugP_log("[IPC RPMSG ECHO] Number of remote cores = %d \r\n", numRemoteCores);
    DebugP_log("[IPC RPMSG ECHO] Total execution time = %" PRId64 " usecs\r\n", curTime);
    DebugP_log("[IPC RPMSG ECHO] One way message latency = %" PRId32 " nsec\r\n",
        (uint32_t)(curTime*1000u/(gMsgEchoCount*numRemoteCores*2)));

    RPMessage_destruct(&gIpcAckReplyMsgObject);
}

void ipc_rpmsg_create_recv_tasks(void)
{
    int32_t status;
    RPMessage_CreateParams createParams;
    TaskP_Params taskParams;

    RPMessage_CreateParams_init(&createParams);
    createParams.localEndPt = IPC_RPMESSAGE_ENDPT_PING;
    status = RPMessage_construct(&gIpcRecvMsgObject[0], &createParams);
    DebugP_assert(status==SystemP_SUCCESS);

    RPMessage_CreateParams_init(&createParams);
    createParams.localEndPt = IPC_RPMESSAGE_ENDPT_CHRDEV_PING;
    status = RPMessage_construct(&gIpcRecvMsgObject[1], &createParams);
    DebugP_assert(status==SystemP_SUCCESS);

    /* We need to "announce" to Linux client else Linux does not know a service exists on this CPU
     * This is not mandatory to do for RTOS clients
     */
    status = RPMessage_announce(CSL_CORE_ID_A53SS0_0, IPC_RPMESSAGE_ENDPT_PING, IPC_RPMESSAGE_SERVICE_PING);
    DebugP_assert(status==SystemP_SUCCESS);

    status = RPMessage_announce(CSL_CORE_ID_A53SS0_0, IPC_RPMESSAGE_ENDPT_CHRDEV_PING, IPC_RPMESSAGE_SERVICE_CHRDEV);
    DebugP_assert(status==SystemP_SUCCESS);

    /* Create the tasks which will handle the ping service */
    TaskP_Params_init(&taskParams);
    taskParams.name = "RPMESSAGE_PING";
    taskParams.stackSize = IPC_RPMESSAFE_TASK_STACK_SIZE;
    taskParams.stack = gIpcTaskStack[0];
    taskParams.priority = IPC_RPMESSAFE_TASK_PRI;
    /* we use the same task function for echo but pass the appropiate rpmsg handle to it, to echo messages */
    taskParams.args = &gIpcRecvMsgObject[0];
    taskParams.taskMain = ipc_recv_task_main;

    status = TaskP_construct(&gIpcTask[0], &taskParams);
    DebugP_assert(status == SystemP_SUCCESS);

    TaskP_Params_init(&taskParams);
    taskParams.name = "RPMESSAGE_CHAR_PING";
    taskParams.stackSize = IPC_RPMESSAFE_TASK_STACK_SIZE;
    taskParams.stack = gIpcTaskStack[1];
    taskParams.priority = IPC_RPMESSAFE_TASK_PRI;
    /* we use the same task function for echo but pass the appropiate rpmsg handle to it, to echo messages */
    taskParams.args = &gIpcRecvMsgObject[1];
    taskParams.taskMain = ipc_recv_task_main;

    status = TaskP_construct(&gIpcTask[1], &taskParams);
    DebugP_assert(status == SystemP_SUCCESS);
}

void ipc_rpmsg_echo_main(void *args)
{
    int32_t status;

    Drivers_open();
    Board_driversOpen();

    DebugP_log("[IPC RPMSG ECHO] %s %s\r\n", __DATE__, __TIME__);

    /* This API MUST be called by applications when its ready to talk to Linux */
    status = RPMessage_waitForLinuxReady(SystemP_WAIT_FOREVER);
    DebugP_assert(status==SystemP_SUCCESS);



    /* create message receive tasks, these tasks always run and never exit */
    ipc_rpmsg_create_recv_tasks();

    /* wait for all non-Linux cores to be ready, this ensure that when we send messages below
     * they wont be lost due to rpmsg end point not created at remote core
     */
    IpcNotify_syncAll(SystemP_WAIT_FOREVER);

    /* Due to below "if" condition only one non-Linux core sends messages to all other non-Linux Cores
     * This is done mainly to show deterministic latency measurement
     */
    if( IpcNotify_getSelfCoreId() == CSL_CORE_ID_R5FSS0_0 )
    {
        ipc_rpmsg_send_messages();
    }
    /* exit from this task, vTaskDelete() is called outside this function, so simply return */

    Board_driversClose();
    /* We dont close drivers since threads are running in background */
    /* Drivers_close(); */
}

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

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

相关文章

Maven 打包跳过测试的 5 种方法

平时开发时的工作的话之主要负责写代码就行了&#xff0c;什么发布项目啊&#xff0c;好吧不是我们干的事。在我们的了解中打包发布项目应该不是一个困难的问题。 对&#xff0c;最简单的方法就行使用直接使用maven插件打包&#xff0c;甚至我们都不需要知道他是怎么实现的&am…

搞懂 API :Mock 常见问题及解决办法

API Mock是一个构建Web服务质量保证环节的非常实用的工具。它可以让开发者在独立工作或集成测试时&#xff0c;快速开始调试和验证他们的代码。但是&#xff0c;在实践中&#xff0c;API Mock也可能会出现一些问题。 本文将讨论API Mock中的一些常见问题&#xff0c;并提供一些…

MyBatis(十四)MyBatis的缓存

前言 1、缓存&#xff1a;cache 2、缓存的作用&#xff1a; 通过减少IO&#xff08;读写&#xff09;的方式&#xff0c;来提高程序的执行效率。 3、mybatis的缓存&#xff1a; 将select语句的查询结果放到缓存&#xff08;内存&#xff09;当中&#xff0c;下一次还是这条…

Python爬虫之Js逆向案例(1)-京东商品评论数据商品详情数据案例

<center>声明&#xff1a;京东商品评论数据&商品详情获取分析仅用于研究和学习&#xff0c;如有侵权&#xff0c;可删除</center> 一次运行程序&#xff0c;同时获取一下内容&#xff1a; 1. 获取整站实时商品详情数据&#xff1b; 2. 获取整站实时商品评论数…

【数据结构】顺序表的增删查改操作

上一篇文章为大家介绍了对顺序表的简单的使用&#xff0c;【数据结构】顺序表详解_王笃笃的博客-CSDN博客 本篇文章继续完善对顺序表增删查改的操作。 上一篇写到了顺序表的尾部插入&#xff0c;本篇将从头部插入继续完善&#xff1b; 以下为本篇目录&#xff0c;方便阅读 …

Axios请求(对于ajax的二次封装)——Axios拦截器与错误处理

Axios请求&#xff08;对于ajax的二次封装&#xff09;——Axios拦截器与错误处理 知识回调&#xff08;不懂就看这儿&#xff01;&#xff09;场景复现核心干货axios拦截器在请求或响应被处理之前拦截他们移除拦截器给自定义的axios实例添加拦截器实际开发中的自定义拦截器&am…

C++ | 探究拷贝对象时的一些编译器优化

&#x1f451;作者主页&#xff1a;烽起黎明 &#x1f3e0;学习社区&#xff1a;烈火神盾 &#x1f517;专栏链接&#xff1a;C 文章目录 前言一、传值传参二、传引用传参三、传值返回拷贝构造和赋值重载的辨析 四、传引用返回【❌】五、传匿名对象返回六、总计与提炼 前言 在传…

网友感到担忧!iOS 17支持第三方应用商店:这下跟安卓没区别了

苹果此前官宣将于6月6日召开WWDC2023大会&#xff0c;按照往年的惯例&#xff0c;在这次大会上将会推出下一代iOS系统&#xff0c;也就是iOS 17。最近国外有关iOS 17的爆料中提到&#xff0c;迫于欧盟法案压力&#xff0c;iOS 17或将支持第三方应用商店。 2022年3月份&#xff…

springboot+vue社区维修平台(源码+文档)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的社区维修平台。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 目前有各类成品java毕设&#xff0c;需要请看文末联…

Chapter11-最常用的消费类

11.1 整体流程 我们使用 DefaultMQPushConsumer 的时候&#xff0c;一般流程是设置好 GroupName 、NameServer 地址 &#xff0c;以及订阅的 Topic 名称&#xff0c; 然后填充Message 处理函数&#xff0c;最后调用 start &#xff08;&#xff09; 。 11.1.1 上层接口类 Defau…

Qt Quick - SplitView

Qt Quick - SplitView使用总结 一、概述二、属性介绍三、简单使用四、序列化SplitView的状态五、定制化 一、概述 SplitView是一个水平或垂直布局元素的控件&#xff0c;每个元素之间有一个可拖动的分配页面内容的滑块。很像IDE里面的那些窗口。就像下面的简单的布局内容一样。…

调度系统: Quartz

最近在做数据中台架构设计&#xff0c;整体架构设计完后发现数据中台最重要的就是元数据和调度系统。元数据设计参考了atlas、metcat、datahus&#xff0c;模型设计、数据架构、技术架构基本完成。现在设计调度系统&#xff0c;才发现调度系统不像别的系统&#xff0c;主要是理…

缓存与数据库双写一致性几种策略分析

作者&#xff1a;京东零售 于泷 一、背景 在高并发场景中&#xff0c;为防止大量请求直接访问数据库&#xff0c;缓解数据库压力&#xff0c;常用的方式一般会增加缓存层起到缓冲作用&#xff0c;减少数据库压力。引入缓存&#xff0c;就会涉及到缓存与数据库中数据如何保持一…

春天到了,讲讲Spring的工作原理

一、春天到了&#xff0c;讲讲Spring的工作原理 在致力于优质IT知识出版分享的异步社区&#xff0c;有这么一本书——两版累计销售了近10w本&#xff0c;它可是完完全全靠着自己过硬的内容实力打出的这片天&#xff01; 第二版已出版4年&#xff0c;基于Spring 5.x编写&#x…

PostGre数据库操作

菜鸟教程 PostgreSQL 教程 | 菜鸟教程PostgreSQL 教程 PostgreSQL 是一个免费的对象-关系数据库服务器(ORDBMS)&#xff0c;在灵活的BSD许可证下发行。 PostgreSQL 开发者把它念作 post-gress-Q-L。 PostgreSQL 的 Slogan 是 “世界上最先进的开源关系型数据库”。 参考内容&a…

新库上线 | CnOpenData中国汽车能源消耗量数据

中国汽车能源消耗量数据 一、数据简介 工业和信息化部组织制定的《乘用车燃料消耗量限值》强制性国家标准&#xff08;GB19578-2021&#xff09;于2021年7月1日起正式实施&#xff0c;该标准规定了燃用汽油或柴油燃料、最大设计总质量不超过3500kg的M1类车辆在今后一段时期的燃…

如何开启tiktok之旅

关于tiktok的用户规模&#xff0c;相比国内抖音而言的机会这里就不再多说了&#xff0c;我之所以研究tiktok&#xff0c;是因为有不少客户咨询了我们tiktok加速方案&#xff0c;我们自身是一家纯网络公司&#xff0c;只提供tiktok加速方案而已&#xff0c;但是遭不住需求量大。…

【设计模式】Java 的三种代理模式

文章目录 一、前言二、正文1、静态代理2、动态代理3、Cglib代理Spring中AOP使用代理 三、总结 一、前言 代理(Proxy)模式是一种结构型设计模式&#xff0c;提供了对目标对象另外的访问方式&#xff1b;即通过代理对象访问目标对象。 这样做的好处是&#xff1a;可以在目标对…

什么是转化率优化(CRO)?网站转化率不高,可以看看这篇文章

你是否将人们带到你的网站&#xff0c;但只是让他们中的一小部分人完成了该页面的目标&#xff1f;你可以每天有成千上万的网站访问者到达。但如果你的网站没有设置成鼓励转换&#xff0c;你就不会说服网站访问者去做。这使得他们的整个访问几乎毫无价值&#xff0c;特别是如果…

MySQL-中间件mycat(三)

目录 &#x1f341;高可用方案 &#x1f341;安装配置 HAProxy &#x1f342;安装 HAProxy &#x1f342;启动验证 &#x1f341;配置 Keepalived &#x1f342;安装 Keepalived &#x1f342;修改配置文件 &#x1f342;启动验证 &#x1f342;测试高可用 &#x1f341;mycat …