嵌入式开发笔记(1)

Git

git submodule

  1. git submodule 命令用于管理包含其他 Git 仓库的项目。 git submodule可以将外部库作为你的项目的一部分来管理,而不必将其直接合并到主仓库中。 •
  2. Git submodule init初始化配置文件中的所有子模块:根据.gitmodules文件中内容设置子模块的URL和路径到本地.git/config中,不下载子模块的内容 •
  3. Git submodule uodate从远程仓库中拉取子模块的内容,并将其更新到.gitmodules文件中指定的提交 (--recursive递归更新所有子模块 --remote从子模块的远程仓库中拉取最新更改) •
  4. git submodule add <repo-url> [<path>] :<repo-url> 是子模块的仓库地址,<path> 是子模块在主仓库中的路径(可选,如果不指定,默认使用子模块仓库的名称作为路径)。 •
  5. git submodule deinit [<path>]: 将子模块从 .git/config 文件中移除,并删除子模块目录中的文件。 •
  6. git rm [<path>]:将子模块的引用从主仓库中删除,并提交更改 •
  7. git submodule 列出所有子模块 •
  8. git submodule status 查看模块当前状态(提交hash、路径、是否有未提交)

2. git config查看和设置配置信息

3. git diff <branch1> <branch2>比较分支差异**

4. git stash

作用临时存储未提交的代码改动(包括工作目录和暂存区的修改),便于切换分支或处理紧急任务后恢复工作。

适用场景

• 代码改到一半需切换分支修复 Bug(未完成代码不想提交)

• 拉取远程代码(git pull)前,避免未提交改动引发冲突

• 多任务中断时保存当前进度

# 存储当前改动(默认名称为stash@{0}) git stash

# 存储并添加备注 git stash save "备注内容"

# 查看所有存储记录 git stash list

# 恢复最近一次存储的改动(保留存储记录) git stash apply

# 恢复最近一次存储的改动(并删除该记录) git stash pop

# 丢弃指定存储(如stash@{1}) git stash drop stash@{1}

# 清空所有存储 git stash clear

5. git revert

作用安全撤销某次提交 ,通过生成一个新的"反向提交"抵消原提交的改动,保留完整历史记录。 适用场景

• 撤销已推送到远程仓库的提交(避免重写历史)13

• 协作开发中回退错误代码(不影响他人分支)

核心特点

• 🔄 不破坏提交历史,适合公共分支

• ⚙️ 可能需手动解决冲突(新旧代码冲突时)

• ❌ 与 git reset 的区别:reset 直接删除提交(危险操作),revert 是安全撤销1

# 撤销某次提交(生成新提交抵消改动) • git revert <commit-hash> •

# 撤销最近一次提交 • git revert HEAD

Linux命令

1. 查看信息

查看当前登录用户whoami /who / id 查看所有用户:cat /etc/passwd | cut -d: -f1

2. 系统服务

以dns为例:(具体命令还和系统和版本有关,这里是ubuntu18.04) sudo systemctl restart systemd-resolved.service sudo service systemd-resolved restart sudo /etc/init.d/ systemd-resolved restart 查找dns服务进程:ps -ef | grep system-resolved 查看状态用status

3. Linux中通过域名查找ip

Nslookup <域名> Dig/host/ping/fping/tracert Ping/ nslookup /tracert windows也可用 **网络通信

4. Linux网络通信------字节序转换----htonl()、htons()、ntohl()、ntohs()

** 头文件:#include <arpa/inet.h>

原型:uint32_t htonl(uint32_t hostlong)

uint16_t htons(uint16_t hostlong)

uint16_t ntohs(uint16_t hostlong)

uint32_t ntohs(uint32_t hostlong)

注意缩写的扩展名就知道函数意义了: h表示host------主机 n表示net------网络 l表示long------unsigned long s表示unsigned short 几个函数功能都是网络和主机字节顺序的转换 (主机字节顺序可能是大端顺序或者小端顺序(这个要看编译器的设置,还有自己是用的C还是Java还是其他的语言,其各自都是不尽相同),但是网络字节顺序一定是大端顺序。

5. ipv4/mac地址字符串转换------inet_aton inet_ntoa

// 点分十进制转网络字节序(eg:192.168.0.1)

int inet_aton(const char *cp, struct in_addr *inp); (返回值为0失败,in_addr *inp为出参)

in_addr_t inet_addr(const char *cp); (直接返回一个地址) // 网络字节序转点分十进制(返回一个地址字符串)

char *inet_ntoa(struct in_addr in); // mac地址字符串和字节之间的转换

头文件:#include <netinet/ether.h>

Ether_aton ether_ntoa ether_aton_r ether_ntoa_r

6. Linux------套接字

头文件:#include <sys.types.h> #include <sys/socket.h>

这里相关的套接字直接看原型就比较明白:

// 创建套接字 int socket(int domain, int type, int protocol);

// 绑定地址到套接字 int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

// 监听连接 int listen(int sockfd, int backlog);

// 接受连接 int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

// 发起连接 int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

// 关闭连接 int close(int fd);

数据流

// TCP 数据流 ssize_t send(int sockfd, const void *buf, size_t len, int flags); ssize_t recv(int sockfd, void *buf, size_t len, int flags);

// UDP 数据包 ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen); ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);

7. 网络信息查询

头文件:#include <netdb.h> 这类函数的原型很明显的表明了使用方法

// 获取主机信息 struct hostent *gethostbyname(const char *name); struct hostent *gethostbyaddr(const void *addr, size_t len, int type);

// 获取服务信息 struct servent *getservbyname(const char *name, const char *proto); struct servent *getservbyport(int port, const char *proto);

// 地址和服务名解析 int getaddrinfo(const char *hostname, const char *service, const struct addrinfo *hints, struct addrinfo **result);

int getnameinfo(const struct sockaddr *addr, socklen_t addrlen, char *host, socklen_t hostlen, char *serv, socklen_t servlen, int flags);

8. linux---route/ip route命令 Route:

Route [选项] [操作] [目标] [参数]

Route -h 可查看使用手册

常用:

route -n 查看路由表

常用选项

-n # 以数字形式显示地址(不解析主机名)

-v # 显示详细操作信息

-e # 使用 netstat 格式显示路由表

-A family # 指定地址族(如 inet 或 inet6)

IP Route: 新工具功能更强大: ip route help 打印出使用手册

使用格式: ip route {list| flush}

SELECTOR 常用:ip (-6) route -n 查看路由 ip r ip route ip route show ip route list 均可查看路由

8**. brctl命令**

Brctl管理以太网桥 启动:

modprobe bridge ## 加载 bridge 模块

echo "1">/proc/sys/net/ipv4/ip_forward ## 开启转发,多个网卡之间进行数据交互

Brctl --help输出使用手册(这个手册非常清晰)

常用:brctl show 展示当前的网桥配置

Linux函数

1. memcmp/memcpy函数

头文件:#include <string.h>

直接比较两个内存块之间的字节内容

声明:int memcmp(const void *str1, const void *str2, size_t n)

• 如果返回值 < 0,则表示 str1 小于 str2。

• 如果返回值 > 0,则表示 str1 大于 str2。

• 如果返回值 = 0,则表示 str1 等于 str2。

常用于字节内容的比较,参数n指明了需要比较的字节长度

类似的C 库函数 **void *memcpy(void str1, const void str2, size_t n) 从存储区 str2 复制 n 个字节到存储区 str1

2. strdup函数

头文件:#include <string.h> char *strdup(const char *s);

复制一个内存空间完全独立的字符串副本,返回指针,使用后最后一定得手动释放指针

下面是规范用法:

cpp 复制代码
#include <syslib.h>

#include<string.h>

int main(void) {    

    char *src ="This is the jibo";    

    char *dest;    

    dest = strdup(s);    

    printf("the dest %s\n",dest);        

    free(dest); // 切记释放空间    

    return 0;

}  

3. strtok/strtok_r函数分割遍历

头文件: #include <string.h>

常用于分割约定俗称的字符串并处理:

声明:char *strtok(char *str, const char *delim)

第一次使用str传需要分割的delim指针(传字符串是多个分割符比如",;"是分割逗号或分号),

后面传NULL;

strtok_r(): **char *strtok_r(char *str, const char delim, char saveptr);

strtok_r() 是 strtok() 的可重入版本,它允许你在多线程环境中安全地使用 使用规范:(saveptr是一个char的指针,保存分割状态)

4. realloc函数

realloc的安全使用方式

(realloc行为) :

如果原有地址后有足够空间,直接追加,指针地址不变 :

如果没有足够空间,新申请一份,copy原来内容,释放原来指针空间,然后返回新的指针地址 由此安全的做法为:

cpp 复制代码
#include <stdio.h>
int main()
{
int*ptr = malloc(100);
if(ptr != NULL)
{
//业务处理
}
else
{
exit(EXIT_FAILURE); 
}
//扩展容量
//代码1
ptr = realloc(ptr, 1000);//这样可以吗?(如果申请失败会如何?)
//代码2
int*p = NULL;
p = realloc(ptr, 1000);
if(p != NULL)
{
ptr = p;
}
//业务处理
free(ptr);
return 0;
}

Uboot

switch init setenv ipaddr <ipv4> setenv serverip <ipv4> tftpboot ER8411v1_un_1.3.0_20250114-rel36677_nandflash_noecc.bin nand erase.chip nand write {loadaddr} 0 {filesize} reset 史上最全的Uboot常用命令汇总(超全面!超详细!)收藏这一篇就够了_uboat控制台指令大全-CSDN博客

VPP

www.meemx.com vpp使用详解

MakeFile

  1. 三要素:目标、依赖、命令

  2. 命令以tab开头

  3. 默认执行规则为第一条,其他顺序无关性

  4. make使用文件的创建和修改时间来判断是否应该更新一个目标文件;makefile支持增量编译

  5. 伪目标:clean、install......

  6. 一条规则可以有多条命令

  7. / 分割长命令到不同行 ; 分割不同命令 (;分割后会当成不同的命令,make的每条命令有一个独立的shell空间)

  8. 一种执行多条命令的语法是用&&,它的好处是当某条命令失败时,后续命令不会继续执行

  9. @ 可以指定某一条命令不回显到输出

  10. 有些时候,我们想忽略错误,继续执行后续命令,可以在需要忽略错误的命令前加上-

代码优化和性能提升

  1. 常见的代码优化思路 18 极致优化(上):如何实现高性能的 C 程序? - 极客时间文档 :高速缓存(局部性原理)、内联函数(预处理逻辑)、restrict关键字(编译成汇编时由于确定数据不会被其他指针更改,可以减少访存次数)、减少不必要的内存引用(比如累乘运算使用register定义一个寄存器局部变量不用多次访问内存) 19 极致优化(下):如何实现高性能的 C 程序? - 极客时间文档 :循环展开(本质上是利用提高CPU指令流水线占用率)、条件传送指令优化(三元运算符代替ifelse)、利用编译器的优化等级、迭代代替递归 Debug

  2. 为什么同时编译两个大型项目会导致虚拟机崩溃,最终导致编译任务失败? 场景:有一个buildroot框架的项目,复制一份到另一个目录,其中两份代码进行不同的配置,命令行同时启动编译,最终导致崩溃 原因推测: • CPU资源耗尽 Buildroot项目编译会尝试在系统上启动N个并行任务,2个项目同时编译导致系统上同时运行2N高负载gcc进程;超越了虚拟机CPU核心处理和能力,调度器不断切换上下文尝试分配时间片------系统几乎100%时间用于切换进程,而不真正编译任务,导致系统完全卡顿失去响应,这被称为"Trashing"(系统颠簸) • 内存RAM耗尽 2N个gcc进程的内存需求可能超过虚拟机分配的上限;物理内存耗尽时,操作系统会开始使用交换分区;Swap是硬盘上的一块空间,用来存放不常用的内存页;硬盘读写速度比内存慢几个量级,频繁使用swap系统性能断崖式下跌------系统完全卡死,CPU不再进行编译任务,而是等待缓慢的硬盘读写,如果swap空间被填满,操作系统内核的OOM(Out of Memory)Killer触发强制随机终止进程释放内存,可能导致编译失败 • 磁盘I/O瓶颈 若CPU和内存都满足了上述的资源要求,磁盘io也是瓶颈,两个buildroot项目都快速读写万级文件,磁头需要来回移动,SSD的并发通道也会占满------所有进程都等待磁盘操作,编译速度很慢,系统卡顿 • 潜在的依赖冲突 若所有的性能和资源都满足,两个buildroot编译时可能下载相同软件包到同一临时目录,导致覆盖或损坏;同时编译和安装同一个基础依赖库zlib或openssl等导致文件锁冲突或安装文件错乱------各种不可预知的错误 解决方案:

  3. 串行编译

  4. 限制并行度:eg:8核虚拟机------两个项目每个项目 make -j4

  5. 使用不同的机器

  6. 硬件升级

  7. segmentation fault (SIGSEGV) 问题 该问题就是内存泄漏/溢出:当一个进程执行一个无效的内存引用或发生断错误时,触发sigsegv信号------内核默认动作终止该进程 常见情形------使用非法指针 解决:gdb查看core文件,Linux默认会为sigsegv故障生成一个core文件,该文件记录了出错时的堆栈信息,通过gdb可以快速追踪 Gdb查看命令bt和where Core文件一般会在程序执行的当前目录生成,若无法生成:

  8. linux内核限制,ulimit -c <number>设置解除限制(ulimit -a查看限制

  9. 当前程序没有当前目录的写权限------chown chgrp等命令赋权即可

Snap

Snap 是 Canonical 开发的跨发行版 Linux 包管理系统,核心特点包括:

  1. 沙盒化运行:每个应用及依赖封装在独立容器中,避免系统污染1
  2. 自动更新:默认后台静默更新(可配置关闭)
  3. 版本管理:支持多版本共存与回滚(通过 snap revert)1
  4. 跨平台兼容:适用于 Ubuntu/Debian/Fedora 等主流发行版 数学表示沙盒隔离原理: Appsnap =(Binaries+Dependencies+Config)⊗Ssandbox

其中 Ssandbox 为安全隔离层。

删除:sudo snap remove <package_name>(会保留~/snap/<package_name>位置的用户数据文件)

彻底卸载:sudo snap remove --purge <package_name>

多版本清理: snap list --all | grep <package_name>

查看所有版本[^1] sudo snap remove --revision=<rev_num> <package_name>

删除指定版本

操作命令示例作用

查看已安装包snap list

显示基础信息查看所有版本snap list --all显示包括非活跃版本

回滚旧版sudo snap revert <package>

清理磁盘空间sudo rm -rf /var/lib/snapd/cache/*

删除更新缓存(需手动执行)

安装snap install <package_name> (--classic)

默认开启自动更新机制:snap get system refresh.timer # 查看自动刷新频率

相关推荐
egoist20233 小时前
[linux仓库]深入解析Linux动态链接与动态库加载:理解背后的原理与技巧
linux·服务器·编辑器·动态库·got
moxiaoran57533 小时前
linux普通账号管理
linux·运维·服务器
chilavert3183 小时前
技术演进中的开发沉思-119Linux命令篇:系统设置命令(上)
linux·运维·服务器
半桔3 小时前
【网络编程】深入 HTTP:从报文交互到服务构建,洞悉核心机制
linux·网络·c++·网络协议·http·交互
小冷Hello3 小时前
【stm32】CAN分析仪+TJA1050+单片机通信不上,波特率等等都没问题,usb扩展坞的供电问题,绝了
stm32·单片机·嵌入式硬件
飘忽不定的bug4 小时前
RK3568移植RM500U-PCIE模块
linux·pcie·rm500g
RFID舜识物联网5 小时前
NFC技术如何破解电子制造领域的效率瓶颈与追溯难题
大数据·人工智能·嵌入式硬件·物联网·安全·制造
特立独行的猫a6 小时前
C 语言各种指针详解
java·c语言·开发语言
wheeldown6 小时前
【Linux&&vs code】Xshell远程配置到VS Code环境配置指南
linux·运维·服务器