1、ROM和RAM的区别
ROM是只读存储器,掉电不丢失(记住O-是only-就是-只,即只读),永久保存,不能进行修改,常用于存储计算机启动用的BIOS芯片等。
RAM是读写存储器,掉电丢失;如计算机内存等
三种RAM:
- SRAM:CPU的缓存就是SRAM,静态的随机存取存储器,加电情况下,不需要刷新,数据不会丢失
- DRAM,动态随机存取存储器最为常见的系统内存,需要不断刷新,才能保存数据
- SDRAM:同步动态随机存储器,即数据的读取需要时钟来同步。
实际的时候,可能会问道flash和eeprom等的知识点,这个在嵌入式开发很常用:
EEPROM(带电可擦写可编程只读存储器)是用户可更改的只读存储器,其可以通过高于普通电压的作用来擦除和重编程(重写)。这使得EEPROM在需要频繁修改数据的场合,如系统配置参数的存储等,具有广泛的应用。
Flash存储器,也被称为闪存,结合了ROM和RAM的长处。它既有EEPROM的特点,也有RAM的特点,是一种全新的存储结构。Flash存储器不仅具备电子可擦除可编程(EEPROM)的性能,还可以快速读取数据,使得数据不会因为断电而丢失。因此,Flash存储器在计算机系统中常用于存储需要频繁擦写且需要保持数据不丢失的数据。
在单片机系统中,RAM主要作为运行时数据存储器,Flash主要用于存储程序,而EEPROM则用于在程序运行时保存一些需要掉电不丢失的数据。
2、编译和链接有什么不同?(如外部符号的处理)
编译生成的是目标文件(object *.o); 编译过程中对于外部符号不做任何解释和处理。外部符号对应的就是“符号”
链接生成的是可执行程序; 链接将会解释和处理外部符号。外部符号对应的是地址;
再次回顾一下编译过程:
此处简单描述一个test.c如何编译成一个二进制文件test的过程来进行:
1.预处理:宏内容替换,#include内容替换等
gcc -E test.c -o test.i
2编译:编译为汇编代码,输出汇编代码文件
gcc -S test.i -o test.s
3.汇编:将汇编代码文件编译为目标文件
gcc -C test.s -o test.o
4.链接:将目标文件与所需的附加目标文件(静态链接库和动态链接库
标准输入输出库)连接起来,最终生成可执行文件test
gcc test.o -o test整个过程我们我们可以用ESC(电脑左上角的按键速记) 和 iso(苹果系统简称速记)。
这个对一些初级的工程师,是比较容易考的到;
3、实现拷贝操作:
已知strcpy函数的函数原型是char *strcpy(char *strDest, const char *strSrc)。其中,strDest是目的字符串,strSrc是源字符串。
不调用C++/C的字符串库函数,请编写函数strcpy
答:
char *strcpy(char *strDest, const char *strSrc)
{
int i=0;
if(!(strDest && strSrc))
return;
while(strDest[i++] = *strSrc++);
return strDest;
}
4、strcpy能把strSrc的内容复制到strDest,为什么还要char *类型的返回值?
为了实现链式操作:返回 strDest
的指针(也就是复制后的目标字符串的起始地址)允许进行链式操作。例如,你可以将 strcpy
的返回值直接传递给另一个函数,或者连续进行多次字符串复制操作。或者如下
int len = strlen(strcpy(strDest, strSrc));
其次,这也是一种错误检查;并且这是一种常见的编程习惯。符合C语言习惯!
5、说明下面的Const声明的含义:
A.
const int a; // a是一个常数
int const a; // a是一个常数
B.
const int *a; // a是一个指向整型常数的指针
int * const a; // a是一个指向整型变量的常指针
int const * a const; // a是一个指向整型常数的常指针
C.
char *strcpy(char *strDest, const char *strSrc);// 参数在函数内部不会被修改
const int strcmp(char *source, char *dest); // 函数的返回值不能被修改
const int a = strcmp(xx, yy);
if(strcmp(xx,yy) != 0)
6、说明关键字volatile有什么含意,并给出例子。
volatile表示被修饰的符号是易变的。告诉编译器不要随便优化我的代码!!
*一个硬件寄存器
*中断中用到的变量
*线程之间共享变量
volatile int a = 10;
while((a & 0x01) == 0);
#define P_UART_STATUS ((const volatile unsigned int *)0x88000000);
// volatile表示硬件会修改这个寄存器的内容
// const表示该寄存器只读,写无意义
7、printf可以接受多个参数,为什么,请写出printf的原型。
int printf(const char *fmt, ...);
其中第一个实参是格式化字符串,第二个实参是可变参数列表;
8、什么是堆栈,简述为什么需要堆栈?
堆栈是计算机中最常用的一种数据结构,只能在一端(称为栈顶)进行数据项的插入和删除。这种数据结构严格遵循“先进后出”(FILO,First In Last Out)的原则进行存取;
他的运用非常广泛:
内存管理:堆栈用于动态地分配和回收内存空间,这使得程序能够灵活地运行。
函数调用:堆栈在函数调用时发挥着重要作用。当函数被调用时,它的临时变量和返回地址等信息会被存储在堆栈中,以确保函数能够正常执行并返回到调用点
数据保护和恢复:在单片机应用中,堆栈用于函数调用、中断切换时保存和恢复现场数据,确保了数据的安全性和完整性
9、请列举常用的串行通信方式(两种以上),并简述串行通信和并行通信不同之处、优缺点。
答:SPI、I2C、串口等
异步通信和同步通信优缺点:
- 并行传输速度快,适合外部设备与微机之间进行近距离、大量和快速的信息交换。然而,其缺点也很明显,比如线路复杂、传输距离短、抗干扰能力差、成本高等
- 串行口优点在于线路简单,传输距离远,成本低。但由于逐个比特位传输,其传输速度相对较慢,且故障率较高;
10、列举一下你熟悉7层OSI协议中的几层。说说你最熟悉的一层协议的功能。
应用层,表示层,会话层,传输层,网络层,数据链路层,物理层。
速记:物联网 输会适用!
- 应用层:为应用程序提供交互服务。它是用户与计算机进行实际通信的地方,主要处理一些终端的应用,如FTP、浏览器、微信等。应用层协议有很多,如域名系统DNS、HTTP协议、SMTP协议等。
- 表示层:负责数据格式的转换,如加密解密、压缩解压缩等。它将计算机能够识别的东西转化为人能够识别的东西,确保发送方和接收方使用相同的数据表示方法。
- 会话层:负责在网络中的两个节点之间建立、维持和终止通信。它负责解决节点链接的协调和管理,同步两个节点之间的对话,并决定通信是否被中断以及通信中断时从何处重新发送。
- 传输层:负责向两台主机进程之间的通信提供数据传输服务。它定义了一些传输数据的协议和端口,如TCP、UDP协议,主要将从下层收到的数据进行分段和传输,达到目的地址后进行重组。
- 网络层:选择合适的路由和交换结点,确保数据及时传送。它将下层接收到的数据进行IP地址的封装和解封装,并负责设备的寻址,跟踪网络中设备的位置,并决定传送数据的最佳路径。
- 数据链路层:将网络层传下来的IP数据包组装成帧,并再相邻节点的链路上传送帧。它主要将从物理层接收的数据进行MAC地址的封装与解封装,并提供数据的物理传输,处理出错通知、网络拓扑和流量控制。
- 物理层:是OSI模型中的最低层,直接面向实际承担数据传输的物理媒体(即通信通道)。它的传输单位为比特(bit),即一个二进制位(0或1)。物理层的功能有两个:发送和接收位流,并尽可能屏蔽传输介质和通信手段的差异。
11、简述几个常用的路由协议
RIP(路由信息协议):RIP协议主要用于一个AS(自治系统)内的路由信息的传递,每30s发送一次路由信息更新
OSPF(开放式最短路径优先):这是一个用于网际协议(IP)网络的链路状态路由协议
IGRP(内部网关路由协议):这是一个Cisco私有协议,又译网关间选径协议,是一种内部网关协议,采用距离向量算法
EIGRP(增强型内部网关路由协议):由于IGRP协议的种种缺陷以及不足,Cisco开发了EIGRP协议来取代IGRP协议
BGP(边界网关协议):这是一个运行于TCP上的自治系统间的路由协议,多用于不同ISP之间交换路由信息,以及大型企业、*等具有较大规模的私有网络 。
网关-网关协议,外部网关协议,内部网关协议(RIP-1、RIP-IGRP、EIGRP、IS-IS和OSPF)
12、写一个实现位转换的程序
位 8 7 6 5 4 3 2 1
数 v8 v7 v6 v5 v4 v3 v2 v1
转换后:位 8 7 6 5 4 3 2 1
数 v1 v2 v3 v4 v5 v6 v7 v8
答:
unsigned char bit_reverse(unsigned char c)
{
unsigned char buf = 0;
int bit = 8;
while(bit)
{
bit--;
buf |= ((c & 1) << bit);
c >>=1;
}
return buf;
}
13、实现一个字符串倒序的程序。
答:
1)、inverted_order(char *p)
{
char *s1,*s2,tem;
s1=p;
s2=s1+strlen(p)-1;
while(s1<s2)
{
tem=*s1;
*s1=*s2;
*s2=tem;
s1++;
s2--;
}
}
2)、inverted_order(char *p)
{
int len = strlen(src);
char *des = (char *)malloc(len + 1);
char *s = &src[len -1];
char *d = des;
while(len-- != 0)
*d++ = *s--;
*d = 0;
free(des);
}
14、引用和指针的区别
(1). 指针是一个实体,而引用仅是个别名;
(2). 引用使用时无需解引用(*),指针需要解引用;
(3). 引用只能在定义时被初始化一次,之后不可变;指针可变;
(4). 引用没有 const,指针有 const,const 的指针不可变;
(5). 引用不能为空,指针可以为空;
(6). “sizeof 引用”得到的是所指向的变量(对象)的大小,
而“sizeof指针”得到的是指针本身(所指向的变量或对象的地址)的大小;
(7). 指针和引用的自增(++)运算意义不一样;
15、队列和栈的区别
队列是先进先出,只能在一端插入另一端删除,可以从头或尾进行遍历(但不能同时遍历)
栈是先进后出,只能在同一端插入和删除,只能从头部取数据
16四层模型?七层模型?TCP/IP协议包括?
这7层是:物理层、数据链路层、网路层、传输层、话路层、表示层和应用层
这4层分别为:应用层、传输层、网络层、链路层。
TCP/IP协议族包括:(IP)、(ARP)、(RARP)、(ICMP)、(UDP)、(TCP)、(RIP)、Telnet、(SMTP)、DNS等协议。
17、TCP通信建立和结束的过程?端口的作用
三次握手和四次挥手;见分析--TCP的三次握手与四次挥手理解及面试题(很全面)-****博客
第一次握手:建立连接时,客户端发送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连接成功)状态,完成三次握手。
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(最后确认)状态,等待客户端的确认。
5)客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。
6)服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。
端口是一个软件结构,被客户程序或服务进程用来发送和接收信息。一个端口对应一个16比特的数。服务进程通常使用一个固定的端口。
21端口:21端口主要用于FTP(File Transfer Protocol,文件传输协议)服务。 23端口:23端口主要用于Telnet(远程登录)服务,是Internet上普遍采用的登录和仿真程序。
25端口:25端口为SMTP(Simple Mail TransferProtocol,简单邮件传输协议)服务器所开放,
主要用于发送邮件,如今绝大多数邮件服务器都使用该协议。
53端口:53端口为DNS(Domain Name Server,域名服务器)服务器所开放,
主要用于域名解析,DNS服务在NT系统中使用的最为广泛。
67、68端口:67、68端口分别是为Bootp服务的Bootstrap Protocol Server
(引导程序协议服务端)和Bootstrap Protocol Client(引导程序协议客户端)开放的端口。
69端口:TFTP是Cisco公司开发的一个简单文件传输协议,类似于FTP。
79端口:79端口是为Finger服务开放的,主要用于查询远程主机在线用户、操作系统类型以及是否缓冲区溢出等用户的详细信息。880端口:80端口是为HTTP(HyperText Transport Protocol,超文本传输协议)开放的,
这是上网冲浪使用最多的协议,主要用于在WWW(World Wide Web,万维网)服务上传输信息的协议。
99端口:99端口是用于一个名为“Metagram Relay”(亚对策延时)的服务,
该服务比较少见,一般是用不到的。
109、110端口:109端口是为POP2(Post Office Protocol Version 2,邮局协议2)服务开放的,
110端口是为POP3(邮件协议3)服务开放的,POP2、POP3都是主要用于接收邮件的。
111端口:111端口是SUN公司的RPC(Remote Procedure Call,远程过程调用)服务所开放的端口,
主要用于分布式系统中不同计算机的内部进程通信,RPC在多种网络服务中都是很重要的组件。
113端口:113端口主要用于Windows的“Authentication Service”(验证服务)。
119端口:119端口是为“Network News Transfer Protocol”(网络新闻组传输协议,简称NNTP)开放的。
135端口:135端口主要用于使用RPC(Remote Procedure Call,远程过程调用)协议并提供DCOM(分布式组件对象模型)服务。
137端口:137端口主要用于“NetBIOS Name Service”(NetBIOS名称服务)。
139端口:139端口是为“NetBIOS Session Service”提供的,主要用于提供Windows文件和打印机共享以及Unix中的Samba服务。
143端口:143端口主要是用于“Internet Message Access Protocol”v2(Internet消息访问协议,简称IMAP)。
161端口:161端口是用于“Simple Network Management Protocol”(简单网络管理协议,简称SNMP)。
443端口:43端口即网页浏览端口,主要是用于HTTPS服务,是提供加密和通过安全端口传输的另一种HTTP。
554端口:554端口默认情况下用于“Real Time Streaming Protocol”(实时流协议,简称RTSP)。
1024端口:1024端口一般不固定分配给某个服务,在英文中的解释是“Reserved”(保留)。
1080端口:1080端口是Socks代理服务使用的端口,大家平时上网使用的WWW服务使用的是HTTP协议的代理服务。
1755端口:1755端口默认情况下用于“Microsoft Media Server”(微软媒体服务器,简称MMS)。
4000端口:4000端口是用于大家经常使用的QQ聊天工具的,再细说就是为QQ客户端开放的端口,QQ服务端使用的端口是8000。
5554端口:在今年4月30日就报道出现了一种针对微软lsass服务的新蠕虫病毒——震荡波(Worm.Sasser),该病毒可以利用TCP 5554端口开启一个FTP服务,主要被用于病毒的传播。
5632端口:5632端口是被大家所熟悉的远程控制软件pcAnywhere所开启的端口。
8080端口:8080端口同80端口,是被用于WWW代理服务的,可以实现网页浏览。
18、有哪些物理地址和IP地址的转换协议?
地址解析协议(ARP)的作用是将IP地址转换成物理地址;
反地址解析协议(RARP)则负责将物理地址转换成IP地址。
19、已知数组table,用宏求元素个数。
#define COUNT(table) (sizeof(table)/sizeof(table[0]))
sizeof
返回整个数组的大小。而对于数组中的单个元素table[0]),sizeof
返回该元素的大小。因此,通过将整个数组的大小除以单个元素的大小,可以得到数组的元素个数。