0


嵌入式软件开发工程师面指南_总结

嵌入式软件开发工程师面指南

个人网站入口:http://www.baiziqing.cn/

一、C语言

1.1、局部变量能否和全局变量重名

能,局部会屏蔽全局。

1.2、如何用C编写死循环

while(1){}或者for( ; ; )

1.2、new和malloc

1)、new和delete是c++的关键字,不需要头文件,需要编译器支持;malloc和free是c/c++的库函数、需要带头文件stdlin.h

2)、使用new操作符申请内存分配时,无需指定内存块的大小,编译器会根据类型信息自行计算;而malloc则需要支持本地所分配的大小。

3)、new操作符内存分配成功时,返回的是对象类型的指针;而malloc内存分配成功则返回void。

1.3、static的用法(定义和用途)(必考)

static 限制作用域

在C语言中,关键字static有三个明显的作用:

1)、用static修饰局部变量:使其变为静态储存方式,那么这个局部变量执行完成时不会被释放,继续保留在内存中。

2)、用static修饰全局变量:使其在本文件内部有效,而其他文件不可以被引用或链接该变量。

3)、用static修饰函数:使函数只在本文件内部有效,对其他文件不可见,这样的函数又叫静态函数;使用静态函数的好处,不用担心与其他文件的同名函数产生干扰,也是对函数本身保护的一种机制。

1.4、const的用法(定义与用途)(必考)

const主要用来修饰变量、函数形参和类成员函数:

1)、用const修饰常量:定义时就初始化,以后不能修改。

2)、用const修饰形参:func(const int a){ };该函数在函数内不能改变。

3)、用const修饰成员函数:该函数对成员变量只能进行只读操作,就是不能修改成员变量的数值。

下面的声明都是什么意思?

constint a;intconst a;constint*a;int*const a;intconst* a const;

第一和第二作业是一样的,a是常整型数。

第三个意味着a是一个指向常整型数的指针。(整型数不可修改,但指针可以)

第四个意思是a是一个指向整型数的常数的指针。(指针指向的整型数是可以修改的,但指针是不可修改的)

第五个意味着a是一个指向整型数的常指针。(指针指向的整型数是不可修改的,同时指针也是不可修改的)

[scode type=“blue”]

结论和记忆方法: ***
(1)const 在 *前面,就表示const作用于p所指向的量。所以这时候p所指向的是个常量。
(2)const 在 后面,表示p本身是常量,但是p指向的不一定是常量。
(3)
在const中间,表示p本身是常量,p指向的也是个常量。

[/scode]

1.5、const常量和#define的区别(编译阶段、安全性、内存占用等)

用#define max 100;定义的常量没有类型(不就行类型安全检查,可能会参数意想不到的错误)所给出的是一个立即数,编译器只是把所定义的常量值与所在的常量名字联系起来,define所定义的宏变量在预处理阶段的时候进行替换,在程序中使用到该常量的地方都要进行拷贝替换。

用const int max = 255;定义的常量有类型(编译时会进行类型检查)名字,存储在静态区域中,在编译时确定其值。在程序运行过程中const变量只有一个拷贝,而#define所定义的宏变量却有多个拷贝,所以宏定义在程序运行过程中所消耗的内存比const变量的大很多。

1.6、volatile作用和用法

一个定义为volatile的变量是说这变量可能被意想不到的地改变,这样不会假设这个变量的值了。

以下几种情况都会用到volatile:

1)、并行设备的硬件存储器。

2)、一个中断服务子程序会访问到的非自动变量。

3)、多线程应用中被几个任务共享的变量。

1.7、变量的作用域(全局变量和局部变量)

全局变量:

在所以函数体外部定义,程序所在的部分(甚至其他文件中的代码)都可以使用。

全局变量不受作用域的影响(也就是全局变量的生命周期一直到程序的结束)。

局部变量:

出现在一个作用域内,它们是局限于一个函数的。

局部变量经常被称为自动变量,它们进入作用域时自动生成,离开作用域时自动消失。

关键字auto可以显式说明这个问题,但是局部变量默认为auto。所以没有必要声明auto。

局部变量可以和全局变量重名,在局部变量作用域范围内,全局变量失效,采用的是局部变量的值。

1.8、sizeof与strlen(字符串,数组)

1)、如果是数组:

#include<stdio.h>intmain(){int a[5]={1,2,3,4,5};printf(“sizeof 数组名=%d\n”,sizeof(a));printf(“sizeof*数组名=%d\n”,sizeof(*a));}

运行结果:

sizeof 数组名=20sizeof*数组名=4

2)、如果是指针,sizeof只会检测到指针的类型,指针都是占用4字节的空间(32位机)。

sizeof是什么?是一个操作符,也是关键字,就不是一个函数,这和strlen()不同,strlen()是一个函数。

1.9、与或非,异或。运算符优先级

1.10、递归函数与回调函数的区别是什么?

答:回调是一个函数把非当前函数当做参数传递到自身内部来调用;而递归是自己调用自己。

1.11、问什么要用回调函数呢?

答:我们对回调函数的使用无非是对函数指针的应用,函数指针的概念本身很简单,但是把函数指针应用于回调函数就体现了一种解决问题的策略,一种设计系统的思想。

1.12、const关键字的作用

const是一个修饰符,被修饰的对象或者变量是不可修改的,也就是说const可读不可改

1.13、系统调用和函数调用的区别

系统调用是最底层的应用,是面向硬件的。而库函数的调用是面向开发的,相当于应用程序的API(即预先定义好的函数)接口;

1.14、段错误发生的原因

段错误 是指访问的内存超过了系统给程序分配的内存空间。

原因:

  • 访问不存在的内存空间
  • 访问只读的内存空间
  • 访问系统保护的内存空间
  • 栈溢出

1.15、段错误发生的原因

1.16、什么时候会造成内存泄露

常见的内存泄露

(1)内存分配未成功,却使用了它
(2)内存分配成功,但尚未初始化就引用它
(3)内存分配成功且初始化,但操作越过了内存的边界
(4)忘记释放内存,造成内存泄漏
(5)释放了内存却继续使用它

1.17、什么是大小端模式

高字节对应高地址(大端模式)、高字节对应低地址(小端模式)

1.18、全局变量可以声明定义在头文件中?

注意头文件中不可以放变量的定义!!!一般情况下头文件中只放变量的声明,因为头文件要被其他文件包含(即#include),如果把定义放到头文件的话,就不能避免多次定义变量,C++不允许多次定义变量,一个程序中对指定变量的定义只有一次,声明可以无数次。

1.19、C语言中各种数据类型与"0"的比较详解

1.19.1、int类型数据和0比较

1.19.1、int类型数据和0比较

if(a ==0)或者 if(a !=0)

1.19.2、float类型与0比较

constfloat N=0.0001;if((a>=N)&&(a<=N)

不建议写成:

if(a ==0)或者 if(a !=0)

1.19.3、bool类型与0比较

建议写成:if(a)或者 if(!a)

1.19.4、指针类型与0比较

if(p ==NULL) 或者 if(p !=NULL)

1.20、c语言中什么是位段

位段(bit-field)是以位为单位来定义结构体(或联合体)中的成员变量所占的空间。含有位段的结构体(联合体)称为位段结构。采用位段结构既能够节省空间,又方便于操作。

1.21、简述什么是地址传递和值传递,并简述两者的区别

值传递只是将变量的内容复制一份而已,函数进行操作的其实是另一个变量,只是另一个变量的值和传递的变量值是相同的。

而地址传递是直接把变量的地址传递给函数,这时函数是直接对原来的变量进行操作的。所以值会变化。

1.21、c语言中调用函数如何返回多个值?

通过使用指针,在函数调用时,传递带有地址的参数,并使用指针更改其值;这样,修改后的值就会变成原始参数。

1.22、函数中能否返回一个局部变量地址

一般的来说,函数是可以返回局部变量的。 局部变量的作用域只在函数内部,在函数返回后,局部变量的内存已经释放了。

1.23、栈的特点是什么

栈的特点是先进后出表。栈是一种只能在一端进行插入和删除操作的特殊线性表。它按照先进后出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据。

1.24、c语言中用了#define,作用范围是从哪到哪

define只在当前文件有效,如果是在头文件中定义的,则引用改头文件的文件都有效

1.25、c语言中定义常量有几种方式

定义常量PI的两种方式:

#definePi3.1415926f;
constfloat pi 3.1415926f;

1.26、程序的局部变量存在于哪里,全局变量存在于哪里,动态申请数据存在于哪里。

程序的局部变量存在于栈区;全局变量存在于静态区;动态申请数据存在于堆区。

1.27、do……while和while有什么区别?

do…while是先循环再判断,while是先判断再循环。

二、Linux

2.1、 Linux内核的组成部分

Linux内核主要由五个子系统组成:进程调度,内存管理,虚拟文件系统,网络接口,进程间通信。

2.2、Linux系统的组成部分

Linux系统一般有4个主要部分:内核、shell、文件系统和应用程序。

2.3、系统调用与普通函数调用的区别

1)、系统调用:

  • 使用INT和IRET指令,内核和应用程核态,从而可以使用特权指令操控设备
  • 依赖于内核,不保证移植性
  • 在用户空间和内核上下文环境间切换
  • 是操作系统的一个入口点

2)、普通函数调用:

  • 使用CALL和RET指令,调用时没有堆
  • 平台移植性好
  • 属于过程调用,调用开销较小
  • 一个普通功能函数的调用

2.4、内核态,用户态的区别

内核态,操作系统在内核态运行——运行操作系统程序

用户态,应用程序只能在用户态运行——运行用户程序

2.5、bootloader、内核、根文件的关系

启动顺序:bootloader->linux kernel->rootfile->app

2.6 、Bootloader启动的两个阶段:

Stage1:汇编语言

Stage2:c语言

2.7、linux下检查内存状态的命令

查看进程:top
查看内存:free
cat /proc/meminfo
vmstat

2.8、一个程序从开始运行到结束的完整过程(四个过程)

预处理(Pre-Processing)、编译(Compiling)、汇编(Assembling)、链接(Linking)

2.9、什么是堆,栈,内存泄漏和内存溢出?

栈由系统操作,程序员不可以操作。

所以内存泄漏是指堆内存的泄漏。

堆内存是指程序从堆中分配的,大小任意的,使用完后必须显式释放的内存。应用程序一般使用malloc,new等函数从堆中分配到一块内存,使用完后,程序必须负责相应的调用free或delete释放该内存块,否则,这块内存就不能被再次使用。

内存溢出:你要求分配的内存超出了系统能给你的,系统不能满足需求,于是产生溢出。

内存越界:向系统申请了一块内存,而在使用内存时,超出了申请的范围(常见的有使用定大小数组时发生内存越界)

内存溢出问题是 C 语言或者 C++ 语言所固有的缺陷,它们既不检查数组边界,又不检查类型可靠性(type-safety)。

2.10、死锁的原因、条件

产生死锁的原因主要是:

1)、因为系统资源不足。

2)、进程运行推进的顺序不合适。

3)、资源分配不当等。

2.11、硬链接与软链接

1)、硬链接

硬链接只能引用同一文件系统中的文件。它引用的是文件在文件系统中的物理索引(也称为inode)。当您移动或删除原始文件时,硬链接不会被破坏,因为它所引用的是文件的物理数据而不是文件在文件结构中的位置。

硬链接的文件不需要用户有访问原始文件的权限,也不会显示原始文件的位置,这样有助于文件的安全。如果您删除的文件有相应的硬链接,那么这个文件依然会保留,直到所有对它的引用都被删除。

2)、软链接

软连接,其实就是新建立一个文件,这个文件就是专门用来指向别的文件的(那就和windows 下的快捷方式的那个文件有很接近的意味)。

软连接产生的是一个新的文件,但这个文件的作用就是专门指向某个文件的,删了这个软连接文件,那就等于不需要这个连接,和原来的存在的实体原文件没有任何关系,但删除原来的文件,则相应的软连接不可用。

2.12、中断和异常的区别

内中断:同步中断(异常)是由cpu内部的电信号产生的中断,其特点为当前执行的指令结束后才转而产生中断,由于有cpu主动产生,其执行点必然是可控的。

外中断:异步中断是由cpu的外设产生的电信号引起的中断,其发生的时间点不可预期。

2.13、中断怎么发生,中断处理流程

请求中断→响应中断→关闭中断→保留断点→中断源识别→保护现场→中断服务子程序→恢复现场→中断返回。

2.14、linux下编译优化选项

加:-o

2.15、linux命令

1)、改变文件属性的命令:chmod (chmod 777 /etc/squid 运行命令后,sq
就被修改为777(可读可写可执行))

2)、查找文件中匹配字符串的命令:grep

3)、查找当前目录:pwd

4)、删除目录:rm -rf 目录名

5)、删除文件:rm 文件名

6)、创建目录(文件夹):mkdir

7)、创建文件:touch

8)、vi和vim 文件名也可以创建

9)、解压:tar -xzvf 压缩包

打包:tar -cvzf 目录(文件夹)

10)、查看进程对应的端口号

1、先查看进程pid
ps -ef | grep 进程名
2、通过pid查看占用端口
netstat -nap | grep 进程pid

2.16、硬实时系统和软实时系统

软实时系统:
Windows、Linux系统通常为软实时,当然有补丁可以将内核做成硬实时的系统的。

硬实时系统:
对时间要求很高,限定时间内不管做没做完必须返回。
VxWorks,uCOS,FreeRTOS,WinCE,RT-thread等实时系统;

三、数据结构

3.1、十大排序

我想对于每一个经历过秋招的小伙伴们来说,十大排序基本都被问过(快速排序、归并排序、堆排序、冒泡排序、插入排序、选择排序、希尔排序、桶排序、基数排序)。

对这十大排序的考察主要有两点:
1、考察时间复杂度、空间复杂度、稳定与否。
2、手写某种排序。
第一点:对于时间复杂度的考察,可能会考察插入排序的平均复杂度是多少?最坏和最好复杂度又是多少?有时候也会从别的角度来对你进行考察,直接会问你了解到的的排序中哪些排序是稳定的?哪些不是稳定的?
第二点:快速排序手写次数绝对占据第一名,因为现在企业招聘基本都是有代码要求的,有时候面试官可能也拿不准让你写什么算法题,“算了,写个快排吧”,快排的频率就是就是这样被拉高的;第二高频率的应该就是归并排序了。在笔者秋招过程中,手写过5次归并,3次快排。因为归并是刚好比快排难度大一点,但也不是那种特别难的排序方法。对于女生来说,让手写的排序一般是冒泡排序、快速排序、归并排序,对于男生同学而言,要求手写的排序一般有快速排序、归并排序以及堆排序。
十大排序中考察最多的就是冒泡排序、快速排序、归并排序、堆排序以及可能会出现的桶排序和基数排序了,其余排序出现的概率稍小一点。

3.2、算法

嵌入式考察算法大多都是双向链表、二叉树、字符串翻转和复制这些普通题目。刷题可以在LeetCode、牛客网、杭电OJ等。
十种常见排序算法可以分为两大类:
非线性时间比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此称为非线性时间比较类排序。
线性时间非比较类排序:不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,因此称为线性时间非比较类排序。

3.3、队列和栈的区别有什么?

栈:

栈(stack)又名堆栈,线性表。仅允许在表的一端进行插入和删除运算。这一端为栈顶,另一端为栈底,先进后出。

队列:

队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。

3.4、顺序表和链表他们的特点?

线性表存储数据,需要预先申请一块存储空间,然后将数据按照次序逐一存储,数据之间紧密贴合,不留一丝空隙,

链表的存储方式与顺序表截然相反,什么时候存储数据,什么时候才申请存储空间,数据之间的逻辑关系依靠每个数据元素携带的指针维持

3.5、什么是完全二叉树

如果二叉树中除去最后一层节点为满二叉树,且最后一层的结点依次从左到右分布,则此二叉树被称为完全二叉树。

3.6、什么是二叉树

树有很多种, 每个节点最多只能有两个子节点的叫二叉树

二叉树的子节点分为左节点和右节点

3.7、七大查找算法

顺序查找

二分查找

插值查找

斐波那契查找

树表查找

分块查找

哈希查找

3.8、十大排序排序算法

(1)冒泡排序;

(2)选择排序;

(3)插入排序;

(4)希尔排序;

(5)归并排序;

(6)快速排序;

(7)基数排序;

(8)堆排序;

(9)计数排序;

(10)桶排序;

3.8、怎样判断一个算法的优劣?

时间复杂度

空间复杂度

3.9、"算法"的基本特征有哪些?

一个算法应该具有以下五个重要的特征:

1,有穷性(Finiteness)

2,确切性(Definiteness)

3,输入项(Input)

4,输入项(Input)

5,可行性(Effectiveness)

3.10、什么是哈希表

根据关键码值而直接进行访问的数据结构

3.11、如何判断单链表是否存在环

方法一、穷举遍历

方法二、哈希表缓存

方法三、快慢指针

方法四、Set集合大小变化

3.12、删除链表中倒数第n个节点

要删除倒数第n个节点,我们就要找到其前面一个节点,也就是倒数第n+1个节点,找到这个节点就可以进行删除;
定义两个指针,p和cur,cur指针向前走,走了n+1步之后,p指针开始走,当cur指针走到链表结尾的时候,p指针刚好走到倒数第n+1个节点处。

3.13、循环队列有什么用

为充分利用向量空间,克服"假溢出"现象的方法是:将向量空间想象为一个首尾相接的圆环,并称这种向量为循环向量。

四、进程与线程

4.1、什么是进程、线程、有什么区别

进程是资源(CPU、内存等)分配的基本单位,线程是CPU调度和分配的基本单位(程序执行的最小单位)。

同一时间,如果CPU是单核,只有一个进程在执行,所谓的并发执行,也是顺序执行,只不过由于切换太快,误以为这些进程同步执行。多核CPU可以同一时间点多个进程在执行。

4.2、多进程与多线程的优缺点

1)、一个进程死了不影响其他进程,一个线程奔溃很可能影响1到它本身所处在的线程。

2)、创建多进程的系统花销大于创建多线程。

3)、多进程通讯因为需要跨域进程边界,不适合大量的数据传送,适合小数据或者密集的数据传送。多线程无需跨域进程边界,适合各线程间的大量传送。并且多线程跨域共享同一进程的共享内存和变量。

4.3、什么时候用进程、什么时候用线程

进程间通讯:

(1)、有名管道、无名管道;(2)、信号;(3)、共享内存;(4)、消息队列;(5)、信号量;(6)、socket

线程通讯(锁):

(1)、信号量;(2)、读写锁;(3)、条件变量;(4)、互斥锁;(5)、自旋锁

4.4、父进程、子进程

父进程调用fork()以后,克隆出一个子进程,子进程和父进程拥有相同内容的代码段、数据段和用户堆栈。

父进程和子进程谁先执行不一定,看CPU。所以我们一般会设置父进程等待子进程执行完毕。

4.5、Fork的作用是什么?

在Linux下产生新的进程的系统调用就是fork函数

4.6、fork和vfork的区别

  • fork ():子进程拷贝父进程的数据段,代码段 vfork( ):子进程与父进程共享数据段
  • fork ()父子进程的执行次序不确定 vfork 保证子进程先运行,在调用exec 或exit 之前与父进程数据是共享的,在它调用exec 或exit 之后父进程才可能被调度运行。

4.7、进程的开销比线程大在了哪里?

  • 创建进程需要为进程划分出一块完整的内存空间,有大量的初始化操作,比如要把内存分段(堆栈、正文区等)。
  • 创建线程则简单得多,只需要确定 PC 指针寄存器 的值,并且给线程分配一个 用于执行程序,同一个进程的多个线程间可以复用堆栈
  • 因此,创建进程比创建线程慢,而且进程的内存开销更大。

4.8、什么是阻塞,什么是非阻塞

阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。

非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。

4.9、同步和互斥

互斥 :是指散步在不同任务之间的若干程序片断,当某个任务运行其中一个程序片段时,其它任务就不能运行它们之中的任一程序片段,只能等到该任务运行完这个程序片段后才可以运行。

同步 :是指散布在不同任务之间的若干程序片断,它们的运行必须严格按照规定的某种先后次序来运行,这种先后次序依赖于要完成的特定的任务。

4.10、申请互斥锁的过程

/*头文件*/#include<pthread.h>

1)初始化互斥锁

intpthread_mutex_init(pthread_mutex_t*mutex,constpthread_mutexattr_t*attr);

2)上锁

intpthread_mutex_lock(pthread_mutex_t*mutex);

3)解锁

intpthread_mutex_unlock(pthread_mutex_t* mutex);

4)销毁互斥锁

intpthread_mutex_destroy(pthread_mutex_t*mutex);

4.11、创建守护进程的步骤

  • 创建子进程,父进程退出
  • 子进程下创建新的会话
  • 设置当前目录为根目录
  • 设置文件权限掩码
  • 退出文件描述符

4.12、指出静态库和共享库的区别

静态库编译时程序较大,可以独立运行。

动态库编译时程序交小,不可独立运行。

4.13、什么是 I/O 多路复用?

I/O 通常指网络 I/O,多路指多个 Socket 链接,复用指操作系统进行运算调度的最小单位线程 。整体意思也就是多个网络 I/O 复用一个或少量的线程来处理 Socket。

I/O 多路服用有多种实现模式:

select

poll

epoll

kqueue

1.14、进线程的区别

线程依赖于进程,同一进程的多个线程共享这一进程的资源。 所以进程间的切换会比线程更加的耗时。

1.15、一个程序中最多创建多少个线程

一个线程的栈要预留1M的内存空间,而一个进程中可用的内存空间只有2G,所以理论上一个进程中最多可以开2048个线程,但是内存当然不可能完全拿来作线程的栈,所以实际数目要比这个值要小。

1.16、文件io中的文件描述符

对于Linux而言,所有对设备或文件的操作都是通过文件描述符进行的。

1.17、线程中的同步应该怎么实现

当使用多个线程来访问同一个数据时,非常容易出现线程安全问题(比如多个线程都在操作同一数据导致数据不一致),所以我们用同步机制来解决这些问题。

1.18、进程间通信消息队列的机制

消息队列与命名管道有许多类似之处,但少了在打开和关闭管道时的复杂性。但使用消息队列并未解决我们在使用命名管道时遇到的问题,比如管道满时的阻塞问题。

与命名管道相比,消息队列的优势在于,它独立于发送和接收进程而存在,这消除了在同步命名管道的打开和关闭时可能产生的一些困难。

1.19、什么是进程池

进程池的作用是在多个客户端并发请求时提高服务器的处理效率。

1.20、进程之间通信的途径有哪些?

进程间通讯方式有:管道,信号,信号量,消息队列,共享内存,套接字共六种。

1.21、产生死锁的原因是什么?

系统资源有限。

进程推进顺序不合理。

1.22、进程和线程有什么区别?

进程是资源分配的最小单位。

线程是程序执行的最小单位,

五、网络编程

5.1、TCP、UDP的区别

TCP --> 传输控制协议,提供面向对象连接、可靠的字节流服务。当客户端和服务器交换数据前,必须先在双方之间建立一个TCP连接、之后才能传输数据。

UDP --> 用户数据报协议,是一个简单的面向数据报的运算层协议。UDP不提供可靠性,它是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地。
TCP<–>UDPTCP是面向连接UDP面向无连接UDP程序结构简单TCP是面向字节流UDP是基于数据报TCP保证数据正确性UDP可能丢包TCP保证数据顺序到达UDP不保证数据到达

4.5、TCP、UDP的优缺点

TCP优点:可靠稳定

TCP的可靠体现在TCP在传输数据之前,会有三次握手来建立连接,而且在数据传递时,有确认、窗口、重传、阻塞控制机制,在数据传完之后,还会断开来连接用来节约系统资源。

TCP缺点:慢、效率低、占用系统资源高、容易被攻击

在传递数据之前要建立连接,这会消耗时间,而且在数据传递时,确认机制、重传机制、阻塞机制等会消耗大量时间,而且每台设备上维护所有的传递连接。

UDP优点:快,比TCP稍安全

UDP没有TCP拥有各种机制,是一种无状态的传输协议,所以传输数据非常快,没有TCP整型机制,被攻击的机会就少一些,但也是无法避免被攻击。

UDP缺点:不可靠、不稳定

因为没有TCP的这些机制,UDP在传输数据时,如果网络质量不好,就会容易丢包,造成数据的缺失。

4.5、TCP、UDP适用场景

TCP:传输一些对信号完整性,信号质量有要求的信息。

UDP:对网络通信质量要求不高时,要求网络通信速度要快的场景。

4.5、TCP为什么是可靠连接

因为TCP传输的数据满足3大条件,不丢失,不重复,按顺序到达。

5.6、OSI典型网络模型 ★★★

5.7、三次握手、四次挥手

1)、三次握手过程

  • 第一次握手:建立连接时,客户端发送syn包(syn=x)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。
  • 第二次握手:服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(syn=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;
  • 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。

TCP/IP建立连接是三次握手过程:

第一次:建立连接时,客户端向服务器发送连接请求,进入SYN_END状态,并等待服务器确认。

第二次:服务器收到客户端连接请求,并向客户端发送允许连接应答,进入SYN_RECV状态。

第三次:客户端收到服务器允许连接应答,并向服务器发送确认连接,此时客户端和服务器进入通信状态,三次握手完成。

2)、四次挥手过程

  • 1.客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。
  • 2.服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
  • 3.客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。
  • 4.服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。

[collapse status=“false” title=“常见面试题:”]

【问题1】为什么连接的时候是三次握手,关闭的时候却是四次握手? ★★★

答:三次握手时,服务器同时把ACK和SYN放在一起发送到了客户端那里。

四次挥手时,当收到对方的 FIN 报文时,仅仅表示对方不再发送数据了但是还能接收数据,己方是否现在关闭发送数据通道,需要上层应用来决定,因此,己方 ACK 和 FIN 一般都会分开发送。

【问题2】为什么客户端最后还要等待2MSL?

答:客户端需要保证最后一次发送的ACK报文到服务器,如果服务器未收到,可以请求客户端重发,这样客户端还有时间再发,重启2MSL计时。

【问题3】为什么不能用两次握手进行连接?

答:3次握手完成两个重要的功能,既要双方做好发送数据的准备工作(双方都知道彼此已准备好),也要允许双方就初始序列号进行协商,这个序列号在握手过程中被发送和确认。

【问题4】如果已经建立了连接,但是客户端突然出现故障了怎么办?

TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。

[/collapse]

5.8、常见网络协议

TCP/IP协议

NetBEUI

IPX/SPX协议

5.9、处理粘包问题

解决粘包问题: 就是转换成发送数据和接收数据的格式,

发送数据: 发送数据,先发送数据的长度,然后在发送真实数据的字节数;

接收数据: 接收真实数据的长度,然后在安置字节长度接收数据;

5.10、ip地址分了多少类

A类:0 ~ 127.255.255.255
B类:128 ~ 191.255.255.255
C类:192 ~ 223.255.255.255
D类:224 ~ 239.255.255.255
E类:240 ~ 255.255.255.255

六、C++

最喜欢问的莫过于strlen与sizeof的区别、explicit关键字、mutable关键字、指针和引用、public、protected、private三者在继承情况下的一些访问权限、菱形继承、友元函数等。这些随便一本基础的C++书籍都会讲到。

6.1、构造和析构的作用

构造函数只是起初始化值的作用,但实例化一个对象的时候,可以通过实例去传递参数,从主函数传递到其他的函数里面,这样就使其他的函数里面有值了。

析构函数与构造函数的作用相反,用于撤销对象的一些特殊任务处理,可以是释放对象分配的内存空间

特点:析构函数与构造函数同名,但该函数前面加~。 析构函数没有参数,也没有返回值,而且不能重载

6.2、继承是做什么的?

继承是指一个对象直接使用另一对象的属性和方法

6.3、多态是做什么?

多态首先是建立在继承的基础上的,先有继承才能有多态。多态是指不同的子类在继承父类后分别都重写覆盖了父类的方法,即父类同一个方法,在继承的子类中表现出不同的形式。

6.4、面向对象中的对象指的是什么?

就是实例化了的类。类是属性和方法的封装。对象是 这个类的具体实现。

6.5、类和对象的关系是什么?

对象是类实例化出来的,对象中含有类的属性,类是对象的抽象。

6.6、类的关键词用什么

class

6.7、如果想要在类的外部访问类

C public的类成员

可以作为虚函数的是普通函数,析构函数。

6.8、友元有哪些呢?

友元函数就是以friend开头的一种破坏类的封装性的一种用法

友元类的私有和保护成员在类外不可以使用

6.9、继承的作用是什么?

继承是指在已存在的类的基础上扩展产生新的类。

意义:继承是面向对象程序设计的三大特征(封装、继承和多态)之一

6.10、组合和继承的区别是什么?

组合和继承是面向对象中两种代码复用的方式。组合是指在新类中创建原有类的对象,重复利用已有类的功能。继承是面向对象的主要特性之一,它允许设计人员根据其他类的实现来定义一个类的实现。

6.11、多态指的是什么?

多态首先是建立在继承的基础上的,先有继承才能有多态。多态是指不同的子类在继承父类后分别都重写覆盖了父类的方法,即父类同一个方法,在继承的子类中表现出不同的形式。多态成立的另一个条件是在创建子类时候必须使用父类new子类的方式。

6.12、什么是抽象类,抽象类怎么使用?

抽象类是特殊的类,只是不能被实例化;除此以外,具有类的其他特性;重要的是抽象类可以包括抽象方法,这是普通类所不能的。

如果预计要创建组件的多个版本,则创建抽象类。抽象类提供简单的方法来控制组件版本。
如果创建的功能将在大范围的全异对象间使用,则使用接口。如果要设计小而简练的功能块,则使用接口。
如果要设计大的功能单元,则使用抽象类.如果要在组件的所有实现间提供通用的已实现功能,则使用抽象类。
抽象类主要用于关系密切的对象;而接口适合为不相关的类提供通用功能。

6.13、malloc 和 new的区别?

malloc/free是标准库函数,new/delete是C++运算符

malloc失败返回空,new失败抛异常

new/delete会调用构造、析构函数,malloc/free不会,所以他们无法满足动态对象的要求。

new返回有类型的指针,malloc返回无类型的指针

6.14、深拷贝和浅拷贝的区别是什么?

浅拷贝(shallowCopy)只是增加了一个指针指向已存在的内存地址,

深拷贝(deepCopy)是增加了一个指针并且申请了一个新的内存,使这个增加的指针指向这个新的内存,使用深拷贝的情况下,释放内存的时候不会因为出现浅拷贝时释放同一个内存的错误。

七、Qt

八、ARM体系结构

8.1、讲一讲冯诺依曼和哈佛体系的区别

哈佛结构:

程序和数据分开独立放在不同的内存块中, 彼此完全分离的结构称为哈佛结构。譬如 大部分的单(MCS51、 ARM9等)均采用哈佛结构。

冯·诺伊曼结构:

程序和数据都放在内存中,且不彼此分离 的结构称为冯诺依曼结构。譬如Intel的 CPU均采用冯诺依曼结构。

8.2、什么是ARM体系架构

ARM体系结构包含有:

(1)结构

  • 不同ARM体系采用不同指令集
  • 哈佛结构是将数据与指令分开存储并行
  • 冯诺依曼结构是混合存储的

(2)ARM工作模式

User 、FIQ、IRQ、System、Supervisor、Abort、Undef

(3)寄存器

ARM有37个寄存器

(4)ARM指令机器码

8.3、什么的异常

正常工作之外的流程都叫异常

九、系统移植

9.1、什么是设备树

设备树:用树型结构描述设备节点

十、驱动

10.1、什么是驱动?

控制硬件的软件

驱动是专门为系统编写的配置文件,没有驱动电脑便无法正常运行,简单来说,驱动是连接电脑和其他硬件的必备程序。

十一、Python

十二、单片机

12.1、 IO口工作方式(学过STM32的人应该很熟悉)

上拉输入、下拉输入、推挽输出、开漏输出。

12.2、请说明总线接口USRT、I2C、USB的异同点

串/并、速度、全/半双工、总线拓扑等。

12.3、IIC协议时序图

12.4、单片机的SP指针始终指向

栈顶

12.5、IIC总线在传送数据过程中共有三种类型信号

它们分别是:开始信号、结束信号和应答信号。

12.6、FIQ中断向量入口地址

FIQ和IRQ是两种不同类型的中断,ARM为了支持这两种不同的中断,提供了对应的叫做FIQ和IRQ处理器模式(ARM有7种处理模式)。

FIQ的中断向量地址在0x0000001C,而IRQ的在0x00000018。

12.7、SPI四种模式,简述四种模式,并画出时序图

spi四种模式SPI的相位(CPHA)和极性(CPOL)分别可以为0或1,对应的4种组合构成了SPI的4种模式(mode)

Mode 0 CPOL=0, CPHA=0
Mode 1 CPOL=0, CPHA=1
Mode 2 CPOL=1, CPHA=0
Mode 3 CPOL=1, CPHA=1

简述四种模式,并画出时序图参考链接:https://www.cnblogs.com/gmpy/p/12461461.html

十三、杂项

13.1、高耦合低内聚

高内聚低耦合,是软件工程中的概念,是判断软件设计好坏的标准,主要用于程序的面向对象的设计,主要看类的内聚性是否高,耦合度是否低。目的是使程序模块的可重用性、移植性大大增强。通常程序结构中各模块的内聚程度越高,模块间的耦合程度就越低。

13.2、什么是溢出,什么是越界

溢出本义是算术溢出(arithmetic overflow),指算术计算结果无法在一定范围内表示,细分上溢(overflow)和下溢(underflow)。

越界即访问越界(access out of range),指对存储的访问不在预先指定的界限内。
逻辑上来说可能造成访问越界的计算结果也可以看成一种溢出,这是引申义。只不过两种情况经常一起出现,所以混用了。

跳转:嵌入式软件开发工程师面指南_总结

跳转:嵌入式软件开发工程师面指南_总结

跳转:开头


本文转载自: https://blog.csdn.net/qq_43498137/article/details/121432108
版权归原作者 子羽丿 所有, 如有侵权,请联系我们删除。

“嵌入式软件开发工程师面指南_总结”的评论:

还没有评论