# 写在前面

整体来说,上海中电的技术面让我感觉起来很舒服,很和蔼而且也给了我很多我项目上的建议,还帮分析我向做的远程遥控小车的方案,就很 nice, 要是没有更好的选择基本时就这家了,.

# 面试经历

因为是第二次面试,所以心态也放缓了一些,问了两个项目,一个是智能车,一个是无线智能节点。问了智能车,为什么使用这款摄像头、摄像头采用的协议 sccb, 车辆采用的 rt-thread 的线程安排,为什么要使用 sobel 算子,IIC 多主机请求的仲裁方式,我主要负责那一块。整体上答的还行,还是很愉快的.
然后是无线节点,这个项目问了 ADS1292, 用了什么滤波,这老生常谈了。为什么用用这个滤波,效果最好,能实现的最稳定. 8266 的与 MCU 通信方式,简述一下数据帧结构,说一下 UART 数据帧的结构.
到这里面试官对其他项目就没有什么兴趣了。开始问了一些偏软件的问题,大概包括 C、C++、操作系统、计算机网络、数据库。这一块我就 C 答的还可以,其他就拉了,数据库我学的可认真了,居然全忘了.
虽然,最后面试官觉得我的技术栈基础还可以,最后问了一下我的绩点,唉,我绩点那就是根本看不得。但是很显然有些拉。要不然能拿到更高的实习工资つ﹏⊂.

# 知识点总结

# 关于项目

项目主要还是那些问题,不过这次问了一个新的,关于 IIC 协议
IIC 协议中多主机进行请求的时候,IIC 协议是如何处理的。这个问题比较巧,最近我 IIC 调的比较多,然后重写了一下 IIC 驱动 OLED 的库.
感兴趣的可以去看一下连接
这里简单说一下,IIC 总线自带仲裁机制。无论多少个主机发起请求,第一个拉低 SDA 的主机 获取到当前总线的控制权

# UART 协议

UART 数据帧格式如下
UART
UART 的 空闲电平为 高电平,起始位为 0 , 8 位数据位,低位数据先行先发 LSB (最低位), 一位奇偶校验位,再加上 1 位停止位 (高电平 1)
UART 数据帧各个位详解:

  • 起始位:发送 1 位逻辑 0 (低电平), 开始传输数据.
  • 数据位:可以是 5~8 位的数据,先发低位,再发高位,一般常见的就是 8 位 (1 个字节), 其他的如 7 位的 ASCII 码.
  • 校验位:奇偶校验,将数据位加上校验位,1 的位数为偶数 (偶校验), 1 的位数 4 为奇数 (奇校验).
  • 停止位:停止位是数据传输结束的标志,可以是 1/1.5/2 位的逻辑 1 (高电平).
  • 空闲位:空闲时数据线为高电平状态,代表无数据传输.

# 关于异步

UART 是异步传输,以 1 个字符为传输单位,传输 2 个字符之间的时间间隔,比如传输 0X33 后再传输 0X35, 这两者时间间隔是未知的.
但是同一字符内相邻位间的时间间隔是确定的,比如 0X33 低两位的 1 和 1 之间的时间间隔是确定的,这涉及到 UART 传输速率的概念 —— 波特率.

波特率的单位是 bps , 全称是 bit per second , 意为每秒钟传输的 bit 数量.
波特率 9600bps, 代表每秒钟传输 bit 的数量为 9600, 那么传输 1bit 数据的时间就是 1/9600=104us, 波特率 115200bps, 代表传输 1bit 数据的时间是 8us.

这里说明一下,对于 STM32 来说,最大波特率取决于 时钟主频 HCLK , UART 的频率是主频的 1/8 或 1/16.
如果抛开物理限制,UART 的最大速率为 20kbps.

# 关于传输

大致的说一下,UART 传输的过程.
首先,UART1 以 115200 波特率发送 0X33, 先在数据线上放 1 个 104us 脉宽的低电平 (起始位), 然后是连续 2 个 104us 脉宽的高电平 (2bit 逻辑 1), 依次类推.
其次,UART2 以 115200 波特率接收 0X33, 通过数这些数据的脉宽,来确认数据.

为了确保数据传输的正确性,减少误差,一般 UART1 和 UART2 之间的波特率差别小于 10%, 一次最多只能传输 1 个字节 (8bit), 也有效减小了累计误差.

# C

C 语言这一块还是老样子,问了一下 static 的作用, const 的作用

# C++

# C++ 和 C 最大的区别

这里我回答的是 类、模板、重载,面向对象的思维,这个没有标准答案,就是个过度问题,有理即可

# 如何使用 C 实现 C++ 的重载

这个就很有意思,C++ 的重载机制无非就是在编译的时候重命名函数名。所以我才用函数 ## 运算符和可变参数的方式简单的实现了一下函数重载.
面试官和我说,也可以使用 void* 指针作为参数实现,但是 void* 只能实现一个参数的重载,多参数重载就无法实现.
这一块我还得继续琢磨琢磨。我之前的 重载实现文章可以到这去看看. 传送门
或者看这篇研究传送门

# 数据成员

分为三类:私有、公有、保护.
私有数据成员可以被继承,但是无法被访问.

# MAP 的 特点

真的久了不写算法,数据结构的特性的忘记了.
Map 的特性是 数据以键值对的方式存在,会将数据按 值的大小进行排序.
set 和 map 最大的区别在于,前者 无序去重,后者 有序包重.
其他的数据结构,我下次再开篇文章复习复习

# 操作系统

# 进程和线程的区别

本质区别: 进程是操作系统资源分配的基本单位,而线程是处理器任务调度和执行的基本单位
资源开销: 进程都有独立的代码和数据空间 (上下文), 进程间切换需要大量的保存上下文。线程可以视为轻量级的线程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器
作用力: 一个进程崩溃后,在保护模式下不会对其他进程产生影响,但是一个线程崩溃整个进程都死掉。所以多进程要比多线程健壮
执行过程: 每个独立的进程有程序运行的入口、顺序执行序列和程序出口。但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制,两者均可并发执行

# 进程间通信 (IPC)

我当时就说了消息传递。还是对概念不够清晰
进程间通信 (IPC) 分为 4 大类:

  • 消息传递 (管道、FIFO、消息队列)
  • 同步 (互斥量、条件变量、读写锁、文件和写记录锁、信号量)
  • 共享内存 (匿名的和具名的)
  • 远程过程调用

# 计算机网络

由于我答的很拉跨,ISO 7 层模型都回答的结结巴巴的,就问了一些基础的问题

# ISO 7 层网络模型

名称作用典型服务
应用层所有能和用户交互产生网络流量的程序FTP、SMTP、HTTP
表示层用于处理两个系统中ASCII、JPEG
会话层向表示层 / 用户层进程提供建立连接并在连接上有序的传输数据.(也被称为同步)ADSP、ASP
传输层负责主机之间的通信,端到端的通信,传输单位:报文段 / 数据报TCP、UDP
网络层把分组从源端传输到目的端,分组交换网络的不同主机所提供的通信服务。单位是数据报IP、IPx、ICMP、ARP、OSPF
数据链路层把网络层数据组装成帧,单位为数据帧SDLC、HDLC、PPP、STP
物理层在物理介质上实现网络传输 单位 bitRJ45、802.3

ISO

# 五层网络模型

应用层、传输层、网络层、数据链路层、物理层

# TCP/IP 网络模型

TCP/IP

# TCP 属于那一层的协议

有了上面的巩固,很显然 TCP 是 传输层的协议 (我居然还想了那么久),

# TCP 和 UDP 的区别

这个就很简单了,因为用过所以还是有一定的了解的.
TCP 是可靠稳定的连接,TCP 是一对一,数据模式
UDP 是不可靠连接,UDP 可以 一对一、多对多,流模式

# TCP (Transmission Control Protocol)

TCP 是一个面向连接的协议,即在发数据之前,必须和对方建立可靠连接.
TCP 的建立需要经过三次对话,大致情节模拟一下:

  1. 主机 A 向 主机 B 发出连接请求数据包 A: 我想发数据
  2. 主机 B 向主机 A 发送同意连接和要求同步 B: 可以,什么时候发
  3. 主机 A 再发出一个数据包确认主机 B 的要求同步 A: 我现在就发,你做好准备
# 三次握手过程
  1. 主机 A 发送 一个含有同步序列号的标志位的数据段给主机 B, 向主机 B 请求建立连接.
    这个数据段包含两个信息:我要和你通信;你可以用哪个序列作为其实数据段来回应我
  2. 主机 B 收到 主机 A 请求后,用带有确认的 ACK 和同步序列号 (SYN) 标志的数据段响应主机 A
    这个数据段同样包含两个人信息:我收到了你的请求,你可以传输数据;你要用哪个序列号作为起始数据段来回应我
  3. 主机 A 回复 一个确认 ACK, 建立 TCP 连接
    这里只含有一个信息,我收到了回复,将要开始传输数据了.

特点:没有应用层的数据,这里仅仅是建立连接, SYN 这个标志位值只可能在 TCP 建立连接的时候置 1, 握手结束后 SYN 被置 0

# 四次挥手过程

第一次:当主机 A 完成数据传输后,将控制位 FIN 置 1, 提出停止 TCP 连接的请求
第二次:主机 B 收到 FIN 后对其作出响应,确认这一方向上的 TCP 连接将关闭,将 ACK 置 1
第三次:由 B 端再提出反方向的关闭请求,将 FIN 置 1
第四次:主机 A 对主机 B 的请求进行确认,将 ACK 置 1, 双方向的关闭结束

由 TCP 的三次握手和四次断开可以看出,TCP 使用面向连接的通信方式,大大提高了数据通信的可靠性,使发送数据端和接收端在数据正式传输前就有了交互,为数据正式传输打下了可靠的基础

# 为什么要三次握手

个人觉得是为了确认当前通信的信道可用,尤其是当 TCP 发生断开重连后,单单一次应答无从确定连接时本次新连接的 ACK 还是旧链接延时的 ACK. 而且所谓的三次握手也是确定一个信道是否有效的最少次数.
TCP 的可靠性依赖于 seq 序列号来实现。通过 sqe 序号的来实现可靠重传,从而避免连接复用的时候无法分别出 seq 是延时或者是 旧链接的 seq , 因此需要三次握手来确定双方的 ISN ( ISN 是初始的 seq 序列号)

再挖细一点,还是上面那个依据

TCP 的可靠性是依靠 swq 实现的.(seq 全程为 sequence numbers )

TCP 协议在被制定的时候就有一个基本设定,通过 TCP 发出的每一个包,都有一个 sequence numbers . sequence numbers 为有序值,所以所有的包都可以被确认收到.
确认机制是累计的,对于一个 sequence numbers x 的确认,这代表 x 系列号之前的包都是被确认的。当然,不包括 x.
TCP 协议没有限制一个重复的连接被重复使用的。这时候,就有了 上面所说的问题:这条连接突然断开重连后,TCP 怎么样识别之前旧链接重发的包?
这就是需要上面所提到 ISN 校对的价值了.
每当生成一个新的连接的时候,都会有一个初始序列号 (Initial Sequence Number ISN) 生成器会生成一个新的 32 位的 ISN.
这个生成器会使用一个 32 位的时钟,大约 每 4µs 进行一次 inc, 所以 ISN 会在大约 4.55 小时循环一次。一般来说,在网络中并不会比最大分段寿命 (Maximum Segment Lifetime (MSL)), 默认使用 2 分钟长. MSL 远比 4.55 小时要多的多,所以可以认定 ISN 唯一
发送方与接收方都会有自己的 ISN (下面的例子中就是 X 与 Y) 来做双方互发通信,具体的描述如下:

  1. A --> B SYN my sequence number is X
  2. A <-- B ACK your sequence number is X
  3. A <-- B SYN my sequence number is Y
  4. A --> B ACK your sequence number is Y

2 与 3 都是 B 发送给 A, 因此可以合并在一起,因此成为 three way (or three message) handshake (其实翻译为三步握手,或者是三次通信握手更为准确)

三次握手 (A three way handshake) 是必须的,因为 sequence numbers 没有绑定到整个网络的全局时钟 (全部统一使用一个时钟,就可以确定这个包是不是延迟到的) 以及 TCPs 可能有不同的机制来选择 ISN (初始序列号).
接收方接收到第一个 SYN 时,没有办法知道这个 SYN 是是否延迟了很久了,除非他有办法记住在这条连接中,最后接收到的那个 sequence numbers (然而这不总是可行的)
这句话的意思是:一个 seq 过来了,跟现在记住的 seq 不一样,我怎么知道他是上条延迟的,还是上上条延迟的呢?
所以,接收方一定需要跟发送方确认 SYN

假设不确认 SYN 中的 seq , 那么就只有:

  1. A --> B SYN my sequence number is X
  2. A <-- B ACK your sequence number is X SYN my sequence number is Y

只有 B 确认了收到了 A 的 seq , A 无法认收到 B 的。也就是说,只有 A 送给 B 的包都是可靠的,而 B 送给 A 的则不是,所以这不是靠的连接.
这种情况如果只需要 A 发送给 B , B 无需回,则可以不做三次次握手.

TCP 的包头结构

源端口 16 位目标端口 16 位
序列号 32 位
回应序号 32 位
TCP 头长度 4 位reserved 6 位控制代码 6 位窗口大小 16 位
偏移量 16 位校验和 16 位
选项 32 位 (可选)

# UDP (User Data Protocol)

  1. UDP 是一个非连接的协议,传输数据之前源端和终端不建立连接,当它想传送时就简单地去抓取来自应用程序的数据,并尽可能快地把它扔到网络上.
    在发送端,UDP 传送数据的速度仅仅是受应用程序生成数据的速度、 计算机的能力和传输带宽的限制;在接收端,UDP 把每个消息段放在队列中,应用程序每次从队列中读一个消息段.
  2. 传输数据不建立连接,因此也就不需要维护连接状态,包括收发状态等,因此一台服务机可同时向多个客户机传输相同的消息
  3. UDP 信息包的标题很短,只有 8 个字节,相对于 TCP 的 20 个字节信息包的额外开销很小
  4. 吞吐量不受拥挤控制算法的调节,只受应用软件生成数据的速率、传输带宽、 源端和终端主机性能的限制
  5. UDP 是面向报文的,发送方的 UDP 对应用程序交下来的报文,在添加首部后就向下交付给 IP 层

ping 命令就是 UDP, ping 是使用 IP 和网络控制信息协议 (ICMP), 因而没有涉及到任何传输协议 (UDP/TCP) 和应用程序。它发送 icmp 回送请求消息给目的主机

# UDP 的包头
源端口 16 位目的端口 16 位
长度 16 位校验和 16 位

# Sokect 的常用函数

这个我就记得一个 bind. 唉,真就是废了.

# socket 基本操作

  1. socket () 函数
  2. bind () 函数
  3. listen () 函数 connect () 函数
  4. accept () 函数
  5. read () 函数 wriet () 函数
  6. close () 函数

# 数据库

这个比上面那个还要拉,第一个问题就死了,我就记得一个原子性

# 事务的性质

  1. 原子性:事务的原子性是指事务中包含的所有操作要么全做,要么全不做 (all or none).
  2. 一致性:在事务开始以前,数据库处于一致性的状态,事务结束后,数据库也必须处于一致性状态.
  3. 隔离性:事务隔离性要求系统必须保证事务不受其他并发执行的事务的影响,也即要达到这样一种效果:对于任何一对事务 T1 和 T2, 在事务 T1 看来,T2 要么在 T1 开始之前已经结束,要么在 T1 完成之后才开始执行
  4. 持久性:一个事务一旦成功完成,它对数据库的改变必须是永久的,即便是在系统遇到故障的情况下也不会丢失

大道五十,天衍四十九,人遁其一!

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

黑羊 支付宝

支付宝