- 博客(43)
- 资源 (7)
- 问答 (1)
- 收藏
- 关注
原创 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
原创 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之命令注册
由于本人对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
转载 第一颗子弹
软件不软的一个主要原因,是其经常处于变化之中。所以,当策略分离不同的变化方向被提出后,一个随之而来的问题也就产生了:何时分离?尽管一个软件已经满足了当前所有需求,作为富有经验,伤痕累累的程序员,我们却毫无喜悦,因为我们很清楚,事情还远未结束:用不了多久,新需求就会再次排山倒海般涌来。而当前设计能否顶得住下一波的冲击,没有人心里有底。怀着不安的心情,我们打开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
Linux线程分离后主线程连接怎么会成功?
2017-09-01
TA创建的收藏夹 TA关注的收藏夹
TA关注的人