自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

码农练功房的博客

编程好文推荐,最佳实践分享,开源代码走读

  • 博客(43)
  • 资源 (7)
  • 问答 (1)
  • 收藏
  • 关注

原创 Linux应用框架cpp-tbox之状态机

和基于状态模式实现的状态机相比,cpp-tbox中状态机的实现十分简单,但是简单并不意味着容易。

2024-11-29 13:40:00 997

原创 Linux应用框架cpp-tbox之jsonrpc

rpc其实就是封装了一下通信过程,没有什么神奇的。

2024-11-29 13:32:25 940

原创 Linux应用框架cpp-tbox之HTTP

TCP是基于字节流的传输层通信协议,在实际使用过程中需要设计好消息边界。中间件的思想有借鉴意义,C++的实现简洁、漂亮。

2024-10-25 09:06:34 1033

原创 Lettershell之自动补全

Lettershell中的自动补全实现的基本思想十分简单,不过在实现过程中,还是需要注意清空命令行输入这种细节,否则终端显示会有问题,读者可以自己尝试。

2024-10-21 09:12:13 560

原创 Linux应用框架cpp-tbox之UDP通信

TCP服务端会为每个客户端分配一个文件描述符,而对于UDP服务端,所有的客户端共用一个文件描述符。由于UDP自身的特点,在编程时简单了许多。

2024-10-21 09:01:33 886

原创 Lettershell之参数类型判断

由于函数签名的引入,我们就可以使用函数签名描述任何参数。对应的,在参数类型已知的情况下,也可以定义对应的参数解析器进行参数解析,自定义的参数类型签名需要以L开头,以;结尾。比如说定义一个TestStruct结构体类型为int a;char *b;s);同时,我们需要对自定义的类型定义解析器,使用宏return 0;return -1;free(data);return 0;

2024-10-17 09:06:24 606

原创 Lettershell之命令解析

命令解释过程中,参数类型判定是难点。代理函数的核心是关于类型转换的操作。

2024-10-16 09:01:37 1213

原创 Linux应用框架cpp-tbox之TCP通信(下篇)

TCP客户端实现的难点在于建立连接时的错误处理、重试和重连。由于TcpConnector具备反复尝试连接的功能,因此客户端和服务端的启动顺序无关紧要。基于Reactor模式的非阻塞网络编程,和我们以前主动调用Socket API的编程方式大相径庭,是从主动调用到被动回调的转变。

2024-10-15 09:02:59 649

原创 Lettershell之输入缓冲区

从代码上看,缓冲区的管理逻辑被分散在多个函数中,阅读代码时,我们需要在多个函数间跳转才能看到全貌。除了需要维护好缓冲区外,还需要在增删改查数据的同时维护好回显。

2024-10-15 08:56:59 1243

原创 Lettershell之按键识别

按键注册是一个不错的设计,使得在解析按键时,各个按键的处理逻辑正交,互不干扰。

2024-10-14 13:34:55 671 2

原创 Lettershell之命令注册

由于本人对IAR不是很熟悉,针对IAR中section的使用不做展开。在gcc、arm编译器中是两者都支持的一个编译特性,能够实现在编译时把某个函数/数据放到叫name的section数据段中。在MDK中,使用//......//......其中和为这个section的起始、终止地址。而在Linux中我们不仅需要使用来定义,还需要在程序链接脚本中定义外部变量来指向 section 的起始和结束地址。使用。

2024-10-14 13:14:14 1068

原创 Lettershell之移植篇

letter-shell通过write、read函数注册的方式确实提高了它的灵活性,使得 letter-shell 可以适应不同的平台和环境,无论是单片机还是 Linux 系统。这种方式允许开发者根据自己的需求选择合适的输入输出机制,这种方式不仅提高了可移植性,还增强了 letter-shell 的实用性。

2024-10-12 13:16:05 1268

原创 Linux应用框架cpp-tbox之TCP通信(上篇)

总体来说TCP连接断开的难度大运TCP连接建立的难度;TCP数据发送的难度大于TCP数据接收的难度。相比直接使用Socket API进行网络编程,使用网络库可以避免踩坑。

2024-10-12 08:45:13 1403

原创 Linux应用框架cpp-tbox之串口通信

通过将一个类的对象作为另一个类的成员变量,可以让一个对象“委托”另一个对象来处理某些功能。这种方式可以避免继承的复杂性,提高代码复用。

2024-10-11 13:50:35 577

原创 Linux应用框架cpp-tbox之应用层缓冲

在非阻塞IO模型+IO复用编程模型中,应用层缓冲是必须的。系统调用(如read, write, open, close等)涉及用户态到内核态的转换,这一过程相对耗时,尽量减少系统调用是提高程序性能的一种策略,特别是在性能敏感和高并发的系统中尤为重要。

2024-10-11 13:45:28 900

原创 Linux应用框架cpp-tbox之线程池

私有数据成员指针封装(内部结构体指针封装)。在面向对象编程中,它体现了封装和数据隐藏的原则,即将数据成员(这里是Data结构体)声明为私有,并通过一个指向该类型的指针(d_)来管理访问和操作,从而保护数据成员不受外界直接干预,仅通过类提供的接口进行交互。条件变量是实现线程池的核心。

2024-10-10 11:41:49 1190

原创 Linux应用框架cpp-tbox之事件驱动Event

在Linux中,信号处理有时被视为是不安全的,此时可以考虑使用pipe、signalfd、eventfd等机制来提高信号处理的安全性。

2024-10-10 11:31:27 1073

原创 Linux应用框架cpp-tbox之事件驱动EventLoop

Reactor模式是一种事件驱动的设计模式,广泛应用于异步I/O处理,特别是在需要高效处理大量并发连接的服务器程序中,如Web服务器、数据库服务器、即时通讯软件等。Reactor模式的核心组件是一个事件循环(EventLoop)线程,它负责监听、分发并处理来自I/O源的事件。cpp-tbox采用的也是Reactor模式,为了便于我们理解什么是Reactor模式,库作者给出过一个贴近生活的例子:Reactor线程就像是一个银行的办事柜台。

2024-10-10 11:20:19 1398

原创 Linux应用框架cpp-tbox之日志系统设计

1) 有三种日志输出渠道:stdout + filelog + syslogstdout,将日志通过std::cout输出到终端;syslog,将日志通过syslog()输出到系统日志;前缀.年月日_时分秒.进程号.log的文件中。文件大小超过1M则另创建新的日志文件。由于写文件效率低,该输出渠道采用前后端模式。三种渠道可以在启动参数中选定一个或同时多种,也可在运行时通过终端更改。2) 根据日志等级渲染不同颜色,一目了然,内容详尽。

2024-10-10 11:10:16 1304

原创 Linux应用框架cpp-tbox之弱定义

学过C/C++的都知道,main函数是程序的入口点,是程序开始执行的地方。每个可执行的C或C++程序必须包含一个main函数。但是参照官方提供的demo,我们会发现:demo没有定义main函数,编译竟然没有报错,而且生成的可执行文件还能运行!在C和C++编程中,attribute((weak))是一个编译器特性(attribute),主要用于告诉编译器或链接器对待特定的函数或全局变量为“弱定义”(weak definition)。

2024-10-10 10:45:43 501

原创 一个死锁问题分析

为什么会死锁呢?一起来看看!!!

2022-12-05 17:57:45 494

原创 Linux应用程序崩溃定位

介绍Linux应用程序崩溃的一些定位手段

2022-09-13 14:36:25 1561

原创 modern cpp 左值右值

C++左值右值介绍

2022-07-13 13:22:57 337

转载 第一颗子弹

软件不软的一个主要原因,是其经常处于变化之中。所以,当策略分离不同的变化方向被提出后,一个随之而来的问题也就产生了:何时分离?尽管一个软件已经满足了当前所有需求,作为富有经验,伤痕累累的程序员,我们却毫无喜悦,因为我们很清楚,事情还远未结束:用不了多久,新需求就会再次排山倒海般涌来。而当前设计能否顶得住下一波的冲击,没有人心里有底。怀着不安的心情,我们打开IDE,调出代码,翻页跳转,试图从字里行间揣测未来变化的可能性。可深究起来,几乎每一行代码,每一项知识都似乎存在变化的可能性。但如果把每一种可能的变化

2022-03-04 15:08:28 154

原创 cpp智能指针

搜了下智能指针的博客,发现很乱,c++ Primer上也一大堆废话,有时看的不知所云。最后在博客园上找到一个总结还算不错的,可以快速了解下基础用法和场景。里面有些代码有点问题,修正后贴出,方便后续快速查阅。智能指针都是值语义(通常作为类的数据成员或者在stack上或者是标准容器库里面的元素),几乎不会有如下用法:shared_ptr<Foo>* pFoo = new shared_ptr<Foo>(new Foo);如果智能指针是对象x的数据成员,而他的模板参数T是个inc

2022-03-04 14:36:16 559

原创 智能指针与多线程

目的:智能指针在多线程编程场景下,可以保证对象安全地析构,解引用时对象有效。本文中涉及到的具体内容可以参考linux多线程服务端编程一书的第一、二章。小结:这里汇总下书中的结论:对象析构算是写操作。借助shared_ptr来实现线程安全的对象释放,但是shared_ptr本身不是100%线程安全。所以多个线程中访问同一个shared_ptr也需要加锁保护。shared_ptr会延长对象的生命周期,只要有一个指向x对象的shared_ptr,该对象就不会析构。shared_ptr是值语义,当

2022-03-04 14:35:05 1429

原创 基于对象和面向对象风格

基于对象和面向对象风格这种叫法来源于陈硕的<<Linux 多线程服务端编程:使用 muduo C++ 网络库>>一书。其具体含义如下:基于对象风格:具体类加全局函数的设计风格。面向对象风格:使用继承和多态的设计风格。作者认为对于应用程序,不宜使用过多的继承,设计过于复杂的继承体系。框架可以考虑使用面向对象风格。以下例子来源于github,本文基本搬移:用面向对象的方法封装一个Thread类一、实现首先定义一个基础的Thread类:Thread.h:#ifndef

2022-03-04 14:33:45 279

原创 最多能创建TCP连接个数

TCP连接个数受端口号、文件描述符、线程资源、内存资源、CPU资源的限制。端口号:系统用一个四元组来唯一标识一个TCP连接:{local ip, local port,remote ip,remote port}在local ip, local port固定、不考虑ip地址分类的情况下,最大tcp连接数约为2的32次方(ip数)×2的16次方(port数),也就是server端单机最大tcp连接数约为2的48次方。实际可用端口范围可以如下查看:[root]# cat /proc/sys/net/i

2022-03-04 14:27:22 3540

原创 ch2 gpio应用:Buzzer封装

Buzzer封装:蜂鸣器是GPIO的一个典型应用,下面我们利用C++语言的继承机制完成对Buzzer类的封装,Buzzer类继承自CGpio类,CGpio类的具体实现参考:ch1 gpio封装亮一张蜂鸣器的电路吧O(∩_∩)O![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mmeQExFJ-1645750489034)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRA

2022-02-25 08:55:21 1153

原创 ch1 gpio封装

一起封装gpio吧!​ 学会使用gpio是学习单片机的第一步,网上的大多数单片机学习教程都是从gpio开始的,对于gpio的典型应用非常的多,有流水灯、蜂鸣器等等。今天我们就来对gpio进行封装。先来看看封装的效果吧!CGpio调用效果:int main(){ CBsp bsp; bsp.Init(); CGpio output(PORT_A,PIN_0);//构造一个io对象,给定PORT和PIN,默认配置为输出口; ou

2022-02-25 08:50:24 337

原创 ch0 CBsp类的实现

为什么用C++开发单片机程序​ 在以微处理器为核心的嵌入式系统中,大部分采用C语言来进行程序设计,但是随着系统规模的增大,程序越来越复杂,维护也越发困难。而使用C++进行开发有以下好处(前提是编译器必须支持C++,否则都是空谈):减少了参数传递。在C++中可以将用到的数据作为数据成员,这样可以避免函数的参数传递过程,能够提高执行速度和效率。更加安全。C++对数据和方法进行了封装,这样可以隐藏类实现的细节,避免内部数据结构暴露。可以减少命名的冲突。C语言没有命名空间的概念,这样容易导致

2022-02-25 08:40:51 595

原创 单片机延时函数实现

在编写单片机程序时,我们经常要用到延时函数,记得我们在学51单片机时,第一个延时是通过软件延时来实现的,代码如下:void delay(volatile uint32_t cnt){ volatile uint32_t i = 0; volatile uint32_t j = 0; for(i = 0;i<cnt;i++) for(j = 0;j<1000;j++); }软件延时的优点是方便,然而却不能提供很精确的延时,而且占用CPU资源

2022-02-25 08:23:57 5599

原创 类成员指针

指向类的数据成员的指针:指向数据成员的指针格式如下:<类型说明符><类名>::*<指针名>例如,设有如下一个类A:class A{public: int fun (int b) { return a * c + b; } A(int i) { a = i; } int c;private: int a;};定义一个指向类A的数据成员c的指针pc,其格式如下:int A:: *pc = &A::c;再定义一个指

2022-02-24 08:55:15 751 2

原创 调用约定与符号名

目的:这里对【函数调用约定与Name Mangling】之间的关系进行总结,方便后续查找。调用约定:__stdcall、__cdecl和__fastcall是三种函数调用约定,函数调用约定会影响函数参数的入栈方式、栈内数据的清除方式、编译器函数名的修饰规则等。调用约定入栈方式清栈责任__stdcall从右到左函数自己__cdecl从右到左调用者__fastcall从右到左(先 EDX、ECX,再到堆栈)被调用者调用协议常用场合:__stdca

2022-02-24 08:53:57 191

原创 时间管理总结

#背景windows FILETIME时间从1601/01/01 零时零分零秒开始计时,windows每个时钟滴答将计数加一,每个时钟滴答的间隔是100 nanoseconds(纳秒,1秒=10的九次方纳秒),即每个时钟滴答= 10 (-7)秒。unix、linux时间是从1970/01/01零时零分零秒开始计数,每秒计数加1。1970/01/01与1601/01/01的时间间隔是11644473600秒。#结构体FILETIME 结构体表示自1601年1月1日以100纳秒为基准的时间间隔。FIL

2022-02-24 08:53:05 247

原创 windows动态库和静态库

梳理下项目中常用的动态库、静态库使用方式。静态库静态库工程生成一个静态库lib文件。参考文献6制作lib后,有三种方式去使用:使用comment 显式调用,这样不用在visual studio 链接器->输入->附件依赖库里面配置依赖库,由于没有指定依赖库路径所有需要显示填写路径。使用comment 显式调用,同时需要在链接器->常规->附加库目录中配置依赖库路径。由于使用了comment所以不用在visual studio 链接器->输入->附件依赖库里面配

2022-02-24 08:51:27 1866

原创 linux随记

shell:shell第一行为#!/bin/bash或#!/bin/sh如果想要打印shell脚本中的每条命令的执行情况可以这样写,其中-x是用来调试用的:#!/bin/sh -x\r,\n与\r\n区别:Unix换行:\n (0x0A)MAC回车:\r (0x0D)Win回车换行:\r\n (0x0D,0x0A)抓包:tcpdump -i any -s 0 host 172.16.119.145 -v -w /tmp/test001.pcaptcpdump dst port

2022-02-24 08:50:53 394

原创 cpp模板总结

总结下c++模板相关的基础知识,便于查阅。模板:模板定义以关键字template开始,后跟一个模板参数列表,这是一个逗号分隔的一个或者多个模板参数的列表,用小括号和大括号包围起来。模板是个半成品,模板编译通过但是使用错误仍然会报错;可以将模板看作是编译期函数;运行期函数的参数要为一个对象(不能是模板);编译期函数的参数可以是模板;声明:模板声明必须包含模板参数:// 声明但是不定义compare和Blobtemplate<typename T> int compare(cons

2022-02-24 08:50:22 2054

原创 静态变量初始化

静态变量的初始化分为两个过程,一个是静态初始化,一个是动态初始化。静态初始化在系统加载后执行第一条语句之前就已经完成。所以,可以认为所有的静态初始化过程是同步完成的。动态初始化,则在main函数之前完成,对于同一个编译单元内的静态变量,动态初始化顺序等同于定义顺序,而对于跨编译单元的静态变量,初始化顺序未定义。静态数据有两种:已初始化数据和未初始化数据。在映像文件里,它们分别被放入 data 段和 bss段。只有 data 段的已初始化的数据才会真正被放入映像文件。int a=5;//data 段

2022-02-24 08:49:27 4919

原创 Go语言面向对象之旅

目的:通过一道题目体验下Go语言下的OO编程范式。题目:模拟人和机器人制造产品。这里人和机器人在工作时都是一名worker(扮演的角色),工作的流程是一样的:如果能量没有消耗完,那么可以继续制造产品,否则停工。区别在于依赖的能量消耗和获取方式不同:人制造产品会消耗吃饭得到的能量,缺乏能量后需要再吃饭补充。人吃完饭后能量值为10,每生产一件产品,消耗能量值为1,吃完饭后能量恢复到10。机器人制造产品会消耗电能,缺乏能量后需要再充电,充完电可以继续工作。充完电后能量值为100,每生产一件产品,消

2022-02-24 08:41:19 290

实现模式,软件设计方法论经典,有追求的人可以看看。

实现模式,软件设计方法论经典,有追求的人可以看看。

2022-03-08

单片机面向对象程序设计

单片机面向对象程序设计

2017-06-13

STM32F1系列 C++工程模板

STM32F1系列 C++工程模板;建议用MDK520打开

2016-06-03

STM32L1 C++工程模板

STM32L1 C++工程模板;尽量用高版本的keil打开

2016-05-31

STM32L工程模板

本压缩包提供的是STM32L的工程模板;开发工具为MDK

2016-03-01

STM8L例程之串口

本压缩包提供的是STM8L的IAR工程模板,程序实现的功能是实现MCU与PC的交互。

2016-03-01

内存分区介绍

本文档主要介绍了内存分区模型、大小端和字节对齐的问题

2016-02-25

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除