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

article/2025/7/23 19:07:35

目录

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

框架与管理

 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地址进行连接。


http://www.hkcw.cn/article/oiydyTeoFI.shtml

相关文章

《HelloGitHub》第 110 期

兴趣是最好的老师&#xff0c;HelloGitHub 让你对开源感兴趣&#xff01; 简介 HelloGitHub 分享 GitHub 上有趣、入门级的开源项目。 github.com/521xueweihan/HelloGitHub 这里有实战项目、入门教程、黑科技、开源书籍、大厂开源项目等&#xff0c;涵盖多种编程语言 Python、…

⼤模型驱动的DeepInsight Copilot在蚂蚁的技术实践

本文整理自潘兰天&#xff08;蚂蚁数据智能团队数据分析平台技术专家)在DA数智大会2025上海站的演讲实录。 本文围绕AI技术在数据分析领域的应用及DeepInsight Copilot产品展开。DeepInsight是一款蚂蚁长期深耕数据分析领域的BI产品&#xff0c;本文首先介绍了DeepInsight Copi…

小黑大语言模型应用探索:langchain智能体构造源码demo搭建1(初步流程)

导入工具包 rom langchain_core.tools import BaseTool from typing import Sequence, Optional, List from langchain_core.prompts import BasePromptTemplate import re from langchain_core.tools import tool from langchain_core.prompts.chat import (ChatPromptTempla…

在大型中实施访问控制 语言模型

大家读完觉得有帮助记得关注&#xff01;&#xff01;&#xff01; 抽象 在企业设置中&#xff0c;组织数据是隔离的、孤立的 并受到精心设计的访问控制框架的精心保护。 如果 LLM 对 siloed data serve 请求进行微调&#xff0c;用于下游任务&#xff0c; 来自具有不同访问权限…

边缘计算网关在管网压力远程调控中的通信协议配置

一、项目背景 在现代城市供水系统中&#xff0c;恒压供水是确保居民用水稳定的关键。传统的恒压供水系统通常依赖人工巡检和本地监控&#xff0c;这种方式存在实时性差、效率低、故障响应慢等问题。随着物联网技术的发展&#xff0c;某大型城市供水企业为了实现对供水系统的实…

51. N-Queens

目录 题目描述 方法一、回溯每次判断是否合法 方法二、回溯哈希 方法三、回溯位运算 题目描述 51. N-Queens 方法一、回溯每次判断是否合法 class Solution {vector<vector<string>> res;vector<string> chessboard; public:vector<vector<strin…

西蒙诺维奇-炮弹导体粗糙度模型揭秘

这篇论文的作者&#xff0c;“导体表面粗糙度建模&#xff1a;从”雪球“到”炮弹“&#xff0c;[1] 认为仅凭数据表不可能对传输线进行准确建模&#xff0c;并且似乎暗示&#xff0c;因为我事先测量了数据&#xff0c;所以我神奇地”调整“了 Rz 参数&#xff0c;以获得与 EDI…

VRRP 原理与配置:让你的网络永不掉线!

VRRP 原理与配置&#xff1a;让你的网络永不掉线&#xff01; 一. VRRP 是什么&#xff0c;为什么需要它&#xff1f;二. VRRP 的核心概念三. VRRP 的工作原理四. 华为设备 VRRP 配置步骤 &#xff08;主备模式&#xff09;4.1 拓扑示例4.2 &#x1f6e0; 配置步骤 五. VRRP 配…

【深度剖析】义齿定制行业数字化转型模式创新研究(上篇3:数字化转型动机分析)

数字化转型正在重塑义齿行业的生态格局,但也面临技术融合与模式变革的深层挑战。当前,义齿定制行业正处于从传统手工制造向全流程数字化制造转型的关键阶段。3D扫描、CAD/CAM(计算机辅助设计与制造)、3D打印等技术的广泛应用,显著提升了义齿制作的精度和效率。传统石膏模型…

RustDesk 搭建自建服务器并设置服务自启动

目录 0. 介绍 1. 事前准备 1.1 有公网 ip 的云服务器一台 1.2 服务端部署包 1.3 客户端安装包 2. 部署 2.1 服务器环境准备 2.2 上传服务端部署包 2.3 运行 pm2 3. 客户端使用 3.1 安装 3.2 配置 3.2.1 解锁网络设置 3.2.2 ID / 中级服务器 3.3 启动效果 > …

Python训练营打卡Day40(2025.5.30)

知识点回顾&#xff1a; 彩色和灰度图片测试和训练的规范写法&#xff1a;封装在函数中展平操作&#xff1a;除第一个维度batchsize外全部展平dropout操作&#xff1a;训练阶段随机丢弃神经元&#xff0c;测试阶段eval模式关闭dropout # 先继续之前的代码 import torch import …

《智慧医疗分级评价方法及标准(2025版)》征求意见函全面解读:人工智能医疗应用的评价体系与指南方向

引言 智慧医疗作为医疗行业数字化转型的重要方向,正在通过人工智能等先进技术重塑医疗服务模式和流程。随着人工智能技术在医疗领域的广泛应用,建立科学、规范的评价体系对于推动智慧医疗健康发展具有重要意义。近期,国家卫生健康委发布了《智慧医疗分级评价方法及标准(20…

碰一碰发视频系统--基于H5场景开发

#碰一碰发视频# 旨在构建一个基于移动网页&#xff08;H5&#xff09;的视频“碰传”交互系统&#xff0c;提供类似华为/苹果设备 NFC 轻碰分享的便捷体验。其核心技术依赖于移动端可用的近场通信&#xff08;NFC 或 H5 相关 API&#xff09;和可靠的媒体数据传输方案。实现细节…

京东热点缓存探测系统JDhotkey架构剖析

热点探测使用场景 MySQL 中被频繁访问的数据 &#xff0c;如热门商品的主键 IdRedis 缓存中被密集访问的 Key&#xff0c;如热门商品的详情需要 get goods$Id恶意攻击或机器人爬虫的请求信息&#xff0c;如特定标识的 userId、机器 IP频繁被访问的接口地址&#xff0c;如获取用…

6年“豹变”,vivo S30系列引领手机进入场景“体验定义”时代

出品 | 何玺 排版 | 叶媛 5月29日晚&#xff0c;备受用户期待的vivo S30系列如约而至。 相比前几代S系列产品&#xff0c;S30系列变化显著&#xff0c;堪称“豹变”。首先&#xff0c;其产品打造思路发生了质变&#xff0c;产品体验更好&#xff0c;综合竞争力更为强。其次&a…

Visual Studio 2022 设置自动换行

Visual Studio 2022 设置自动换行 一、在 Visual Studio 菜单栏上&#xff0c;选择 工具>选项二、选择“文本编辑器”>“所有语言”>“常规” 全局设置此选项。 一、在 Visual Studio 菜单栏上&#xff0c;选择 工具>选项 二、选择“文本编辑器”>“所有语言”&…

视频监控汇聚平台EasyCVR安防小知识:如何通过视频融合平台解决信息孤岛问题?

一、项目背景与需求分析​ 随着数字化技术发展与网络带宽升级&#xff0c;视频技术应用场景不断拓展&#xff0c;视频监控、记录仪等多样化产品构建起庞大体系。但这些独立系统彼此割裂&#xff0c;形成信息孤岛。 在系统集成项目中&#xff0c;视频系统深度融合已成必然趋势…

Flutter 4.x 版本 webview_flutter 嵌套H5

踩坑早期版本 使用 WebView 代码如下 import package:flutter/material.dart; import package:webview_flutter/webview_flutter.dart;class HomePage extends StatelessWidget {const HomePage({super.key});overrideWidget build(BuildContext context) {return Scaffold(ap…

new和delete的理解

malloc、free和new、delete的区别 //malloc和free&#xff0c;称作c的库函数 //new和delete&#xff0c;称作运算符 /**********************************************/ //malloc按照字节开辟内存,返回值是void *,需要做类型强转 //仅开辟内存&#xff0c;不做初始化;malloc开…

如何用Python抓取Google Scholar

文章目录 [TOC](文章目录) 前言一、为什么要抓取Google Scholar&#xff1f;二、Google Scholar 抓取需要什么三、为什么代理对于稳定的抓取是必要的四、一步一步谷歌学者抓取教程4.1. 分页和循环4.2. 运行脚本 五、完整的Google Scholar抓取代码六、抓取Google Scholar的高级提…