
C语言
文章平均质量分 72
梅山剑客
2023年6月毕业,7月入职的嵌软攻城狮
展开
-
内存泄漏导致Hard_Fault问题记录
如果不这样做,在重复分配而不释放的情况下,会导致内存使用不断增加,最终可能耗尽可用内存,导致内存泄漏或其他内存相关错误。在LwIP中,每当通过pbuf_alloc成功分配了一个pbuf后,就应该在这个pbuf不再需要时使用pbuf_free来释放它,以避免内存泄漏。在函数Ethernet_sendPack中,使用了pbuf_alloc来分配一个新的pbuf结构体,如果在主循环中重复调用这个函数,并且每次调用都成功分配了内存,但没有在发送数据后释放这些内存,这将会导致内存泄漏。实际是出现内存泄漏的问题。原创 2024-03-27 17:02:10 · 552 阅读 · 1 评论 -
数据结构—环形缓冲区
环形数组(Circular Array)是一种特殊类型的数组,其元素在内存中首尾相接,形成一个环形。由于环形数组的元素在内存中是首尾相接的,因此不需要为数组的头部和尾部留出额外的空间。易于实现动态扩展:当需要增加更多元素时,环形数组可以通过简单地扩展现有数组的大小来实现动态扩展,而无需重新分配和复制原有数据。由于环形数组的特性,当索引超出数组的界限时,会自动回到数组的开头或结尾,避免了常规数组越界访问导致的错误。环形数组保持了数据的连续性,这有助于提高数据访问的局部性,从而优化CPU缓存的性能。原创 2024-01-03 13:55:52 · 829 阅读 · 0 评论 -
C语言进阶C++知识点补充(二)
介绍C语言进阶到C++学习的新内容:数据抽象、数据封装、抽象类、异常处理、模板原创 2022-07-21 00:15:00 · 527 阅读 · 4 评论 -
C语言进阶C++知识点补充(一)
从C语言进阶到C++扩展知识点简略补充原创 2022-07-20 09:36:24 · 463 阅读 · 0 评论 -
C语言项目练习—学生管理系统
通过C语言写一个简单的学生信息管理系统,增强对C语言一些重要知识点的认识。一、创建学生节点使用结构体可以很好的把每一个学生的信息都放在一个特点的位置,方便遍历每一个学生的信息。#include<stdio.h>//创建一个节点typedef struct _STU{ char arrStunum[10];//学生学号 char arrStuname[10];//学生姓名 int iStuSorce;//学生分数 struct _STU*pNext;//指向下一个节点指针}原创 2022-04-23 22:28:35 · 554 阅读 · 0 评论 -
DAC7512—软件模拟SPI实现与DAC7512通信
今天使用DAC751实现输出0-5V电压,效果良好精度很高。DAC7512时序图。需要注意的是要给出5V参考电压,实现DAC5V正常输出。根据时序图,在开启写入数据之前,片选信号拉高再拉低,然后时钟线和数据线同步写入16个数据,之后片选信号线拉高,完成16位数据写入。软件代码引脚配置初始化引脚配置为3个推挽输出即可。#define SOFT_CLK_1 HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_SET)#define SOFT_CLK_0 HA原创 2022-04-12 23:05:43 · 2327 阅读 · 1 评论 -
Linux网络通信——TCP通信流程
1、TCP通信流程TCP是一个面向连接的,安全的,流式传输协议,这个协议是一个传输层协议。面向连接:是一个双向连接,通过三次握手完成,断开连接需要通过四次挥手完成。安全:tcp通信过程中,会对发送的每一数据包都会进行校验, 如果发现数据丢失, 会自动重传流式传输:发送端和接收端处理数据的速度,数据的量都可以不一致4.1 服务器端通信流程创建用于监听的套接字, 这个套接字是一个文件描述符int lfd = socket();将得到的监听的文件描述符和本地的IP 端口进行绑定bind()原创 2022-04-09 22:49:56 · 6993 阅读 · 2 评论 -
Linux网络编程——socket套接字
socket编程Linux系统采用了Socket套接字,因此,Socket接口就被广泛使用,到现在已经成为事实上的标准。与套接字相关的函数被包含在头文件sys/socket.h中。网络通信的主体主要分为两部分:客户端和服务器端。在客户端和服务器通信的时候需要频繁提到三个概念:IP、端口、通信数据,下面介绍一下需要注意的一些细节问题。字节序在各种计算机体系结构中,对于字节、字等的存储机制有所不同,因而引发了计算机通信领域中一个很重要的问题,即通信双方交流的信息单元(比特、字节、字、双字等等)应该以什么原创 2022-04-08 22:42:44 · 922 阅读 · 0 评论 -
Linux线程间同步(三)
6. 信号量6.1 信号量函数信号量用在多线程多任务同步的,一个线程完成了某一个动作就通过信号量告诉别的线程,别的线程再进行某些动作。信号量不一定是锁定某一个资源,而是流程上的概念,比如:有A,B两个线程,B线程要等A线程完成某一任务以后再进行自己下面的步骤,这个任务并不一定是锁定某一资源,还可以是进行一些计算或者数据处理之类。信号量(信号灯)与互斥锁和条件变量的主要不同在于”灯”的概念,灯亮则意味着资源可用,灯灭则意味着不可用。信号量主要阻塞线程, 不能完全保证线程安全,如果要保证线程安全, 需要信原创 2022-04-06 17:03:05 · 394 阅读 · 0 评论 -
Linux线程间同步(二)
4. 读写锁4.1 读写锁函数读写锁是互斥锁的升级版, 在做读操作的时候可以提高程序的执行效率,如果所有的线程都是做读操作, 那么读是并行的,但是使用互斥锁,读操作也是串行的。读写锁是一把锁,锁的类型为pthread_rwlock_t,有了类型之后就可以创建一把互斥锁了:pthread_rwlock_t rwlock;之所以称其为读写锁,是因为这把锁既可以锁定读操作,也可以锁定写操作。为了方便理解,可以大致认为在这把锁中记录了这些信息:锁的状态: 锁定/打开锁定的是什么操作: 读操作/写操原创 2022-04-05 09:26:41 · 599 阅读 · 0 评论 -
linux线程间同步(一)
1. 线程同步概念假设有4个线程A、B、C、D,当前一个线程A对内存中的共享资源进行访问的时候,其他线程B, C, D都不可以对这块内存进行操作,直到线程A对这块内存访问完毕为止,B,C,D中的一个才能访问这块内存,剩余的两个需要继续阻塞等待,以此类推,直至所有的线程都对这块内存操作完毕。 线程对内存的这种访问方式就称之为线程同步,通过对概念的介绍,我们可以了解到所谓的同步并不是多个线程同时对内存进行访问,而是按照先后顺序依次进行的。1.1 为什么要同步线程需要分时复用CPU时间片,并且如果测试程序中原创 2022-04-03 04:30:00 · 1375 阅读 · 0 评论 -
Linux高级编程——多线程
1、线程概念线程是轻量级的进程,在Linux环境下线程的本质仍是进程。操作系统会以进程为单位,分配系统资源,可以这样理解,进程是资源分配的最小单位,线程是操作系统调度执行的最小单位。1.1 线程与进程的区别进程有自己独立的地址空间, 多个线程共用同一个地址空间1、线程更加节省系统资源, 效率不仅可以保持的, 而且能够更高2、在一个地址空间中多个线程独享: 每个线程都有属于自己的栈区, 寄存器(内核中管理的)3、在一个地址空间中多个线程共享: 代码段, 堆区, 全局数据区, 打开的文件(文件描述符原创 2022-04-02 16:31:25 · 1885 阅读 · 0 评论 -
DAC8551编程原理以及实现方式
因项目需要通过0-5V电压控制比例阀,后通过芯片选型,选取DAC8551作为电压输出芯片,输出线性电压控制比例比例阀。资料来源于:德州仪器TI—DAC8551数据手册DAC8551介绍DAC8551 是一款小型、低功耗、电压输出、16 位数模转换器 (DAC)。 它是单调的,提供良好的线性度。 DAC8551 使用一个通用的 3 线串行接口,该接口以高达 30 MHz 的时钟速率运行,并与标准 SPI、QSPI、Microwire和数字信号处理器 (DSP) 接口兼容。DAC8551 需要外部参考电原创 2022-03-31 15:52:54 · 4311 阅读 · 0 评论 -
Linux信息处理机制——信号
1. 信号概述Linux中的信号是一种消息处理机制, 它本质上是一个整数,不同的信号对应不同的值,由于信号的结构简单所以天生不能携带很大的信息量,但是信号在系统中的优先级是非常高的。在Linux中的很多常规操作中都会有相关的信号产生,先从我们最熟悉的场景说起:通过键盘操作产生了信号:用户按下Ctrl-C,这个键盘输入产生一个硬件中断,使用这个快捷键会产生信号, 这个信号会杀死对应的某个进程通过shell命令产生了信号:通过kill命令终止某一个进程,kill -9 进程PID通过函数调用产生了信号转载 2022-03-31 04:30:00 · 1959 阅读 · 0 评论 -
linux进程——守护进程
信号概述Linux 中的信号是一种消息处理机制,它本质上是一个整数,不同的信号对应不同的值,由于信号的结构简单所以天生不能携带很大的信息量,但是信号在系统中的优先级是非常高的。在 Linux 中的很多常规操作中都会有相关的信号产生,先从我们最熟悉的场景说起:通过键盘操作产生了信号:用户按下 Ctrl-C,这个键盘输入产生一个硬件中断,使用这个快捷键会产生信号,这个信号会杀死对应的某个进程通过shell命令产生了信号:通过 kill 命令终止某一个进程,kill -9 进程PID通过函数调用产生.转载 2022-03-30 17:27:41 · 2777 阅读 · 0 评论 -
Linux多线程高并发网络通信服务器与客户端实现
学习本节内容需要掌握网络socket编程基础,多线程编程基础。下面来看在没有多线程情况下,使用单线程实现socket编程的步骤:1、单线程服务器端单线程实现网络通信服务器代码实现:服务器端实现流程:1、socket创建socket套接字文件描述符2、bind绑定ip地址和端口号3、listen监听是否有客户端与服务器端连接4、accept并且等待客户端连接5、read/recv、write/send与客户端通信6、close关闭套接字文件描述符#include <stdio.h&原创 2022-03-29 10:10:52 · 2078 阅读 · 0 评论 -
Linux进程间通信—共享内存
共享内存不同于内存映射区,它不属于任何进程,并且不受进程生命周期的影响。通过调用 Linux 提供的系统函数就可得到这块共享内存。使用之前需要让进程和共享内存进行关联,得到共享内存的起始地址之后就可以直接进行读写操作了,进程也可以和这块共享内存解除关联,解除关联之后就不能操作这块共享内存了。在所有进程间通信的方式中共享内存的效率是最高的。共享内存操作默认不阻塞,如果多个进程同时读写共享内存,可能出现数据混乱,共享内存需要借助其他机制来保证进程间的数据同步,比如:信号量,共享内存内部没有提供这种机制。1转载 2022-03-29 04:00:00 · 1943 阅读 · 0 评论 -
Linux进程间通信—内存映射
1. 创建内存映射区如果想要实现进程间通信,可以通过函数创建一块内存映射区,和管道不同的是管道对应的内存空间在内核中,而内存映射区对应的内存空间在进程的用户区(用于加载动态库的那个区域),也就是说进程间通信使用的内存映射区不是一块,而是在每个进程内部都有一块。由于每个进程的地址空间是独立的,各个进程之间也不能直接访问对方的内存映射区,需要通信的进程需要将各自的内存映射区和同一个磁盘文件进行映射,这样进程之间就可以通过磁盘文件这个唯一的桥梁完成数据的交互了。如上图所示:磁盘文件数据可以完全加载到进程的转载 2022-03-28 03:45:00 · 890 阅读 · 0 评论 -
Linux进程间通信—管道
1. 管道管道的是进程间通信(IPC - InterProcess Communication)的一种方式,管道的本质其实就是内核中的一块内存 (或者叫内核缓冲区),这块缓冲区中的数据存储在一个环形队列中,因为管道在内核里边,因此我们不能直接对其进行任何操作。因为管道数据是通过队列来维护的,我们先来分析一个管道中数据的特点:管道对应的内核缓冲区大小是固定的,默认为 4k(也就是队列最大能存储 4k 数据)管道分为两部分:读端和写端(队列的两端),数据从写端进入管道,从读端流出管道。管道中的数据只转载 2022-03-27 03:45:00 · 1007 阅读 · 1 评论 -
Linux进程控制(详解)
内容来自:爱编程的大丙1. 进程概述从严格意义上来讲,程序和进程是两个不同的概念,他们的状态,占用的系统资源都是不同的。程序:就是磁盘上的可执行文件, 并且只占用磁盘上的空间,是一个静态的概念。进程:被执行之后的程序叫做进程,不占用磁盘空间,需要消耗系统的内存,CPU资源,每个运行的进程的都对应一个属于自己的虚拟地址空间,这是一个动态的概念。1.1 并行和并发CPU时间片CPU在某个时间点只能处理一个任务,但是操作系统都支持多任务的,那么在计算机CPU只有一个和的情况下是怎么完成多任务处理的呢转载 2022-03-26 03:30:00 · 5101 阅读 · 1 评论 -
Linux文件描述符复制与重定向
在 Linux 中只要调用 open() 函数就可以给被操作的文件分配一个文件描述符,除了使用这种方式 Linux 系统还提供了一些其他的 API 用于文件描述符的分配,相关函数有三个:dup, dup2, fcntl。转载 2022-03-25 03:15:00 · 3251 阅读 · 0 评论 -
Linux虚拟地址空间与文件描述符
本文主要介绍linux操作系统中的虚拟地址空间和文件描述符,通过图解的形式形象解释了其内容。转载 2022-03-24 03:00:00 · 699 阅读 · 0 评论 -
数据结构—使用双向链表实现栈和队列
本节介绍栈和队列的实现,栈的实现,队列的实现。原创 2022-03-21 17:40:00 · 1406 阅读 · 0 评论 -
有限状态机的编程原理及编程实例
有限状态机有限状态机解决的问题是复杂流程。简单流程:自然流程是结构化的,按照人类顺序思维解决的问题。复杂流程:自然流程不是结构化的,比如先前的MultiButton。具体实例在linux操作系统下实现终端设备界面相互切换。实现读取fd1的数据写入的fd2中,读取fd2的数据写入到fd1当中。状态机简单示意图如下所示:实验工程源码#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#i原创 2022-03-19 10:07:42 · 1555 阅读 · 0 评论 -
LinuxC应用开发学习笔记(十六)—流媒体广播-终章
基于IPV4的流媒体广播原创 2022-01-17 17:34:37 · 2714 阅读 · 7 评论 -
LinuxC应用开发学习笔记(一)--C语言
LinuxC应用开发学习笔记(一)平台介绍:linux Ubuntu 16.04C编译过程:C源文件–预处理–编译–汇编–连接–可执行文件man gcc查看gcc的帮助手册gcc -E hello.c //后缀必须为.c文件gcc -E hello.c > hello.i //重定向为i类型文件gcc -S hello.i //不需要指定,会自动生成hello.s文件gcc -c hello.s //链接成 -o文件gcc hello.o -o hello ./hello原创 2021-11-22 22:21:31 · 2493 阅读 · 0 评论 -
LinuxC应用开发学习笔记(十五)— Socket套接字
网络套接字socket基本功:两门语言,一门脚本语言。使用拿来主义先实现功能。讨论:跨主机的传输需要注意的问题。1、字节序问题:大端存储:低地址处放高字节小端存储:X86 低地址处放低字节0x00 00 00 05大 05 00 00 00小 00 00 00 05区分主机字节序和网络字节序:主机字节序:host网络字节序:network解决办法:to _s: htons ,htonl, ntohs,ntohl2 对齐:struct{int i;float;char ch;原创 2022-01-15 08:37:44 · 652 阅读 · 2 评论 -
LinuxC应用开发学习笔记(十四)—管道算法和进程间通信
管道算法和进程间通信管道的实现#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/wait.h>#define BUFSIZE 1024 int main(){ int pd[2],len = 0; __pid_t pid; char buf[BUFSIZE]; if(pipe(pd)<0) {原创 2022-01-12 22:22:07 · 488 阅读 · 0 评论 -
LinuxC应用开发学习笔记(十三)—高级I\O
高级I\O非阻塞IO – 阻塞 IO补充:有限状态机编程有限状态机#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <errno.h>#define TTY1 "/dev/tty11"#define原创 2022-01-10 21:07:21 · 515 阅读 · 2 评论 -
LinuxC应用开发学习笔记(十二)—并发(线程)
线程1、线程的概念一个正在运行的函数线程间通信会比进程间通信简单点。posix线程是一套标准,而不是实现。openmp线程线程标识:pthread_t (理解为一个整型数)ps下面的 - - 是线程。进程来消耗当前的进程号的。进程就是容器用来承载线程。pthread_equal();//比较线程标识pthread_self();//返回当前线程标识2、线程的创建pthread_create();线程的调度取决于调度器调度。#include <stdio.h>#inc原创 2022-01-06 22:29:34 · 948 阅读 · 0 评论 -
LinuxC应用开发学习笔记(十一)—并发(信号)
信号同步异步:什么时候到来不知道,产生什么结果不知道处理:查询法、通知法一、信号(初步异步、强烈异步)1、信号的概念信号是软件中断。信号的响应依赖于中断。2、signal();void signal(int signum,void (*func)(int )))(int);信号会打断阻塞的系统调用。如:open 和 read#include <stdio.h>#include <stdlib.h>#include <signal.h>#i原创 2022-01-05 22:10:20 · 553 阅读 · 1 评论 -
LinuxC应用开发学习笔记(十)—多进程
进程进程基本知识已经进入多进程阶段。1、进程标识符 pid类型 pid_t命令 ps进程号是顺次向下使用getpid();getppid();2、进程的产生(1)fork();注意理解关键字:duplicating 意味着拷贝、克隆、一模一样等含义fork后父子进程的区别:fork的返回值不一样,pid不同,ppid不同,未决信号和文件锁不继承,资源利用量归0.init进程:1号,是所有进程的祖先进程。(2)vfork();3、进程的消亡及释放资源4、exec函数族5、用户原创 2021-12-30 21:10:04 · 587 阅读 · 0 评论 -
LinuxC应用开发学习笔记(九)——文件系统
主要介绍linux 文件系统相关内容,包括文件属性,文件访问权限,文件信息等,并且举例多种示例代码解释文件属性信息。原创 2021-12-28 23:09:30 · 864 阅读 · 3 评论 -
LinuxC应用开发学习笔记(八)—系统调用I/O
UNIX环境高级编程(APUE)文件系统四、六、七章I/03-5章、14章文件I/O标准I/O并发信号10章节多进程并发多线程并发10-11章节IPC:进程间通信8章节 进程基础(涉及到多进程)13章 守护进程15-16章注意事项:1、弃用root用户2、重构代码3、课堂重点:项目,课堂代码,面试题,实验性题目,推荐书籍课后题I/O:input & output,是一切实现的基础标准io:stdio 依赖于sysio系统调用io:sysio(文件IO)优先原创 2021-12-21 22:42:54 · 1056 阅读 · 0 评论 -
LinuxC应用开发学习笔记(七)--数据结构
栈和队列的应用–求中算法主函数#include <stdio.h>#include <stdlib.h>#include "sqstack.h"#include "queue.h"#define NR_BALL 27static int check(queue *qu){ int i = (qu->head+1)%MAXSIZE; while (i!=qu->tail) { if(qu->data[i]&g原创 2021-12-16 22:13:52 · 757 阅读 · 0 评论 -
LinuxC应用开发学习笔记(六)--数据结构
栈和队列的应用主函数(不完整)#include <stdio.h>#include <stdlib.h>#include "sqstack.h"static void compture(sqstack *snum,datatype* op){ datatype n1,n2,n; st_pop(snum,&n2); st_pop(snum,&n1); switch (*op) { case '+':原创 2021-12-12 22:47:14 · 923 阅读 · 0 评论 -
LinuxC应用开发学习笔记(五)--数据结构
6、双向链表双向链表的头文件#ifndef LLIST_H_#define LLIST_H_#define LLIST_FORWARD 1#define LLIST_BACKWARD 2typedef void llist_op(const void *);typedef int llist_cmp(const void *,const void *);struct llist_node_st{ struct llist_node_st *prev; stru原创 2021-12-12 20:42:14 · 827 阅读 · 0 评论 -
LinuxC应用开发学习笔记(四)--数据结构
数据结构1、线性表线性表的头文件#ifndef SQLIST_H__#define SQLIST_H__#define DATASIZE 1024 typedef int datatype;typedef struct node_st{ datatype data[DATASIZE]; int last; /* data */}sqlist;sqlist *sqlist_create();void sqlist_creat1(sqlist **);i原创 2021-12-08 22:50:14 · 1124 阅读 · 0 评论 -
LinuxC应用开发学习笔记(三)--C语言
函数1、函数的定义数据类型 函数名 (【数据类型 变量名 】)int i; 在main函数中,argc表示传递多少个参数,argv 表示传递的列表 ,字符指针数组的首地址 printf("hello!\n");//一个 进程的返回状态是给他的父进程看的, printf("argc = %d!",argc); for(i=0;i<=argc;i++) { puts(argv[i]); } return 0;//结束当前函数 2、函数的传参值传递:不会改变互换的参数原创 2021-11-26 22:09:08 · 1123 阅读 · 1 评论 -
LinuxC应用开发学习笔记(二)--C语言
P30 数组数组:构造类型之一,连续存放int arr[M] = {1,2,3}; printf("%d\n",sizeof(arr)); printf("arr = %p\n",arr); //arr是个常量 不能无条件出现在等号左边。 for(int i=0;i<M;i++) { printf("%p-->%d\n",&arr[i],arr[i]); } int arr[] = {1,2,3,4,5,6};printf("%d\n",sizeof(arr)原创 2021-11-23 21:55:57 · 3719 阅读 · 0 评论