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

电子书阅读器:基于UDP的网络日志调试系统

目录

为什么要引入网络编程进行远程打印?

框架与管理

 debug层结构

stdout.c

netprint.c(重头戏)

明确两个问题:udp和server端的选择

核心机制 

实现细节 

 debug_manager.c

netprint_client.c

为什么要引入网络编程进行远程打印?

针对开发板调试中串口打印的局限性,建议采用网络日志收集方案替代传统串口输出。

  • 我们的程序是在开发板上运行,以前 printf 打印信息从串口打印出来。如果有成百上千个设备要同时去测试的话,那就要接成百上千条串口线,太麻烦了。所以说用串口线打印,一个是麻烦,另外一个是不好管理。
  • 还有串口的打印非常慢,当应用程序加入了成百上千条串口打印之后,就会导致程序运行得非常慢。
  • 发布一个程序之后,肯定会把这些打印信息去掉,就会导致调试的程序和真正发布的程序效果是不一样的,就会掩盖很多的问题。

所以我们要引入网络编程,把打印信息通过网络传输到某一台机器上,在那台机器上进行观察。

框架与管理

功能架构:

        其他函数在进行打印调试输出的时候使用DebugPrint函数,DebugPrint函数调用底层的打印结构体(封装在stdout.c和netprint.c中)。

        功能:

  1. 模块化架构:通过T_DebugOpr结构体抽象不同输出方式。
  2. 支持多输出通道管理;包括串口通道(stdout)以及网络打印(netprint)
  3. 提供动态通道开关接口(SetDebugChannel)。
  4. 对于网络打印(netprint.c),使用环形缓冲区存储日志信息,当客户端(日志)连接之后,使用网络通信传递日志信息。
  5. 实现日志分级控制(0-7级)。
  • 如果我们用stdou.c来打印的话,肯定很快,但是用netprint来打印的话还会涉及客户端和服务端,所以不会一开始马上就打印出来,所以我们要先把数据存入buffer,当客户端连接之后,再使用网络通信传输数据给客户端。
  • 关于第5点理解:我们参照内核printk的实现的功能,对每条信息实现设置和显示打印级别。

 debug层结构

在debug_manager.h中定义结构体;包含name,初始化(对网络通信的初始化),print(在debug_manager.c中先对变参形式的数据进行处理,参考printf,使用vsprintf存入到一个缓冲区中),Exit,canUsed(用于判断当前打印渠道)。

typedef struct DebugOpr{char *name;int canUsed;int (*DebugInit)(void);int (*DebugExit)(void);int (*DebugPrint)(char *strData);struct DebugOpr *ptNext;
}T_DebugOpr, *PT_DebugOpr;

stdout.c

        (无需初始化和退出,打印则直接调用printf即可)

#include <config.h>
#include <debug_manager.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>static int StdoutDebugPrint(char *strData) {/* 标准输出: 直接将输出信息用printf打印即可 */printf("%s", strData);return strlen(strData);// 返回已经成功打印的字符数
}// 分配注册一个结构体
static T_DebugOpr g_tStdoutDebugOpr = {.canUsed = 1,.name = "stdout",.DebugPrint = StdoutDebugPrint,// 对于标准输出,不需要做什么初始化和退出操作// 因此这里直接设置为空即可,当后续需要调用这两个函数的时候需要判断是否存在这两个函数// .DebugExit = StdoutDebugExit,// .DebugInit = StdoutDebugInit,
};// 注册结构体
int StdoutInit(void){return RegisterDebugOpr(&g_tStdoutDebugOpr);
}

netprint.c(重头戏)

明确两个问题:udp和server端的选择

使用udp还是tcp?

  1. 日志传输时如果使用TCP传输显然更安全并且可以保证服务端接收的顺序。如果采用UDP则不可能会出现日志块丢失的情况。但是日志块丢失一般出现在网络环境不好的情况下,如果网络环境出现问题即使使用TCP也会因为Tcp的超时重传机制,出现传输拥堵的问题,最终可能导致进程异常结束。
  2. 如果使用UDP来传输,传输效率上会很快。
  3. 在对日志完整性要求不是很高,在可靠的局域网环境下可以使用UDP。

开发版作为server端还是cllient端?

  1. 烧入开发板的程序当做 server 端,因为开发板上你可以随便执行应用程序,然后你想在哪一台机器上打印,就用那台机器登录开发板就可以了。ssh root@192.168.5.9
  2. 被动服务模式: 开发板作为Server时持续监听固定端口(如8888),客户端可随时连接获取日志。这种设计符合UDP无连接特性优势,无需维护长连接状态
  3. 资源占用优化: Server端只需初始化一次网络模块,避免了Client端频繁建立连接的开销。
  4. 单个Server可同时响应多个Client请求,便于团队协作调试
核心机制 
  1. 采用16KB环形缓冲区实现异步日志传输
  2. 双线程模型:发送线程(NetDebugSendThread)和接收线程(NetDebugRecvThread)
  3. 条件变量(pthread_cond_t)实现线程间高效同步
实现细节 

在对UDP日志服务初始化的时候        

  1. UDP Socket创建与绑定(端口号通过SERVER_PORT宏定义)
  2. 动态分配16KB打印缓冲区(PRINT_BUF_SIZE宏控制)
  3. 双线程模型建立(发送/接收线程分离)

打印函数的实现

        其他文件调用DebugPrint打印的时候会调用各个渠道的Print;首先将数据放入到环形缓冲区中;之后使用条件变量唤醒发送线程。发送线程平时处于休眠状态(客户端连接之后并且有数据进入到唤醒缓冲区中),等待唤醒。唤醒后,如果有客户端连接并且环形缓冲区中有数据,则将环形缓冲区中的数据取出来放入到发送缓冲区中,通过sendto函数向客户端发送打印数据,直到环形缓冲区中没有数据。NetDebugRecvThread用于接收来自客户端的设置与控制命令。

        为什么要使用环形缓冲区?

由于环形缓冲区的读写分开特性,当两个线程进行通信的时候,可以采用环形缓冲区进行交流,一个进程读取,一个进程写入,由于读写的位置不同,并不需要加锁进行并发控制,也就减少了锁的时间开销

        在多进行几次打印后会发现客户端不再打印信息,原因在于条件变量仅进行通知操作也要加上互斥量。

        线程的条件变量在唤醒和休眠的时候要获得互斥量:条件本身是由互斥量保护的。线程在改变条件状态之前必须要首先锁住互斥量。-------------------------------------参考APUE p332。

  • 原子性保证:pthread_cond_wait()必须与互斥量配合才能实现"解锁-等待-加锁"的原子操作
  • 互斥量保护共享状态:条件变量的等待/通知机制必须基于某个共享状态的改变,该状态需要互斥量保护
    pthread_mutex_lock(&g_tSendMutex);pthread_cond_signal(&g_tSendConVar);pthread_mutex_unlock(&g_tSendMutex);

 debug_manager.c

全局日志级别参照内核的实现,使用8个打印级别。

  1. SetDebugLevel:解析"dbglevel=X"格式命令,设置全局日志级别阈值(0-7)
  2. SetDebugChannel:处理"通道名=0/1"指令,动态启用/禁用特定输出通道。

 在main.c中首先初始化日志系统,因为后续初始化会调用日志调试系统。

netprint_client.c

基于UDP协议的网络调试客户端程。主要用于发送控制命令和接收日志信息。需要单独编译,通过开发板ip地址进行连接。

相关文章:

  • python打卡day40
  • TF 卡 U1 与 U3 的核心差异解析:从速度标准到应用场景
  • dvwa3——CSRF
  • 智能改变一切:当技术革命遇见人类文明
  • MySql(八)
  • Java本地缓存实现方案全解析:原理、优缺点与应用场景
  • 第十二篇:MySQL 分布式架构演进与云原生数据库探索
  • 针对Helsinki-NLP/opus-mt-zh-en模型进行双向互翻的微调
  • 大厂前端研发岗位设计的30道Webpack面试题及解析
  • ROS 2 中的 robot_state_publisher 和 joint_state_publisher 详解
  • comfyui 工作流中 视频长度和哪些参数有关? 生成15秒的视频,再加上RTX4060 8G显卡,尝试一下
  • AI书签管理工具开发全记录(五):后端服务搭建与API实现
  • (18)混合云架构部署
  • SpringBoot整合Flowable【08】- 前后端如何交互
  • 数据分类分级的实践与反思:源自数据分析、治理与安全交叉视角的洞察
  • AWS WebRTC:获取ICE服务地址(part 3):STUN服务和TURN服务的作用
  • 深入剖析HBase架构
  • 若依项目AI 助手代码解析
  • ImBatch 7.6.3 中文版 - 高效图片批量处理工具
  • [Javascript进阶]JSON.stringify与JSON.parse详解
  • 网站源码建站/论坛seo网站
  • 中华人民共和国城乡建设部网站官网/百度seo和谷歌seo有什么区别
  • 国外论文类网站有哪些/网络营销的基本内容有哪些
  • 网站院长信箱怎么做/网络广告策划流程有哪些?
  • 萧山做网站哪里找/360免费建站网页链接
  • wordpress 上一篇/seo论坛