我在一个NVR平台上进行编程,完成实验,任务如下:·在NVR软件平台中添加一个独立进程,可随系统自动启动. ·该进程实现ubus方法,根据传入参数触发内存泄漏及访问空指针问题·在dsd中添加接口,可用postman通过TDCP接口调用上述ubus 方法。我找到他人代码,但我是初学者,请帮我详细分析这些代码 并且教会我,包括但不限于使用注释,知识点解释,函数解释等等。一共两份代码,以。 分割。/**
* @file nvr_work.c
* @brief nvr work
*
* @author Wang Wei <wangwei14@tp-link.com.hk>
* @version 0.0.1
* @date 2024-09-04 Wed 11:45
*
*/
#include "nvr_work.h"
#include "model.h"
#include "validator.h"
#include "dsd_dbg.h"
#include "ubus_api.h"
#include "json/json.h"
#include "error.h"
#include "dsd.h"
#include <stdio.h>
#include <stdlib.h>
#define MEM_LEAK_IDX_MIN 2
LOCAL STATUS do_ubus_call(DS_HANDLE_CONTEXT *context, JSON_OBJPTR param,
const char *module_name, const char *method_name)
{
int ret = SLP_ENONE;
UBUS_CONN *conn = NULL;
UBUS_CALL_ATTR attr = {0};
if (!context || !module_name || !method_name)
{
DSD_LOG(DSD_LOG_ERROR, "Invalid params.");
ret = NVR_INTF_PARA_ERR;
goto finish;
}
conn = ubus_create_connection();
if (NULL == conn)
{
DSD_LOG(DSD_LOG_ERROR, "ubus connection error.");
ret = NVR_UBUS_CONN_ERR;
goto finish;
}
attr.module = module_name;
attr.method = method_name;
if (NULL == param)
{
attr.msg = NULL;
}
else
{
if (ERROR == jso_to_string(param, context->buffer, context->buf_len))
{
DSD_LOG(DSD_LOG_ERROR, "jso_to_string error.");
ret = EPROCESSERR;
goto finish;
}
attr.msg = context->buffer;
}
if (NULL != context->res_obj)
{
jso_free_obj(context->res_obj);
context->res_obj = NULL;
}
ret = ubus_call(conn, &attr, &(context->res_obj));
if (ret < 0)
{
DSD_LOG(DSD_LOG_ERROR, "ubus call error.");
ret = EPROCESSERR;
goto finish;
}
jso_obj_get_int(context->res_obj, "err_code", &ret);
finish:
if (NULL != conn)
{
ubus_close_connection(conn);
}
if (NULL == context->res_obj)
{
context->res_obj = jso_new_obj();
}
return ret;
}
/**
* @fn nvr_work_mem_leak_cb
* @brief 触发内存泄漏
* @param[in] context ds 上下文
* @param[in] param cb func param
* @return func status
*/
LOCAL STATUS nvr_work_mem_leak_cb(DS_HANDLE_CONTEXT *context, JSON_OBJPTR param)
{
if (NULL == context || NULL == param)
{
NVR_WORK_ERR("DS Invalid Params.\n");
return NVR_INTF_PARA_ERR;
}
if (0 != do_ubus_call(context, param, "nvr_work", "mem_leak"))
{
NVR_WORK_ERR("nvr_work_mem_leak err\n");
jso_add_string((*context).res_obj, "mem_leak", "ERR");
return ERROR;
}
jso_add_string((*context).res_obj, "mem_leak", "OK");
jso_obj_add((*context).res_obj, "param", param);
return OK;
}
/**
* @fn nvr_work_null_ptr_cb
* @brief 访问空指针
* @param[in] context ds 上下文
* @param[in] param cb func param
* @return func status
*/
LOCAL STATUS nvr_work_null_ptr_cb(DS_HANDLE_CONTEXT *context, JSON_OBJPTR param)
{
if (NULL == context || NULL == param)
{
NVR_WORK_ERR("DS Invalid Params.\n");
return NVR_INTF_PARA_ERR;
}
if (0 != do_ubus_call(context, param, "nvr_work", "null_ptr"))
{
NVR_WORK_ERR("nvr_work_mem_leak err\n");
jso_add_string((*context).res_obj, "null_ptr", "ERR");
return ERROR;
}
jso_add_string((*context).res_obj, "null_ptr", "OK");
jso_obj_add((*context).res_obj, "param", param);
return OK;
}
SERVICE nvr_work_service[] =
{
{
.keyword = "mem_leak",
.keyword_action = nvr_work_mem_leak_cb,
},
{
.keyword = "null_ptr",
.keyword_action = nvr_work_null_ptr_cb,
},
};
DS_MODULE nvr_work_module =
{
.name = "nvr_work",
.config_file = NULL,
.section_name = NULL,
.section_type = NULL,
.service = nvr_work_service,
.permission = PERMIT_MASKS(PERMIT_RW, PERMIT_RW, 0),
};
/**
* @fn nvr_work_register
* @brief nvr_work 模块注册
*/
STATUS nvr_work_register()
{
return add_module_node(&nvr_work_module);
}
。/**
* @file nvr_work_ubus.c
* @brief nvr work ubus
*
* @author Wang Wei <wangwei14@tp-link.com.hk>
* @version 0.0.1
* @date 2024-09-05 Thu 11:00
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <libubus.h>
#include <json/json.h>
#include <libubox/uloop.h>
#include <sys/resource.h>
#include "tp_type.h"
#include "nvr_work_ubus.h"
#ifdef FTRACE_EN
#include "trace_tool.h"
#include "backtrace.h"
#else
#include <sys/resource.h>
#endif
LOCAL struct ubus_context *nvr_work_context = NULL;
LOCAL const char *wm_path = NULL;
#define MEM_LEAK_TIMES 5
enum
{
TEST_SET_NUM,
TEST_SET_NUM_MAX,
};
LOCAL const struct blobmsg_policy mem_leak_policy[TEST_SET_NUM_MAX] =
{
[TEST_SET_NUM] = {.name = "num", .type = BLOBMSG_TYPE_INT32},
};
/**
* @fn ubus_nvr_work_mem_leak_cb
* @brief nvr work mem lead ubus cb
* @note 在该函数中进行内存泄漏
* @param[in] context ubus context
* @param[in] obj ubus obj
* @param[in] req ubus request
* @param[in] method ubus call method
* @param[in] msg ubus msg
* @return func status
*/
LOCAL STATUS ubus_nvr_work_mem_leak_cb(struct ubus_context *context,
struct ubus_object *obj,
struct ubus_request_data *req,
const char *method,
struct blob_attr *msg)
{
int i = 0;
for (i = 0; i < MEM_LEAK_TIMES; ++i)
{
int *ptr = (int *)malloc(sizeof(int));
memset(ptr, 0, sizeof(int));
}
NVR_WORK_INFO("nvr_work mem_leak\n");
return OK;
}
LOCAL const struct blobmsg_policy null_ptr_policy[TEST_SET_NUM_MAX] =
{
[TEST_SET_NUM] = {.name = "num", .type = BLOBMSG_TYPE_INT32},
};
/**
* @fn ubus_nvr_work_null_ptr_cb
* @brief nvr work mem lead ubus cb
* @note 在该函数中进行空指针访问
* @param[in] context ubus context
* @param[in] obj ubus obj
* @param[in] req ubus request
* @param[in] method ubus call method
* @param[in] msg ubus msg
* @return func status
*/
LOCAL STATUS ubus_nvr_work_null_ptr_cb(struct ubus_context *context,
struct ubus_object *obj,
struct ubus_request_data *req,
const char *method,
struct blob_attr *msg)
{
NVR_WORK_INFO("nvr_work null_ptr\n");
int *ptr = NULL;
printf("%d\n", (*ptr));
return OK;
}
LOCAL const struct blobmsg_policy trace_alloc_policy[TEST_SET_NUM_MAX] = {};
extern void trace_alloc_debug();
/**
* @fn ubus_nvr_work_trace_alloc_cb
* @brief nvr work trace alloc ubus cb
* @note 在该函数中进行内存检测
* @param[in] context ubus context
* @param[in] obj ubus obj
* @param[in] req ubus request
* @param[in] method ubus call method
* @param[in] msg ubus msg
* @return func status
*/
LOCAL STATUS ubus_nvr_work_trace_alloc_cb(struct ubus_context *context,
struct ubus_object *obj,
struct ubus_request_data *req,
const char *method,
struct blob_attr *msg)
{
trace_alloc_debug();
NVR_WORK_INFO("nvr_work trace_alloc\n");
return OK;
}
/* ubus method */
LOCAL struct ubus_method nvr_work_ubus_methods[] =
{
UBUS_METHOD("mem_leak", ubus_nvr_work_mem_leak_cb, mem_leak_policy),
UBUS_METHOD("null_ptr", ubus_nvr_work_null_ptr_cb, null_ptr_policy),
UBUS_METHOD("trace_alloc", ubus_nvr_work_trace_alloc_cb, trace_alloc_policy),
};
/* usub obj type */
LOCAL struct ubus_object_type nvr_work_ubus_get_obj_type =
UBUS_OBJECT_TYPE("nvr_work", nvr_work_ubus_methods);
/* ubus obj */
LOCAL struct ubus_object nvr_work_ubus_obj =
{
.name = "nvr_work",
.type = &nvr_work_ubus_get_obj_type,
.methods = nvr_work_ubus_methods,
.n_methods = ARRAY_SIZE(nvr_work_ubus_methods),
};
LOCAL void nvr_work_ubus_add_fd()
{
ubus_add_uloop(nvr_work_context);
}
LOCAL void nvr_work_ubus_reconnect_timer(struct uloop_timeout *timeout)
{
LOCAL struct uloop_timeout retry =
{
.cb = nvr_work_ubus_reconnect_timer,
};
int32_t t = 2;
if (ubus_reconnect(nvr_work_context, wm_path) != 0)
{
uloop_timeout_set(&retry, t * 1000);
return;
}
nvr_work_ubus_add_fd();
}
LOCAL void nvr_work_ubus_connection_lost(struct ubus_context *context)
{
nvr_work_ubus_reconnect_timer(NULL);
}
STATUS nvr_work_ubus_init(const char *path)
{
uloop_init();
wm_path = path;
nvr_work_context = ubus_connect(UBUS_UNIX_SOCKET);
if (NULL == nvr_work_context)
{
printf("nvr_work ubus connect failed!\n");
return ERROR;
}
printf("nvr_work connected as %08x\n", nvr_work_context->local_id);
nvr_work_context->connection_lost = nvr_work_ubus_connection_lost;
nvr_work_ubus_add_fd();
if (ubus_add_object(nvr_work_context, &nvr_work_ubus_obj) != 0)
{
printf("nvr_work ubus add obj failed\n");
return ERROR;
}
return OK;
}
void nvr_work_ubus_done()
{
if (NULL != nvr_work_context)
{
ubus_free(nvr_work_context);
}
uloop_done();
}
int main(int argc, char *argv[])
{
char *path = NULL;
if (ERROR == nvr_work_ubus_init(path))
{
printf("nvr_work ubus init failed!\n");
return ERROR;
}
uloop_set_uloop_fd_ptr(&(nvr_work_context->sock));
uloop_run();
nvr_work_ubus_done();
return 0;
}