自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(73)
  • 资源 (7)
  • 收藏
  • 关注

原创 一种动态联动的实现方法

本文中,笔者将此类动态联动的问题抽象化,并提供上面提到的第二种方法的演示实现。

2024-03-17 22:22:41 1184

原创 基于USDT的日志优化

尽管安卓系统的日志管理系统是原生的,但这么大的日志生成量确实给设备带来比较大的负载(尤其当日志需要保存到文件中时)。这固然与嵌入式软件研发管理脱不开关系,但我们仍然需要寻找相应的解决办法——尤其对于一个没有研发管理权限的开发人员(如笔者),不可能限制其他的开发人员不在代码中加入过量的、循环的日志信息。一种方案是,通过编译时的宏定义来控制这些日志信息是否会生成,但这也造成了一问题:用于生产的嵌入式应用很可能因编译时的宏定义,不会生成这些冗余的调试信息,而一些软件异常只能在实际应用中发生。

2024-03-09 20:32:22 898

原创 为raspberrypi编译bpftrace调试工具

例如,树苺派的Linux内核版本为6.1,那么确认该版本内核的(初始)发布日期(是2023年初发布的),然后选择时间上相近的。系统,二者的Linux内核版本大致相同,均为6.1版本。之后,我们需要在debian安装其他依赖库(而不编译所有的依赖库,否则耗时太久了)。工具的过程,按照这些操作,笔者为工作中的嵌入式设备也制作了可用的。然而工作中,笔者因使用的嵌入式设备比较老,使用的版本为。的正常运行,可能还需要访问内核的头文件,这就需要使能。然后,笔者为树莓派的内核使能了相关的内核选项,详见。

2024-03-03 20:19:02 1117

原创 在Ubuntu-12.04环境下使用新的Rust开发工具

这种修改、替换应用使用的动态链接器(从而间接指定使用的glibc动态库)的方法,可以方便地为老系统安装一些新的应用。在一些工作环境受限的条件下(如不能安装新的系统作为开发环境),能够让我们不受过多的限制,不影响我们对开发工具的选择。

2024-02-17 21:45:25 973 1

原创 RISCV汇编与Linux内核传参

这种方法生成的可执行文件是静态链接的,不依赖动态链接器也不能调用标准C语言库提供的功能。第二种方法是可以连接到标准C语言库的,而且是动态链接的。的C语方库的这一过程整合到全志D1设备上运行,就可以直接在汇编代码中引用柡准C语言库提供的变量及函数。这一点可以参考上面帖出的Linux内核源码:因在riscv平台上,C语言函数栈是向下生长的,内核在栈上构造这些信息时,参数的写入恰好与。而该设备上也缺少整套的。需要说明的是,在使用C语言库编写汇编应用时,需要严格地遵守。的应用层汇编的开发,有了一个可行的方法。

2023-11-26 19:09:19 412

原创 携带二进制文件的软件恢复方法

为快速修复远程嵌入式设备上的某个服务,一种将升级、配置操作命令与升级包集成于同一个脚本文件的方法

2023-11-15 22:53:12 225

原创 一种嵌入式应用软件内存泄露的跟踪定位方法

一种简单的C/C++应用软件内存泄露问题的定位方法

2023-07-02 12:10:32 401

原创 获取系统中各应用的运行时间

因为笔者的树莓派内核的配置选项为该值。但在其他嵌入式设备上运行结果是正确的(感兴趣的可以尝试一下)——该方案通常只适用于嵌入式设备,而不适合在。由此可判定各个应用进程的开始运行时的系统启动时间,其与当前系统已运行的时间之差,就是应用进程已持续运行的时间。另一种可行的方案是,增加一个动态库,当动态库被加载时会自动执行一个函数,记录应用开始运行时的系统时间。不过该方案的缺陷是需要修改各个应用的代码,并增加进程间通信的机制(通过上面的。这也是笔者在该分享前部分说的,相比之下,另两种方案的可取之处。

2023-05-14 16:26:45 555 1

原创 使用bindgen将C语言头文件转换为Rust接口代码

本文演示了使用bindgen将C语言头文件转换为Rust接口代码文件的两种方法

2023-01-25 16:34:09 1669

原创 在嵌入式设备运行Rust/bluer蓝牙简单应用

本文主要演示了如何在openwrt嵌入式设备上编译、运行bluer蓝牙简单应用程序的过程

2023-01-08 14:26:05 1187

原创 为嵌入式设备编译Rust/dbus进程间通信组件

本文演示了如何交叉编译Rust/DBus模块并在嵌入式设备上运行简单示例的过程

2022-11-26 17:37:37 1280 1

原创 Rust引用转换时避免使用变量

本文记录了笔者在Rust引用转换时避免使用多余变量的方法

2022-11-20 16:44:07 556

原创 为全志D1/RISCV64设备移植openwrt-22.03系统

为全志D1/RISCV64东山派设备移植openwrt-22.03

2022-09-19 22:16:50 2084

原创 基于uftrace的应用性能侧写

本文演示了使用开源工具uftrace的应用性能侧写操作方法,并对不同方法的结果作比较

2022-06-03 15:47:54 520

原创 Rust下的JSON动态反序列化

Rust下的结构体反序列化在之前的一篇文章中,笔者介绍了在Rust编程语言中,使用serde_json包对结构体的序列化和反序列化的基本操作;重点是在定义结构体时,继承源于serde包的 Deserialize及Serialize特性:use serde_json;use serde::{Deserialize, Serialize};#[derive(Serilize, Deserialize, Debug)]struct rust_struct { member_0: String,

2022-05-21 15:18:32 1348

原创 为嵌入式设备编译paho.mqtt.rust应用

为嵌入式MIPS准备rust开发环境在此前的一篇文章中,笔者对Rust的交叉编译开发环境的安装作了说明,演示了简单Hello World应用的交叉编译。笔者在该文章中记录了较为复杂的rust应用(paho.mqtt.rust)的编译过程,目柡设备为运行openwrt系统的MT7628设备。此处简要重复笔者安装嵌入式MIPS的rust交叉编译工具链的过程。首先,以根用户权限安装rust编译器:curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs

2022-05-01 13:30:57 828

原创 PLY:嵌入式Linux环境下的内核探测工具

简单Linux系统环境下的内核探测在笔者之前的文章中提到,基于内核eBPF探针的常用工具主要bpftrace、bcc,二者复杂的依赖库使得其在嵌入式Linux系统环境下常常是不可用的。截止目前,一些嵌入式SDK(例如buildroot及openwrt等)未提供这两个性能分析工具的自动化构建功能。一种可行的方案是参考Linux内核源码samples/bpf下的示例编写基于eBPF的C代码,并编译生成BTF目柡文件和可执行应用,用于嵌入式设备上的性能分析。这种方案可行但实施的效率较低。幸运的是,同属于iovi

2022-04-17 08:45:19 911

原创 虚拟动态共享库VDSO的实现机制

失落的strace在《BPF Performance Tools》一书中,作者评批strace用于监测系统应用的创建execve时写道:The current implementation of strace(1) uses breakpoints that can greatly slow the target (over 100x), making it dangerous for production use. ...Also, this example traces the exec() sy

2022-04-05 20:44:22 1649

原创 为Evince-PDF添加灰色背景

Ubuntu系统的默认PDF阅读软件ubuntu操作系统自带了Evince-PDF阅读器,其优点是简单便捷,不过与其他常用的PDF阅读器相比,缺少很多定制化的选项,例如为避免眼睛疲劳的替换阅读界面背景颜色的功能。使用GNU/Linux操作系统的一个优势是,可以获取从内核至应用各个层面的软件源码,并加以修改后重新编译,可以方便地实现所需的新功能。笔者在该文章中记录了为Evince阅读器添加灰色背景的操作过程。作为对比,在添加该功能之前,笔者打开SystemTap教程文档的背景如下:修改之后,在Evinc

2022-03-20 12:08:35 1089

原创 基于Linux内核的应用探测: uprobe

基于Linux内核的应用性能分析技术Linux内核有良好的分层设计,但了解并实时跟踪内核的行为并不容易。为此,Linux内核开发者实现了跟踪点(tracepoint)、性能监测(perf_event)、函数跟踪(ftrace)等功能,用于Linux的调试和性能分析。最近几年已经成熟的eBPF内核子系统带来了内核性能分析技术的飞跃,常用的主要有bcc、bpftrace;二者同属于github的iovisor用户,直译出来即为“输入输出监测”,即性能监测。这些工具同样可用于应用层的性能分析,这是笔者关注的功能

2022-03-13 20:31:28 3822

原创 SystemTap应用跟踪探测的使用

用户静态定义探测点USDTusdt(User-Statically-Defined-Tracepoint)是一种向应用插入跟踪点的技术方案,其特点是跟踪点的插入是静态的,通常需要修改应用的源码并再次编译。该技术方案源于DTrace,不过usdt应用跟踪的功能在Systemtap和bcc等内核跟踪调试工具中已有良好的支持。Systemtap开源工具提供了sys/sdt.h头文件,该头文件没有相应用C代码实现,仅仅提供了多个STAP_PROBExxx和DTRACE_PROBExxx宏定义。这些宏定义通过GCC

2021-11-07 23:23:41 701

原创 嵌入式设备上SystemTap调试工具使用

SystemTap调试工具简介SystemTap调试器常用于Linux内核的动态调试,不过该工具集也可用于应用的跟踪调试。随着Linux内核及其应用程序的复杂度不断加深,使用一些在功能上区别于传统的GDB调试工具就变得越来越重要了。这类调试工具具有低延时(Low Latency),高性能,动态调试的特点。嵌入式Linux设备的系统软件通常不需从头开发,这些调试工具可以帮助开发者快速理解Linux内核、系统层软件,同时定位、解决一些软件上的缺陷。SystemTap的工作机制比较特殊,它会将开发者编写的Sy

2021-10-31 21:54:43 1105

原创 BPF示例在64位ARM上的调试

eBPF调试工具eBPF作为Linux内核中调试功能强大的子系统,相应的应用层调试工具有很多,例如bpftool/bpftrace,以及提供了Lua和Python调试接口的bcc;内核信息收集、性能分析的开源工具SystemTap也用到了内核的eBPF功能。不过笔者希望在嵌入式设备上使用eBPF提供的调试功能,一种方法是使用开源的SDK(例如yocto,笔者未尝试过)自动化构建这些调试工具(否则就需要手动交叉编译);另一种方法是将某个支持arm64架构的Linux发行版(例如运行debian系统的树莓派)

2021-10-24 22:18:05 3309 4

原创 BPF内核调试开发坏境的搭建

BPF的内核调试方法一直以来,笔者对BPF功能的认知一直停留在与tcpdump工具进行网络抓包相关;最近几年BPF已成为内核的顶级子系统,从网络抓包的内核支持模块演进成为内核调试、性能跟踪的复杂模块。其对内核的调试(也可用于应用的调试)是动态的;不过该动态调试过程并不需要编译内核模块并加载之,而是将调试应用编译成为eBPF字节码,并通过bpf系统调用将该字节码加载到内核中的BPF虚拟机中解析执行,或由内核中的BPF Jit编译为机器码后运行。这一调试机制使得其与传统的GDB调试方法相比,具有更低的延时和更

2021-10-17 22:41:15 3163 3

原创 GDB内存调试初探八

Linux/amd64的调用规则为了方便调试,笔者在PC机上直接调试简单的内存相关的应用;这需要了解x86_64的ABI,该文档对函数调用制定了一些限定规则,其中重要的有两点,第一点是参数的传参(非浮点参数):User-level applications use as integer registersfor passing the sequence: %rdi, %rsi, %rdx, %rcx, %r8 and %r9.The kernel interface uses %rdi, %rsi,

2021-10-10 22:37:36 975

原创 GDB内存调试初探七

非main_arena的内存分配在初探六中提到,正常情况下创建一个新的线程时,会为新线程创建独立的arena,其类型为struct malloc_state。当一个线程退出时,其动态分配的堆内存不会被释放,而是通过malloc_state结构体中的next_free指针链接保存起来(那么当再次创建新线程时可复用):/* malloc/malloc.c */struct malloc_state { ... struct malloc_state * next; struct m

2021-10-03 21:44:39 1169

原创 应用OOM及子进程的创建

Linux应用内存分配失败的问题大型的嵌入式应用常占用巨量的内存。一些“杂揉、拼凑”而成的应用,常在一个应用中包含多个功能模块,例如音视频处理模块,系统控制模块等。这样的应用设计会带来一系列的内存问题,最主要的一个是音视频的应用会占用大量的内存空间,从而影响应用的运行性能。笔者根据以往的经验,列出一种与子进程创建相关的内存分配失败问题。当某个应用向Linux内核申请内存但内核无法满足时,内核会根据配置,选择性地杀掉该进程;该功能与OOM-Killer相关(注意,区别于安卓内核中的lowmemory-kil

2021-09-25 22:35:02 851

原创 ARMv7-a的多寄存器Load/Store

多寄存器的加载与存储ARMv7-a架构的芯片提供了高效的寄存器数据加载与存储指令,一条指令可以从内存中加载多个寄存器,也可以将多个寄存器的数据存储至内存中。读写的内存必须是连续的;虽然数据量不大,但基于这些指令可以实现高效的数据拷贝、(软)中断的上下文保存、恢复,以及内核的任务切换、应用层的协程实现。Arm Architecture Reference Manual对这些指令做了详尽的说明:编写多寄存器的加载和存储示例ARMv7芯片提供了以上多种指令,原因是这些指令在加载、存储数据时,具体功能实现有

2021-09-19 23:02:38 530

原创 GDB内存调试初探六

内存访问越界的定位去年笔者分享了两篇内存访问越界的定位方法,第一种方法用到了mprotect系统调用设置内存属性,第二种方法则未用到该系统调用。两种方法对于调试用的简单应用都有效,不过笔者编写的调试应用是单线程的。在具体的工作实践中,只用到过第一种方法;因此不确定第二种方法效果如何。笔者认为这两种方法有一些缺点,某些情况下甚至可能会失效,例如系统调用产生的内存访问越界:read(fd, buf, buflen + overflowsize)。此外,第二种方法需要知晓具体的内存分配的数据结构,笔者希望通过本

2021-09-12 22:31:35 1101

原创 U-Boot的重定位实现机制

获取当前芯片平台的相关信息为了深入了解ARM 64位芯片架构,笔者为u-boot添加了archinfo命令,以获取CPU当前的工作状态等信息。不过在增加完整的64位ARM架构信息查看功能之前,笔者首先增加了简单的获取当前PC指针及栈指针的函数:diff --git a/arch/arm/lib/arch-info.c b/arch/arm/lib/arch-info.cnew file mode 100644index 00000000..b9bc9fd0--- /dev/null+++ b/a

2021-09-05 22:05:13 1919

原创 U-Boot启动Linux内核的简单实现

64位ARM Linux内核启动的环境要求在64位ARM处理器上,Linux内核启动前,对设备的环境要求主要有以下几点:内存(DDR)已初始化完成,禁用MMU,关闭数据缓存(dcache);蔽屏CPU中断,关闭指令缓存(icache);禁用驱动的DMA操作,防止Linux内核在启动过程中内存被IO设备访问;除此之外, Linux内核对64位ARM处理器的状态(例如异常级别,Exception Level)有一些细致的要求,这里不再探究,详细的说明请参考官方文档。U-Boot启动

2021-08-29 22:51:06 803

原创 GNU Makefile -- 规则依赖执行顺序和双冒号规则

Make的规则依赖执行顺序GNU Make的规则依赖有两种类型:普通依赖(normal prerequisites)和顺序依赖(order-only prerequisites)。对于普通依赖,其出现的顺序指定了依赖被更新的顺序。这一特性可以在一定程度上(非并行调用Make)隐含各依赖项之间的依赖关系,但不具备稳定性。笔者编写了简单的测试脚本:.PHONY: all foo bar cleanifeq ($(REORDER),yes)all: bar foo | orderedelseall:

2021-08-22 23:23:12 3691

原创 Rust对异步编程的支持

线程池与异步执行作为一名嵌入式底层开发人员,工作中很少遇到线程池和异步执行的概念。在Lua脚本语言中有一个协程的概念,与线程池的异步执行有一些相似,但仍存在很多区别。用户态应用创建一个线程,绝大部分时间处于阻塞的状态(如果不是这样,这个线程占用的CPU时间会很高);线程会占用一定的系统资源。当一个多线程的应用的大部分线程都处于一个阻塞的状态,那就会浪费很多的系统资源。此外,对于一些高并发的事件处理,若采用创建新的任务线程的方案,那么某些情况下创建的线程数量可能达到上百个甚至上千个。这两点都会浪费操作系统的

2021-08-15 23:18:40 912

原创 Rust结构体的JSON序列化和反序列化

一个JSON的序列化问题与人聊天时偶然问到一个问题:“给定任意一个(C/C++)结构体,如何实现其JSON的序列化和反序列化,而不用专门编写相应的序列化、反序列化实现代码?”我摇摇头,表示不知如何实现这一功能;现在我也认为,这一功能对于C/C++,是不可能自动化实现的。不过对于其他的静态编译型编程语言,如Golang/Rust等,这一功能则相对容易实现。与Golang的反射机制(Reflection)不同,Rust使用到了trait机制。Rust的JSON序列化库serde提供了通用的序列化功能,诸多

2021-08-08 23:05:02 3453

原创 GNU Makefile--C/C++头文件依赖规则的生成

使用GCC编译器生成头文件依赖复杂的C/C++工程中的头文件比较多,在编写GNU Makefile时,手动指出其源代码文件的头文件依赖关系是不可行的,需要通过编译工具自动生成头文件的依赖关系。GNU GCC的-MXX命令行选项用于生成某个代码文件的依赖关系,通常使用的命令行选项为:-MT object.o -MP -MMD -MF object.d其中,-MT用于指定与源文件对应的目标文件名(此处为object.o);-MP指示GCC编译器为依赖的头文件增加伪目标规则;-MMD不会隐含增加-E编译选

2021-08-01 22:33:35 1021

原创 u-boot的自拷贝(重定位)

u-boot的加载地址早期的通用启动器(Universal Bootloader, u-boot)没有图形界面配置的功能,为某个设备修改配置的操作比较繁琐。较新版本的u-boot提供了图形化配置界面,可以在以下配置界面下修改u-boot的加载基地址(对应的配置项为CONFIG_SYS_TEXT_BASE):-> Boot options -> Boot images -> Text Base该地址指定了u-boot在内存中存放的起始地址,通常由SoC厂商的内置B

2021-07-25 21:41:53 1308 2

原创 GNU Makefile--命令行参数的传递

make的命令行变量参数在Makefile脚本中,可以通过$(MAKE)递归执行其他的Makefile。make的一些命令行选项(例如禁止输出当前目录的选项--no-print-directory等),会对其行为产生一些影响,而递归调用的make也应当继承这一类选项。此外,在编译u-boot或Linux内核等工程时,常用的命令为:make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- ...命令中的ARCH和CROSS_COMPILE两个变量参数也应当在由$

2021-07-18 22:05:02 11037 1

原创 Rust应用调用C语言动态库

外部功能接口FFI虽然高级(脚本)编程语言的功能丰富,表达能力强,但对底层的一些特殊操作的支持并不完善,就需要以其他编程语言来实现。调用其他编程语言的接口,被称为Foreign Function Interface,直译为外部功能接口。该接口通常是调用C语言实现的外部功能模块,因为C语言接近于全能,几乎任何功能都能够实现;正如同使用汇编语言也可以实现很多功能一样,但开发效率低下。很多脚本语言提供了FFI功能,例如Python、PHP和JIT版本的Lua解析器等。同样的,Rust也提供了FFI接口,作为标准

2021-07-11 21:38:06 9752

原创 netlink套接字监测网络设备

网络设备的状态监测嵌入式系统层的开发常涉及到设备的网络配置,如何监测设备网络状态的变化通常是一些系统级的服务在实现过程中需要考虑的问题。一种可行的方案是在系统服务里创建一个线程,每隔一段时间(如5秒)获取网络接口的连接状态及信息,并与之前的信息相比较。这种方案的优点是简单、直接;而缺点是响应网络变化不及时,轮询的方式从某种角度看,是不合理的。实事上,现在已有了很多开源的网络配置服务,如openwrt中的netifd,及桌面系统下的NetworkManager(一些嵌入式SDK集成了该网络服务的守护进程);

2021-07-04 20:38:40 1362 1

原创 GNU Makefile--调试器remake

remake调试器国外的开发人员对GNU Make进行了一定程度上的重构,增加了Makefile的动态调试功能,命名为remake。调试器的操作界面类似于GDB的命令行,开发者为其编写了详细的文档,有兴趣的可以参考。GNU Make自身也支持若干个调试选项,但其调试功能比较有限,remake的作者对此很不满。不过,remake工具对递归的调试(即一个Makefile脚本中调用$(MAKE)执行新的Makefile)支持不够完善,对单个Makefile的调试功能则相对完整。本文记录了笔者通过remake工具

2021-06-27 20:44:18 1289

phell分析Makefile变量的工具

简单GNU Makefile调试工具,详见相关博客

2021-05-30

LuaARM.tar.xz

用于在嵌入式ARM/Linux(及安卓)设备上安装一个简单的Lua脚本运行环境。包含独立的glibc库文件,因此不需要依赖设备的文件系统。提供了ubus/uloop/uci/luasocket/luaposix/zeromq等开源软件的Lua模块,理论上可以开发较为复杂的嵌入式应用(纯Lua脚本)。相关的博客文章对此资源有更详细的描述说明。

2020-08-09

memory_20200518.zip

用于在Linux/ARMv7嵌入式设备上调试glibc的ptmalloc内存分配模块的简单应用(附源码)

2020-05-31

LinuxARM.tar.xz

本资源类似于博客文章(https://blog.csdn.net/yeholmes/article/details/78568172)中提到的安装于嵌入式设备上的简易调试、开发工具;不过该资源用于分享此类工具的制作原理及过程,相关博客文章后续会贴出来。在安卓手机上或嵌入式ARM/Linux设备上的安装步骤为: 1: cd /data/user/ ; umask 022 2: busybox xz -d -c LinuxARM.tar.xz | busybox tar -x -f - 3: cd LinuxARM ; tar -xf Git.tar 4: sh scripts/install.sh 之后就可以通过SSH登录到设备上。该资源主要包含了Vim/Git/Gdb/Coreutils/Lua等开发调试工具。

2020-04-12

coroutine.tar.gz

基于AArch64平台,Linux内核任务切换的实现机制,应用层的简单协程实现。详见相关博客的帖子。

2020-01-05

c++-mprotect.tar.gz

为了让应用在踩内存时就发生崩溃(这样可以使用gdb调试,或分析其coredump),一种方法是将C++类对象配置成只读属性;可用的系统调用为mprotect,它可以配置一段对页对齐的内存区域内存的读写属性。

2019-10-27

rootfs.ext2.xz

ext2根文件系统镜像,用户名为root,密码为123456。用于QEMU运行Linux内核。EABI硬浮点。如要编译简单应用置于其中,建议使用Linaro的交叉编译工具链,6.4及以下的gcc版本。

2019-08-04

空空如也

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

TA关注的人

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