当前位置: 首页 > article >正文

物联网面试必过要点

要是能熟记以下知识点再加上自身的项目经验过个面试问题不大。指针定义一个指向指针的的指针它指向的指针是指向一个整型数 int **a; 一个有10个指针的数组该指针是指向一个整型数的 int *a[10]; 一个指向有10个整型数数组的指针 int (*a)[10] 一个指向函数的指针函数指针该函数有一个整型参数并返回一个整型数 int *a)( int ){} 一个返回指针类型的函数。 int* a(int){} 一个有10个指针的数组该指针指向一个函数该函数有一个整型参数并返回一个整型数 int (* a[10])( int ) //类似这种定义应该采用分解法来做。 先定义单个函数指针 int (*a)(int)然后再是有10个指针的数组 int (*a[10])(int)关键字static的作用是什么1)在函数体内一个被声明为静态的变量在这一函数被调用过程中维持其值不变该变量存放在静态变量区。2) 在模块内但在函数体外一个被声明为静态的变量可以被模块内所用函数访问但不能被模块外其它函数访问。它是一个本地的全局变量。3) 在模块内一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是这个函数被限制在声明它的模块的本地范围内使用关键字constconst int a; 常量a int const a; 常量a const int *a; 指针指向的内容不可以被修改 但是指针指向的地址可以修改。 int * const a; 指针指向的地方不可以被改但是指向的地址的内容可以修改。 int const * const a; 指针指向地址的内容和指针指向的地址都不可以修改。第一个设置a的bit 3第二个清除a 的bit 3a | 1 3 a ~(1 3) 或BIC a,a,#0x3有符号数与无符号数下面的代码输出是什么为什么void foo(void) { unsigned int a 6; int b -20; (ab 6)puts( 6) : puts( 6); }大于6. 有符号数转换为无符号数。无符号数不存在正负之分所有位都用来表示数的本身。有符号数最高位用来表示数的正负最高位为1则表示负数最高位为0则表示正数。1. 无符号数转换为有符号数看无符号数的最高位是否为1如果不为1即为0则有符号数就直接等于无符号数2.如果无符号数的最高位为1则将无符号数取补码得到的数就是有符号数。3..有符号数转换为无符号数 看有符号数的最高位是否为1如果不为1即为0则无符号数就直接等于有符号数4.如果有符号数的最高位为1则将有符号数取补码得到的数就是无符号数所以6 - 20 -14因为结果作为一个无符号数已经溢出了所以又加了65536结果变成一个正数了,为65522-5对应正数500000101→所有位取反11111010→加1(11111011)\0问题void test1() { char string[10]; char* str1 0123456789; strcpy( string, str1 ); } //溢出 还有\0 void test2() { char string[10], str1[10]; int i; for(i0; i10; i) { str1[i] a; } strcpy( string, str1 ); } str1没有\0结束符程序崩溃。 void test3(char* str1) { char string[10]; if( strlen( str1 ) 10 ) { strcpy( string, str1 ); } }改为strlen( str1 ) 10 这种方式不会报错但是会造成隐藏的严重bug 会修改内存里面的数据。请计算sizeof的值和strlen的值。void func ( char *str ) { sizeof( str ) ? } char str[10] “hello”; strlen(str); 4和5宏定义问题#include stdafx.h #define SQR(X) X*X int main(int argc, char* argv[]) { int a 10; int k 2; int m 1; a / SQR(km)/SQR(km); printf(%d\n,a); return 0; } a a/ (km*km/km*km) 宏定义A,B中取较大值 #define compare(a,b) ((a b) ? (a) : (b))用C写个程序如何判断一个操作系统是16 位还是32 位的不能用sizeof()函数。int a 32767; if( (a 1) 0 ) { cout32 bitendl; } else { cout16 bitendl; }16位的int范围为-32768 ~ 32767在不用第三方参数的情况下交换两个参数的值.aab; ba-b; aa-b; 或者 a a^b; b a^b; a a^b;指针操作unsigned short array[]{1,2,3,4,5,6,7}; int i 3; *(array i) ? 结果是4。 main() { int a[5]{1,2,3,4,5}; int *ptr(int *)(a1);// (a1)指向下一个一维数组 printf(%d,%d,*(a1),*(ptr-1)); }解int *ptr(int *)(a1);a表示取得数组a存储区域的首地址再加1表示数组a存储区域的后的地址这就使得ptr指针指向数组的最后一个元素后面的那个存储单元的地址而ptr减1后再进行数据访问则访问的是ptr指针的前一个存储单元的值所有最后的答案是25(int *)(a1) 强制转化指针类型。include filename.h和 include “filename.h” 有什么区别会直接去系统遍历会首先在当前项目遍历头文件如果不存在才去系统遍历。的可以改成但是一定不能改成不能做switch()的参数类型是只有整数可以做参数局部变量能否和全局变量重名。可以重名。 局部变量名会覆盖全局变量名。 C中可以使用作用域来区分。全局变量可不可以定义在可被多个.C文件包含的头文件中为什么不可以但是可以声明。 这里涉及到强符号和弱符号的问题具体的可以参考下面的blog。在C语言中函数和初始化的全局变量包括初始化为0是强符号未初始化的全局变量是弱符号。对于它们下列三条规则使用① 同名的强符号只能有一个否则编译器报重复定义错误。② 允许一个强符号和多个弱符号但定义会选择强符号的。③ 当有多个弱符号相同时链接器选择占用内存空间最大的那个。一语句实现x是否为2的若干次幂的判断。if ( x ( x - 1 ) 0 )printf(是2的幂);else printf(不是2的幂);pow(x,y),计算x的y次幂sqrt(x),求浮点数x的平方根fabs(x),求浮点数x的绝对值char* sAAA; printf(%s,s); s[0]B; printf(%s,s); 有什么错常量区 不允许修改内容,结果不变。AAA#define MAX 256 int main() { unsigned char A[MAX],i; for (i0;iMAX;i) A[i]i; }char是一字节八位最大可以表示的整数是255所以这里死循环了struct name1 { char str; short x; int num; } struct name2 { char str; int num; short x; } typedef struct { int a; char b[3]; short d; int c; } node; sizeof(struct name1)8 sizeof(struct name2)12 sizeof(node) 16 union test { int a; int b[5]; double c; } struct test1 { int a; test b; double c; } sizeof(test1) 32;字节对齐int main() { char a; char *stra; strcpy(str,hello); printf(str); return 0; }没有为a分配内存并且a是一个字符变量。 内存越界。地址和变量大小操作unsigned char *p1; unsigned long *p2; p1(unsigned char *)0x801000; p2(unsigned long *)0x810000;请问p15 0x801005; p25 0x810014;输出结果p15的值是801005因为指针变量指向的值字符加一表示指针向后移动一个字节那么加5代表向后移动5个字节所以输入801005p55的值是801014因为指针变量指向的长整形的加一表示指针向后移动4个字节那么加5代表向后移动20个字节所以输入810014输出时十六进制要是十进制就是810020了有数组定义int a[2][2]{{1},{2,3}};则a[0][1]的值为0。 // 对int (*ptr) (),则ptr 是一维数组的名字。 // 函数指针指针在任何情况下都可进行, ,, ,运算。 //不明所以switch(c) 语句中c 可以是int ,long,char ,float ,unsigned int 类型。 //错。 只能是整数float排除。不使用库函数编写函数int strcmp(char *source, char *dest) 相等返回0不等返回-1写一函数int fun(char *p)判断一字符串是否为回文,是返回1不是返回0出错返回-1静态变量操作#includestdio.h int sum(int a) { int c0; static int b 3;//静态 c1; b2; return(abc); } int main() { int I; int a2; for(I0;I 5;I) { printf(%d,, sum(a)); } return 0; } 8,10,12,14,16,一定能打印出”hello”的是134,有错误的是2char *GetHellostr(void); int main(void) { char *ps; ps GetHellostr( ); if(ps ! NULL) { printf(ps); } return 0; } (1) char *GetHellostr(void) { char *ps“hello”; return ps; } (2) char *GetHellostr(void) { char a[]“hello”; return (char *)a; 内存已经被释放了 } (3) char *GetHellostr(void) { static char a[]“hello”; return (char *)a; } (4) char *GetHellostr(void) { char *ps; ps malloc(10); if(NULL ps) return NULL; strcpy(ps,”hello”); return ps; }字符串函数char* strcpy(char* strDest,const char* strSrc) { assert(strDest!NULL strSrc!NULL); char* strTmp strDest; while(*strSrc!\0) { *strDest *strSrc; } strDest \0; return strTmp; } int strlen(const char*strSrc) { assert(strSrc! NULL); int len 0; while((*strSrc) ! \0) len; return len; } char* strcat(char* strDest,const char* strSrc) { assert((strDest ! NULL) (strSrc ! NULL)); char* strTmp strDest; while(*strDest ! \0) strDest; while(*strDest *strSrc); *strDest \0; return strDest; }二级指针和指针的引用void foo(char **p)//双指针 { *p after; } int main() { int *p befor; foo(p); cout p endl;//输出的为after return 0; } void foo(char *p)//指针的引用 { p after; } int main() { int *p befor; foo(p); cout p endl;//输出的为after return 0; }使用汇编语言的原因第一汇编语言执行速率要高于c语言。第二启动代码编写bootloader和内核使用时主要对cpu和内存进行初始化时使用。因为这个时候还能没有c语言编写的环境(堆栈还没建立)所以不能用c语言。#ifndef X#define X...#endif防止头文件被重复包含和编译。指针与数组的区别。第1个存储方式的不同数组是存储的成员内容的本身。而指针存储的是首地址。第2个是运算方式的不同。数组名是一个常量不能进行自增自减的运算而指针是一个变量可以进行自增自减的运算。第3个是赋值运算的操作。数组可以进行初始化操作但不能通过赋值语句进行整体的赋值而指针能指向另一条语句。链表和数组的区别数组静态分配内存链表动态分配内存。数组在内存中是连续的链表是不连续的。数组利用下标定位查找的时间复杂度是O(1)链表通过遍历定位元素查找的时间复杂度是O(N)。数组插入和删除需要移动其他元素时间复杂度是O(N)链表的插入或删除不需要移动其他元素时间复杂度是O(1)。strcpy 为什么要返回char*strcpy函数返回的值可以作另一个函数的实参实现链式操作。IIC介绍开始信号 SCL 为高电平时 SDA 由高电平向低电平跳变开始传送数据。结束信号 SCL 为高电平时 SDA 由低电平向高电平跳变结束传送数据。应答信号接收数据的 IC 在接收到 8bit 数据后向发送数据的 IC 发出特定的低电平脉冲表示已收到数据。 CPU 向受控单元发出一个信号后等待受控单元发出一个应答信号 CPU 接收到应答信号后根据实际情况作出是否继续传递信号的判断。若未收到应答信号由判断为受控单元出现故障。//IIC 发送一个字节 //返回从机有无应答 //1有应答 //0无应答 void IIC_Send_Byte(u8 txd) { u8 t; SDA_OUT(); IIC_SCL0;//拉低时钟开始数据传输 for(t0;t8;t) { IIC_SDA(txd0x80)7; txd1; delay_us(2); //对 TEA5767 这三个延时都是必须的 IIC_SCL1;delay_us(2); IIC_SCL0; delay_us(2); } } //读 1 个字节 ack1 时发送 ACK ack0发送 nACK u8 IIC_Read_Byte(unsigned char ack) { unsigned char i,receive0; SDA_IN();//SDA 设置为输入 for(i0;i8;i ) { IIC_SCL0; delay_us(2); IIC_SCL1; receive1; if(READ_SDA)receive; delay_us(1); } if (!ack) IIC_NAck();//发送 nACK else IIC_Ack(); //发送 ACK return receive; }AES加密AES加密过程中最后16字节的处理128位加密当原文大小不是16字节的整数倍时AES加密会进行填补缺几个填几个当原文大小刚好是16的倍数的时候为了区别明文和密文AES会在明文的后面补充16字节的16。当密文解密到最后的16字节的数据的时候发现最后一个字节的数据为16则舍弃这一串16字节的数据若小于16则表示进行了填充舍弃填充的部分。RS232和RS485h和RS422的特性和区别RS232特点:(1)接口的信号电平值较高 易损坏接口电路的芯片。RS232电压为负逻辑关系。即:逻辑1为-3~-15V;逻辑0:3~15V噪声容限为2V。即要求接收器能识别高于3V的信号作为逻辑“0”低于-3V的信号作为逻辑1”TTL电平为5V为逻辑正0为逻辑负。与TTL电平不兼容故需使用电平转换电路方能与TTL电路连接。(2)传输速率较低在异步传输时比特率为20Kbps;(3)接口使用一根信号线和一根信号返回线而构成共地的传输形式这种共地传输容易产生共模干扰所以抗噪声干扰性弱。(4)传输距离有限最大传输距离标准值为15米RS485特点(1)RS-485的电气特性逻辑“1”以两线间的电压差2V~6V表示逻辑“0以两线间的电压差-6V~-2V表示。接口信号电平比RS-232-C降低了 就不容易损坏接口电路芯片 且该电平与TTL电平兼容 刻方便与TTL电路连接。(2) 数据最高传输速率为10Mbps(3)RS-485接口采用平衡驱动器和差分接收器的组合抗共模干扰能力强即抗噪声性能好。(4)RS-485接口的最大传输距离实际上可达3000米。(5)RS-232-C接口在总线上只允许连接一个收发器即单站能力而RS-485接口在总线上只允许连接多达128个收发器即具有多站能力这样用户可以利用单一的RS-485接口方便地建立设备网络。RS-422和RS-485电路原理基本相同都是以差动方式发送和接受RS-422通过两对双绞线可以全双工工作收发互不影响而RS485只能半双工工作发收不能同时进行但它只需要一对双绞线。RS 422和RS 485在19kpbs下能传输1200米。用新型收发器线路上可连接台设备。RS-422的电气性能与RS-485完全一样。主要的区别在于RS-422有4根信号线两根发送(Y、Z)、两根接收(A、B)。由于RS-422的收与发是分开的所以可以同时收和发(全双工)RS-485有2根信号线发送和接收。RS232是全双工的RS485是半双工的RS422是全双工的。232一对一通信485允许连接128个收发器232单端传送方式485差分信号编译器编译编译器的执行过程编译、汇编、链接编译分为6个阶段词法分析语法分析语义分析中间代码生成代码优化目标代码生成后面的4,5可以不需要。内存区域划分全局变量-》静态区局部变量-》栈动态生成-》堆栈和堆的主要区别空间的申请和释放堆需要人为的进行栈是自动的堆的空间是不连续的栈的空间是连续的堆的空间比较大但申请和应用导致使用起来比较慢栈区空间是向下增长堆区是向上增长快速排序时间复杂度为nlgnvoid fast(int *data, int begin, int end) { int base 0, i 0, j 0; if(begin end) { base data[begin]; i begin; j end; while(i j) { while(i j base data[j]) { j--; } data[i] data[j]; while(i j base data[i]) { i; } data[j] data[i]; } data[i] base; fast(data,begin,i - 1); fast(data,i 1,end); } else { return; } }二分查找法int search(int *data, int key, int begin, int end) { int middle (end - begin) / 2 begin; if(begin end) { return -1; } if(data[middle] key) { return middle 1; } else if(data[middle] key) { end middle - 1; return search(data,key,begin,end); } else if(data[middle] key) { begin middle 1; return search(data,key,begin,end); } }大小端大端格式高字节放在低地址位0x1234 0x12-0x4000,0x34-0x4001小端格式低字节放在低地址位0x1234 0x12-0x4001,0x34-0x4000Extern:extern 是声明不是定义也不分配空间extern double pi 3.14,是声明也是分配空间也定义sizeof空间C语言中sizeof是运算符(操作符)不是函数而且是唯一一个以单词形式出现的运算符它用来计算存放某一个量需要占用多少字节它的结合性是从右到左。Sizeof共同体取最大变量的为空间大小结构体字节对齐枚举大小取其中常数的大小一般为4。__attribute__((packed)),告诉编译器在编译过程中取消优化对齐__attribute__((aligned(8)),设定一个指定对齐的大小__attribute__((at(0x80000000))),设定存储地址Short A[10]; short *q,*p; q p A; p;Sizeof((char*)p - (char*)q) 2;网络编程基本知识访问网址的过程1域名解析为IP地址DNS2与目的主机进行TCP连接三次握手3发送与收取数据http4与目标主机断开TCP连接四次挥手域名baidu.com通过DNS《--》主机IP通过APR--》通过RAPR物理地址域名www网址 HTTP URL--》协议主机端口号路径局域网LAN,广域网WANLAN分为物理层MAC层LLC层APR:地址解析协议根据IP地址获取物理地址的一个TCP/IP协议RAPR逆地址解析协议将MAC地址转为IP地址DNS域名系统将一个域名转为一个IP地址IP地址用于唯一标识互联网计算机的逻辑地址域名IP地址的基础上进行一个符号化的方案帧中继网是一种广域网。一个简单的计算机网络的3个部分为一个通信子网一系列通信协议若干主机。集线器所有端口是一个冲突域交换机是一个端口一个冲突域。在无连接系统UDP中发送数据不需要联系目的设备。Internet起源于美国国防部www万维网起源于英国物理粒子实验室一般监视套接字的描述符取最大的加1IP地址长度为32为分4段每段8位范围为1~254由两部分组成网络地址主机地址。IP地址类型A类1~127B类128~191C类192~223D类224~239E类240~255端口号范围在0~65536每个协议对应特定的端口号使用TCP/IP的网络在传输信息时出现了错误信息采用的是ICMP协议。IP地址非网络号主机号不能为0非广播号主机号不能为255。网络传递中时延最小的是电路交换路由器在网络层网卡在数据链路层。数据链路层处理设备到设备之间的通信。传输层处理端节点间的通信两端用户传输文件在应用层。数据链路层数据单位为帧物理层为位网络层为包广域网和局域网的中间设备为路由器和交换机DNS,TFTP,SNMP,因为一次传输数据较少建立在UDP之上。HTTP,FTP,TELNET,EMAIL,SMTP建立在TCP之上SMTP是一组用于源地址到目的地址传递邮件的规则FTP用于Internet上控制文件的双向传输默认端口号为21Telnet用于Internet远程登陆服务的标准协议默认端口号23POP3允许用户从服务器上把邮件存储到本地主机同时删除保存在邮件服务器上的邮件。OSI开发系统互联404:请求资源不存在403表示禁止访问301资源永久被转移302临时转移503服务器暂时无法处理请求MQTT与Http的区别1MQTT以数据为中心Http以文档为中心。2Http是以请求-响应为模型Mqtt以订阅-发布为模型这样是独立存在当一个客户端出现故障时不影响整个系统。3Mqtt提供3中服务质量且传输速率比Http块。系统编程基本知识进程和线程区别根本区别进程是操作系统资源分配的基本单位线程是处理器任务调度和执行的基本单位。内存分配在同一进程内的线程是可以共享该进程的地址空间和资源每个进程的地址空间和资源是相互独立的。进程之间的通信方式FIFO,管道信号信号量队列共享内存套接字僵尸进程子进程退出父进程运行父进程未调用Wait或waitpia导致子进程变为僵尸进程危害占进程表位置多了就导致进程创建失败孤儿进程子进程运行父进程退出子进程由Init进程收养子进程变为孤儿无危害进程在退出时不会销毁自己打开的共享内存“信号量用在多线程多任务同步的一个线程完成了某一个动作就通过信号量告诉别的线程别的线程再进行某些动作大家都在semtake的时候就阻塞在 哪里。而互斥锁是用在多线程多任务互斥的一个线程占用了某一个资源那么别的线程就无法访问直到这个线程unlock其他的线程才开始可以利用这 个资源。比如对全局变量的访问有时要加锁操作完了在解锁。有的时候锁和信号量会同时使用的用户栈和内核栈是两个独立的区域内核栈保存的是内核态运行程序时候的相关寄存器的信息用户栈保存用户进程的子进程之间相互调用的参数返回值以及局部变量等。中断相应过程CPU接收中断-》保存中断中上下文跳转到中断处理的历程-》执行中断顶半部-》执行中断低半部-》恢复被中断的上下文顶半部一般用于执行比较紧急的任务比如清中断读取寄存器底半部用于不太紧急的。可以节省中断处理时间Sftp,scp在Linux中用于传输文件。Chomd更改的是拥有者user所属组群group其他用户other一个任务呗唤醒就处于就绪状态FreeRTOS通过任务优先级来实现任务调度中断优先级最高。FreeRTOS里的任务之间通讯可以通过队列、二进制信号量、计数信号量、互斥等几种手段操作系统一般是用户与计算机的接口短路求值a 1,b 0,c 3;K (a b)(c);K 0,c 3;Printfprintf入栈的顺序是从右到左Printf(“%d”,a,b);a 1,b 2;最后输出1先进后出printf输出字符串遇到’\0’停止输出。指针与数组的区别。第1个存储方式的不同数组是存储的成员内容的本身。而指针存储的是首地址。第2个是运算方式的不同。数组名是一个常量不能进行自增自减的运算而指针是一个变量可以进行自增自减的运算。第3个是赋值运算的操作。数组可以进行初始化操作但不能通过赋值语句进行整体的赋值而指针能指向另一条语句。链表和数组的区别数组静态分配内存链表动态分配内存。数组在内存中是连续的链表是不连续的。数组利用下标定位查找的时间复杂度是O(1)链表通过遍历定位元素查找的时间复杂度是O(N)。数组插入和删除需要移动其他元素时间复杂度是O(N)链表的插入或删除不需要移动其他元素时间复杂度是O(1)。各种基础知识Int *p; p p 2这是不合法的未申请空间也没有指向空间地址这样操作属于野指针。两个指针可以相减相加得到的地址没有什么意义。USB采用的是异步通信。‘\101’转义字符对应8进制十进制对应65-》AUnion定义的时候不能初始化指针在32位机占4字节在64位机占8字节16位int范围为-32768~32767嵌入式常用的数据传递方式为中断。数组名为指针常量其值不可改。函数重载必定是形参的类型或者个数不同在C中数组的下标为负数是合理的指向的只是a[0]前面的一个数在C#和Java中会报错ARM处理器的特点为低功耗。ARM处理器在ARM是32位指令在Thumb是16位指令不能同时支持。在ARM处理器中Reset的中断优先级最高。存储器速度由快到慢是寄存器缓存内存flashCPU的主要组成部分运算器控制器CPU上的三条总线数据总线控制总线地址总线完整计算机系统包括运算器控制器存储器输入设备输出设备。双绞线的传输距离无法超过100米。静态变量的生命周期到程序结束Typedef和define区别#define是C语言中定义的语法是预处理指令在预处理时进行简单而机械的字符串替换不作正确性检查只有在编译已被展开的源程序时才会发现可能的错误并报错。typedef是关键字在编译时处理有类型检查功能。它在自己的作用域内给一个已经存在的类型一个别名但不能在一个函数定义里面使用typedef#define没有作用域的限制只要是之前预定义过的宏在以后的程序中都可以使用而typedef有自己的作用域#define INTPTR1 int*typedef int* INTPTR2;INTPTR1 p1, p2;INTPTR2 p3, p4;含义分别为声明一个指针变量p1和一个整型变量p2声明两个指针变量p3、p4补码转原码:符号位不变取反加1。10011011以1开头为负数取反符号位不变11100100 1 111 00 101C基础知识Private数据只有基类和友元可访问Protected数据只有基类友元派生可以访问友元函数不能通过this指针访问对象在C语言中只要是非零的数就表示真不需要一定为整数标识符由字母数字下划线构成数字不能在第一位编译器在提取符号时总是尽可能多地将后面的符号纳入到前面的表达式除非纳入之后会让一个有效的表达式变成无效例如ab编译器认为它和下面的式子等价(a)bint main() { int a[] {2,4,5,6}; int *p a; int **q p; printf(%d,*(p)); printf(%d,**q); return 0; } 值为2,4 *P可看成*P即先执行p后执行*p但由于这里的“”号是后加加号 所以会在整条语句执行完后再对P自加一freertos相关知识点在 FreeRTOS 中任务、队列、信号量等组件有各自的功能但它们也经常配合使用来实现更复杂的功能。在使用这些功能时有几个关键的注意事项和搭配使用的策略1. 任务Task注意事项任务栈大小每个任务在创建时都需要指定栈大小。如果栈大小设置不当可能会导致堆栈溢出进而引发程序崩溃。栈大小通常与任务的复杂度、局部变量和函数调用深度相关。开发时要密切监控栈使用情况。使用configCHECK_FOR_STACK_OVERFLOW配置项来启用栈溢出检查。任务优先级设置任务的优先级时需要谨慎。高优先级的任务会占用更多的 CPU 时间因此应该避免让某些任务处于长期高优先级状态以防影响其他任务的执行。任务优先级之间的调度遵循优先级抢占式策略。较低优先级的任务在高优先级任务运行时会被挂起。任务调度如果没有调用vTaskStartScheduler()启动调度器任务将不会运行。务必确保任务创建并正确启动调度器。任务之间的协作任务间通信任务通常需要通过队列、信号量等方式来进行数据传递和同步。举例来说一个任务可以通过队列将数据发送到另一个任务而另一个任务则从队列接收数据并处理。任务也可以使用信号量来同步其执行顺序。例如一个任务完成特定操作后释放信号量另一个任务则等待信号量释放后继续执行。2. 队列Queue注意事项队列大小队列的大小即最多能容纳多少元素需要根据系统的需求来设置。如果队列满了且没有任务读取数据则xQueueSend()会阻塞任务直到队列有空间。如果队列为空xQueueReceive()会阻塞任务直到有数据可用。使用portMAX_DELAY可以让任务永久等待队列操作或者可以使用特定的时间来限制等待时长。队列操作的线程安全队列本身是线程安全的但在任务间使用队列时仍需要确保数据一致性。例如使用队列传输指针时指针指向的数据应该在多个任务中保持一致性例如避免数据修改引起的竞态条件。队列与任务的搭配使用任务间通信队列最常用于任务间传递数据。一个任务可以将数据放入队列而另一个任务可以从队列中获取数据。例如任务 A 从传感器读取数据并将其发送到队列。任务 B 从队列中读取数据并进行处理或发送到显示屏。队列与信号量的结合有时需要信号量来控制队列的访问。例如一个任务可以在队列为空时等待信号量释放而另一个任务在将数据放入队列后释放信号量。3. 信号量Semaphore注意事项互斥信号量信号量的常见用途之一是实现任务的互斥锁。使用互斥信号量时确保互斥信号量在使用后总是释放否则其他任务将无法获得锁导致死锁。xSemaphoreTake()阻塞任务直到它能成功获取信号量。xSemaphoreGive()用来释放信号量。必须确保每次获取信号量后都能释放。使用xSemaphoreCreateMutex()创建互斥信号量时FreeRTOS 会自动处理优先级继承以避免优先级反转问题。二进制信号量与计数信号量二进制信号量适用于任务间的同步如一个任务通知另一个任务开始执行。常见的用法包括用信号量通知任务开始工作或结束工作。计数信号量适用于计数事件如限制某个资源的并发访问次数。例如控制并发线程访问共享资源的数量。信号量与任务的搭配使用互斥在需要保护临界区的情况下可以使用信号量确保多个任务不能同时访问某些共享资源。例如多个任务可能同时操作共享内存如果不使用信号量可能会发生竞态条件。例如任务 A 和任务 B 都需要访问共享数据但为了防止数据冲突它们在访问数据时必须先获取互斥信号量。任务同步信号量也常用于同步多个任务的执行。例如任务 A 完成初始化后释放信号量任务 B 等待信号量并开始执行。4. 定时器Timer注意事项定时器回调函数定时器的回调函数是由系统的定时中断触发的。回调函数不应该做太多复杂的操作最好是做一些简单的标志位设置或状态更新。过于复杂的操作可能会影响定时器的精度和系统性能。定时器精度定时器的精度取决于系统时钟的配置。通过configTICK_RATE_HZ可以调整系统节拍率从而改变定时器的精度。定时器的删除一旦定时器不再需要应该及时删除以释放资源。使用xTimerDelete()可以删除定时器。定时器与任务的搭配使用定时任务调度定时器可以用来周期性地执行任务。例如每隔一段时间发送心跳信号或周期性读取传感器数据。例如在一个系统中你可能希望每 1 秒钟读取一次温度传感器的数据并将其处理。可以通过一个周期性定时器来实现这个功能。5.其他注意事项死锁在使用信号量时要特别小心死锁的发生。死锁通常是由于两个或更多任务互相等待对方释放信号量而导致的。避免在同一任务中多次获取多个信号量或同时在多个任务之间相互依赖信号量。任务调度FreeRTOS 采用优先级调度机制任务的执行顺序依赖于任务的优先级。在设计任务时要避免出现优先级反转问题可以通过使用优先级继承协议来解决这一问题。综上所述任务、队列、信号量等是 FreeRTOS 中的核心工具它们各自发挥不同的作用并且通常需要搭配使用来实现更复杂的功能。例如任务通过队列传递数据使用信号量来控制对共享资源的访问定时器则用于定期执行某些操作。合理使用这些工具可以确保系统的高效运行并避免常见的多任务调度和同步问题。MQTT服务质量QoS及发布订阅模型2.发布订阅模型发布者Publisher发送消息的客户端。每个消息都带有一个主题Topic。订阅者Subscriber接收消息的客户端。订阅某个主题后会接收到该主题发布的所有消息。消息代理Broker负责管理所有的消息传输、主题的订阅/发布等任务。它将发布者和订阅者连接在一起。3.MQTT的QoS服务质量等级MQTT 协议支持三种服务质量等级QoS这决定了消息在传递过程中的可靠性QoS 0 – 最多一次消息最多发送一次不会进行重试。消息可能丢失也不会确认消息的接收状态。适用于对实时性要求高但对消息可靠性要求不高的场景。适用场景温度传感器的实时数据推送、设备状态更新等。QoS 1 – 至少一次消息会被至少发送一次接收方会确认消息的接收。如果确认没有收到发布者会重新发送消息。可能会出现消息重复但可以确保消息最终到达。适用场景需要保证消息可靠到达的应用如警报系统、远程控制。QoS 2 – 只有一次消息只能送达一次且必须被正确地传递到接收方。这是最严格的服务质量保证它保证消息的可靠性并避免重复发送。会使用四步握手机制确保消息的准确传递。适用场景需要高度可靠消息传递的场景如支付交易、设备配对等。4.注意事项QoS 选择选择 QoS 级别时需要权衡系统需求考虑到带宽、延时、消息重复等因素。对于对可靠性要求不高的应用可以选择 QoS 0。对于可靠性要求较高的应用应该选择 QoS 1 或 2。延迟与带宽QoS 1 和 2 需要更多的带宽和计算资源尤其是 QoS 2因为它需要四步握手。对于有限带宽和资源的设备应该尽量使用 QoS 0。HTTP相关知识1.HTTP 协议概述HTTPHypertext Transfer Protocol是一种用于在客户端如浏览器和服务器之间传输超文本的协议是Web的基础。HTTP 是无状态的即每一次请求都是独立的服务器不会记住客户端的状态除非使用 Cookies 或 Sessions。2.HTTP的请求和响应HTTP请求由请求行、请求头、请求体组成。请求行包含方法如 GET、POST、URL 和协议版本。请求头包含客户端的信息如 User-Agent、Accept。请求体通常用于 POST 请求包含需要发送的数据。HTTP响应由状态行、响应头和响应体组成。状态行包含协议版本、状态码和描述如 200 OK、404 Not Found。响应头包含服务器的信息如 Server、Content-Type。响应体包含响应的实际内容如 HTML 页面、JSON 数据等。3.HTTP方法GET请求获取资源数据通过 URL 传递。POST提交数据数据放在请求体中适用于提交表单或上传数据。PUT用于更新现有资源。DELETE删除指定资源。HEAD获取响应头类似 GET但不返回响应体。OPTIONS请求服务器支持的 HTTP 方法。5.注意事项HTTP 是无状态的每次请求都相互独立服务器不会保存客户端状态。为了在多个请求间保持状态通常使用Cookies或Sessions。缓存控制HTTP 头中的Cache-Control可以用来控制缓存策略帮助优化页面加载速度和减少服务器负载。安全性使用HTTPS加密的 HTTP可以保证数据传输的安全性防止中间人攻击。性能大量的 HTTP 请求可能导致较高的延迟和负载现代应用中通常使用持久连接和HTTP/2来减少连接开销。常用的协议及注意事项常用协议MQTT优点低带宽、高效、支持离线消息传递、发布/订阅模型。适用场景物联网IoT设备、实时消息推送。注意事项选择合适的 QoS 级别合理配置连接和重试机制。HTTP优点普遍支持、易于实现、良好的兼容性。适用场景Web 服务、RESTful API、表单提交。注意事项使用 HTTPS 来提高安全性合理管理缓存和会话状态注意请求和响应的体积。常见选择对于低带宽、高频率的消息传输MQTT更加适合。对于 Web 服务和大多数传统客户端-服务器通信HTTP是更常用的协议。综合建议IoT 系统通常优先选择MQTT因为它轻量且适应低带宽、延迟要求高的场景。Web 应用使用HTTP或HTTPS并使用 RESTful 风格的 API 来简化交互。总结来说MQTT 和 HTTP 各有优势和应用场景合理选择适合的协议和服务质量级别以及在设计时关注安全、可靠性和性能能够提升应用的可用性和稳定性。

相关文章:

物联网面试必过要点

要是能熟记以下知识点,再加上自身的项目经验,过个面试,问题不大。指针定义一个指向指针的的指针,它指向的指针是指向一个整型数 int **a; 一个有10个指针的数组,该指针是指向一个整型数的 int *a[10]; 一个指向有10个整…...

完整博文目录

Java 集合 JDK 常用集合类源码阅读 🌟 并发 JUC 并发包源码阅读 🌟ThreadPoolExecutor 与常用线程池volatile, synchronized 和锁 基础扩展 String 字符串浅析反射机制异常机制 数据库 HBase HBase原理 🌟 MySQL 事务,隔离…...

第一篇:从零搭建 Spring Boot 3 + Dubbo 3 + ZooKeeper 微服务实战

技术栈速览组件版本说明Spring Boot3.2.6基础框架Apache Dubbo3.3.4RPC 框架ZooKeeper3.9.2注册中心(Docker 部署)Curator5.xZK 客户端(由 Starter 管理)JDK17Spring Boot 3 最低要求项目目录结构先把整体结构了然于胸&#xff0c…...

联合循环——14 厂用电缆介绍

一、电缆的应用类别 电缆,是连接两个设备传输电信号的组件,由两条或更多的导线粘合、扭曲或编织在一起形成。电缆的用途广泛并且每个用途都需特制,它的功能大至传输电能、电信号和实现电磁能转换的线材产品。 电力缆通常由传输电力或电信号的…...

文章代码地址

文章目录 CSDN主页 文章代码 文章目录 工具 docsify详解 Git详解 nssm详解 Typora详解 VScode入门 PhotoShop入门 PM2详解 json-server详解 VMware Workstation Pro详解 计算机基础 Linux详解 网络详解 HTTP详解 计算机常用端口 语义化版本规范(SemVer&#…...

联合循环——13 智能电厂的发展

一、国内外智能电厂 1.1 大唐姜堰智慧电厂的创新科技 原文链接:https://www.sohu.com/a/129754422_131990 (1)智慧决策系统: 智慧决策系统以关注数据的诊断、分析为己任,集科学、有效、便捷的数据诊断、分析方法与一身…...

联合循环——12 电厂通讯系统简介

一、SCADA (Supervisory Control And Data Acquisition) 数据采集与监视控制系统是以计算机为基础的DCS与电力自动化监控系统;它应用领域很广,可以应用于电力、冶金、石油、化工、燃气、铁路等领域的数据采集与监视控制以及过程控…...

联合循环——11 厂用储能电池原理介绍

一、化学能到电能 燃烧(氧化还原反应)是使化学能转换为电能的关键。而氧化还原反应的本质是氧化剂和还原剂之间发生电子转移的过程。电子转移引起化学键的重新组合。同时伴随着体系能量的变化。 如:煤的燃烧、铝和盐酸反应放热(氧…...

Java毕业设计——基于 Java+SSM+微信小程序的智能二维码门禁管理系统设计与实现(毕业论文+程序源码)——门禁管理系统

基于 JavaSSM微信小程序的智能二维码门禁管理系统设计与实现(毕业论文程序源码) 大家好,今天给大家介绍基于 JavaSSM微信小程序的智能二维码门禁管理系统设计与实现,文章末尾附有本毕业设计的论文和源码下载地址哦。需要下载开题…...

java毕业设计——基于 java+springboot+微信小程序的短视频社交平台设计与实现(毕业论文+程序源码)——短视频社交平台

基于 javaspringboot微信小程序的短视频社交平台设计与实现(毕业论文程序源码) 大家好,今天给大家介绍基于 javaspringboot微信小程序的短视频社交平台设计与实现,文章末尾附有本毕业设计的论文和源码下载地址哦。需要下载开题报…...

跨平台兼容性测试:Cypress在电商系统中的应用

一、电商系统中的兼容性测试挑战在数字化时代,电商系统需在多样化的设备(如桌面、平板、手机)和浏览器(如Chrome、Firefox、Edge)上无缝运行,以保障用户购物体验。跨平台兼容性测试验证软件在不同环境下的行…...

C++毕业设计——基于 C+++TCP+Websocket的即时通信系统设计与实现(毕业论文+程序源码)——即时通信系统

基于 CTCPWebsocket的即时通信系统设计与实现(毕业论文程序源码) 大家好,今天给大家介绍基于 CTCPWebsocket的即时通信系统设计与实现,文章末尾附有本毕业设计的论文和源码下载地址哦。需要下载开题报告PPT模板及论文答辩PPT模板…...

Lumibot核心功能揭秘:股票、期权、期货一站式交易解决方案

Lumibot核心功能揭秘:股票、期权、期货一站式交易解决方案 【免费下载链接】lumibot Backtesting and Trading Bots Made Easy for Crypto, Stocks, Options, Futures, FOREX and more 项目地址: https://gitcode.com/gh_mirrors/lu/lumibot Lumibot是一款功…...

如何快速上手 runtimejs:轻量级 JavaScript 库操作系统完整指南

如何快速上手 runtimejs:轻量级 JavaScript 库操作系统完整指南 【免费下载链接】runtime [not maintained] Lightweight JavaScript library operating system for the cloud 项目地址: https://gitcode.com/gh_mirrors/runt/runtime runtimejs 是一个轻量级…...

如何使用img2css:将任何图片转换为纯CSS的终极指南

如何使用img2css:将任何图片转换为纯CSS的终极指南 【免费下载链接】img2css Convert any image to pure CSS. Recreates images using only box-shadows. 项目地址: https://gitcode.com/gh_mirrors/im/img2css img2css是一个创新工具,能够将任何…...

如何快速构建 Vue Music 音乐应用:从安装到部署的完整指南

如何快速构建 Vue Music 音乐应用:从安装到部署的完整指南 【免费下载链接】vue-music cloud-music(网易云音乐) 项目地址: https://gitcode.com/gh_mirrors/vuem/vue-music Vue Music 是一个基于 Vue.js 开发的现代化音乐播放应用,它模仿网易云音…...

ps4-exploit-host远程DNS使用教程:无需本地运行即可玩转漏洞利用

ps4-exploit-host远程DNS使用教程:无需本地运行即可玩转漏洞利用 【免费下载链接】ps4-exploit-host Easy Exploit Hosting 项目地址: https://gitcode.com/gh_mirrors/ps/ps4-exploit-host ps4-exploit-host是一款功能强大的PlayStation 4漏洞利用托管工具&…...

如何快速上手DetectAndTrack:CVPR18论文算法的完整实践指南

如何快速上手DetectAndTrack:CVPR18论文算法的完整实践指南 【免费下载链接】DetectAndTrack The implementation of an algorithm presented in the CVPR18 paper: "Detect-and-Track: Efficient Pose Estimation in Videos" 项目地址: https://gitcod…...

终极Keychron键盘设置指南:从入门到精通的实用技巧

终极Keychron键盘设置指南:从入门到精通的实用技巧 【免费下载链接】keychron Settings for Keychron keyboards 项目地址: https://gitcode.com/gh_mirrors/ke/keychron Keychron开源项目是针对Keychron键盘的设置工具,帮助用户在Linux系统上轻松…...

终极Android WebView缓存解决方案:CacheWebView开源项目完全指南

终极Android WebView缓存解决方案:CacheWebView开源项目完全指南 【免费下载链接】CacheWebView Custom implement Android WebView cache, offline website, let cahe config more simple and flexible 项目地址: https://gitcode.com/gh_mirrors/ca/CacheWebVi…...

揭秘DomainPasswordSpray:简单高效的域密码喷洒工具完全指南

揭秘DomainPasswordSpray:简单高效的域密码喷洒工具完全指南 【免费下载链接】DomainPasswordSpray DomainPasswordSpray is a tool written in PowerShell to perform a password spray attack against users of a domain. By default it will automatically gener…...

PySpace与GLSL深度整合:打造自定义分形着色器的终极指南

PySpace与GLSL深度整合:打造自定义分形着色器的终极指南 【免费下载链接】PySpace GLSL Fractal Ray Marcher in Python 项目地址: https://gitcode.com/gh_mirrors/py/PySpace PySpace是一个强大的Python项目,它将GLSL(OpenGL着色语言…...

java毕业设计下载(全套源码+配套论文)——基于javaEE+SSH+oracle的健康管理系统设计与实现

基于javaEESSHoracle的健康管理系统设计与实现(毕业论文程序源码) 大家好,今天给大家介绍基于javaEESSHoracle的健康管理系统设计与实现,更多精选毕业设计项目实例见文末哦。 文章目录: 基于javaEESSHoracle的健康管…...

asp毕业设计——基于asp+access的销售供应链管理系统设计与实现(毕业论文+程序源码)——供应链管理系统

基于aspaccess的销售供应链管理系统设计与实现(毕业论文程序源码) 大家好,今天给大家介绍基于aspaccess的销售供应链管理系统设计与实现,文章末尾附有本毕业设计的论文和源码下载地址哦。需要下载开题报告PPT模板及论文答辩PPT模…...

PPOCRLabel进行多语言语种的自动标注

需求需要标注法语。PPOCRLabel默认标注中文/英文。如果需要标注其他语种,需要修改代码。在PPOCRLabel.py中MainWindow的__init__中进行修改:self.lang "fr" # 加入法语标志params {"use_doc_orientation_classify": False,&qu…...

告别论文焦虑:从开题到答辩,AI如何提供一站式解决方案?

当查重、格式、AIGC检测三重压力叠加,一款真正懂学术的智能工具或许能成为你的毕业季“救命稻草”。 又到一年毕业季,图书馆、实验室、宿舍里,无数学生正面临学术生涯的重要关卡——毕业论文。从开题报告的反复修改,到文献综述的浩…...

如何使用BlindAI构建安全的隐私增强AI解决方案:完整指南

如何使用BlindAI构建安全的隐私增强AI解决方案:完整指南 【免费下载链接】blindai Confidential AI deployment with secure enclaves :lock: 项目地址: https://gitcode.com/gh_mirrors/bl/blindai BlindAI是一款基于安全飞地技术的隐私增强AI部署解决方案&…...

35岁前必建“技术护城河”:脏乱差模块防御学

第一章&#xff1a;脏乱差模块的识别与战略价值1.1 模块特征诊断矩阵代码腐化指标&#xff1a;循环复杂度>30、单元测试覆盖率<20%的祖传代码模块业务耦合陷阱&#xff1a;涉及多系统联动的支付对账、库存同步等核心链路接口文档黑洞区&#xff1a;仅存口头传承的业务规则…...

装傻生存艺术:如何让AI认定你是“濒危程序员”

AI时代的测试生存悖论在AI驱动的自动化测试生态中&#xff0c;测试工程师面临一个微妙挑战&#xff1a;过度展现技术能力可能触发AI系统的“竞争警报”&#xff0c;导致工具限制访问权限或误判操作意图&#xff1b;而完全隐藏专业性又将削弱职业价值。这一矛盾催生了“濒危程序…...

在技术债沼泽建城堡:让裁员成本高到绝望

在软件测试领域&#xff0c;技术债&#xff08;Technical Debt&#xff09;常被视为隐藏的沼泽——它悄无声息地累积&#xff0c;拖慢开发效率&#xff0c;增加系统风险。然而&#xff0c;聪明的测试从业者能将这片沼泽转化为坚固城堡&#xff0c;让裁员成本高到企业望而却步。…...