嵌入式常用定义整理
- 简述常见的嵌入式存储器和特点(4种以上)。
- ROM、SRAM、DRAM。
根据掉电数据是否丢失,存储器可以分为RAM(随机存取器)和ROM(只读存储器),其中RAM的访问速度比较快,但掉电后数据会丢失,而ROM掉电后数据不会丢失。人们通常所说的内存即指系统中的RAM。
RAM又可分为SRAM(静态存储器)和DRAM(动态存储器)
SRAM是利用双稳态触发器来保存信息的,只要不掉电,信息是不会丢失的。
DRAM是利用MOS(金属氧化物半导体)电容存储电荷来储存信息的,因此必须通过不停的给电容充电来维持信息。DRAM的成本、集成度、功耗明显优于SRAM。
通常人们所说的SDRAM是DRAM的一种,它是同步动态存储器,利用单一的系统时钟同步所有的地址数据和控制信号。使用SDRAM不但能提高系统的表现,还能简化设计、提供高速的数据传输,在嵌入式系统中经常使用。
- Flash是一种非易失闪存技术,由于它具有和ROM一样掉电数据不会丢失的特性。Flash主要分为NOR Flash和NAND Flash两种。
NOR Flash的特点是在芯片内执行(Execute In Place),这样应用程序可以直接在Flash内运行,不必再把代码读到系统RAM中。
NAND Flash能提供极高的单元密度,可以达到高存储密度,NAND读和写操作采用512字节块,单元尺寸几乎是NOR器件的一半,同时由于生产过程很简单,大大降低了生产的成本。NAND Flash中每个块的最大擦写次数是100万次,是NOR Flash的10倍,这些使得NAND Flash越来越受到人们的喜爱。
- 简述常见嵌入式软件交叉调试方式,并简单描述。
软件交叉调试方式主要是通过插入调试桩的方式来进行的。调试桩方式进行调试是通过目标操作系统和调试器内分别加入某些功能模块,两者互通信息来进行调试。该方式的典型调试器有Gdb调试器。
Gdb的交叉调试器分为GdbServer和GdbClient,其中GdbServer就作为调试桩在安装在目标板上,GdbClient就是驻于本地的Gdb调试器。
它们的调试原理图如图所示:
- Linux中函数库有那3种使用方式,简述之。
Linux中函数库可以有三种使用的形式:静态、共享和动态。静态库的代码在编译时就已连接到开发人员开发的应用程序中,而共享库只是在程序开始运行时才载入。
动态库也是程序运行时载入,但是与共享库不同的是,动态库使用的库函数不是在程序运行使开始载入,而是在程序中的语句需要时使用时才载入。动态库可以在程序运行期间释放动态库所占用的内存,腾出空间供其他程序使用。
由于共享库和动态库并没有在程序中包括库函数的内容,只是包含了对库函数的引用,因此代码的规模比较小。
- 简述栈和堆的区别。
栈是由编译器在需要时分配的,不需要时自动清除的变量存储区。里面的变量通常是局部变量、函数参数等。堆是由malloc()函数(C++语言为new运算符)分配的内存块,内存释放由程序员手动控制,在C语言为free函数完成(C++中为delete)。栈和堆的主要区别有以下几点:(1)管理方式不同。栈编译器自动管理,无需程序员手工控制;而堆空间的申请释放工作由程序员控制,容易产生内存泄漏。(2)空间大小不同。栈是向低地址扩展的数据结构,是一块连续的内存区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,当申请的空间超过栈的剩余空间时,将提示溢出。因此,用户能从栈获得的空间较小。堆是向高地址扩展的数据结构,是不连续的内存区域。因为系统是用链表来存储空闲内存地址的,且链表的遍历方向是由低地址向高地址。由此可见,堆获得的空间较灵活,也较大。栈中元素都是一一对应的,不会存在一个内存块从栈中间弹出的情况。(3)是否产生碎片。对于堆来讲,频繁的malloc/free(new/delete)势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低(虽然程序在退出后操作系统会对内存进行回收管理)。对于栈来讲,则不会存在这个问题。
(4)增长方向不同。堆的增长方向是向上的,即向着内存地址增加的方向;栈的增长方向是向下的,即向着内存地址减小的方向。(5)分配方式不同。堆都是程序中由malloc()函数动态申请分配并由free()函数释放的;栈的分配和释放是由编译器完成的,栈的动态分配由alloca()函数完成,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行申请和释放的,无需手工实现。(6)分配效率不同。栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行。堆则是C函数库提供的,它的机制很复杂,例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考数据结构/操作系统)在堆内存中搜索可用的足够大的空间,如果没有足够大的空间(可能是由于内存碎片太多),就有需要操作系统来重新整理内存空间,这样就有机会分到足够大小的内存,然后返回。显然,堆的效率比栈要低得多。
- 简述什么是系统调用;
系统调用是操作系统提供给外部程序的接口。在C语言中,操作系统的系统调用通常通过函数调用的形式完成。因为这些函数封装了系统调用的细节,将系统的调用的入口、参数以及返回值用C语言的函数调用过程实现。在Linux系统中,系统调用函数定义在glibc中。系统调用需要注意以下几点。
(1)系统调用函数通常在成功时返回0值,不成功时返回非0值。如果要检查失败原因,则要判断全局变量errno的值,errno中包含错误代码。
(2)许多系统调用的返回数据通常通过引用参数传递。这时,需要在函数参数传递缓冲去地址,而返回的数据就保存在该缓冲区中。
(3)不能认为系统调用函数比其他函数的执行效率高。因为系统调用是一个非常耗时的过程。
- 简述chmod 文件权限0-7的含义。
- Linux I/O处理5种模型的名称。
总体来说,I/O处理的模型有5种。
(1)阻塞I/O模型:在这种模型下,若所调用的I/O函数没有完成相关功能就会使进程挂起,直到相关数据到才会出错返回。如常见对管道设备,终端设备和网络设备进行读写时经常会出现这种情况。
(2)非阻塞I/O模型:在这种模型下,当所请求的I/O的操作不能完成时,则不让进程睡眠,而且立即返回。非阻塞I/O使用户可以调用不会阻塞的I/O操作如open、write和read。如果该操作不能完成,则会立即返回出错或者返回0。
(3)多路选择I/O模型,在这种模型下,如果请求的I/O操作阻塞,且它不是真正阻塞I/O,而是让其中的一个函数等待,在这期间,I/O还能进行其他操作。如select和poll函数。
(4)信号驱动I/O模型,在这种模型下,通过安装一个信号处理程序,系统可以自动捕获特定信号的到来,从而启动I/O。
(5)异步I/O模型,在这种模型下,当一个描述符已准备好,可以启动I/O时,进程会通知内核,但并不所有的系统都支持这种模型。
- 串口初始化设置波特率115200,8个数据位,1特停止位,无奇偶校验,请写出初始化程序。
- 简述进程和程序的区别。
进程是一个程序的一次执行的过程,同时也是资源分配的最小单元。它和程序有本质区别的,程序是静态的,它是一些保存在磁盘上的指令的有序集合,没有任何执行的概念;而进程是一个动态的概念,它是程序执行的过程,包括了动态创建、调度、和消亡的整个过程。它是程序执行的资源管理的最小单位。因此,对系统而言,当用户在系统中键入命令执行一个程序时候,它将启动一个进程。
- 简述Linux进程5种状态。
- 运行(TASK_RUNNING):一般指就绪状态,也就是指进程随时可以投入到运行和运行状态。
- 可中断(TASK_INTERUPTIBLE):在这个状态时进程停止运行,直到它获得满足它继续运行的条件。
- 不可中断(TASK_UNINTERUPTIBLE):在这个状态时进程也是停止运行,但是,即便它获得满足它继续运行的条件,它也不会马上被激活。
- 僵死(TASK_ZOMBIE):进程运行结束,等待父进程销毁它。
- 停止(TASK_STOPPED):进程停止运行,当进程收到SIGSTOP、SIGTSTP、SIGTTIN、SIGTTOU等信号,就会停止。在调试期间,进程收到任何信号,也会停止运行。
- 什么是管道,简要描述有名管道和无名管道。
管道是Linux中进程间通信的一种方式,它把一个进程的输出直接连接到另一个进程的输入。Linux的管道主要包括两种:无名管道和有名管道。
无名管道是一种专门用来实现进程间通信的特殊文件,和普通文件有一定的差异:无名管道只能存在于进程进程通信期间,通信完成后将自动消失,而且只能临时存放通信的信息,不能像普通文件一样存储大量常规信息。但是,在编程应用方式,具有和普通文件一样的特点,可以使用read/write等函数进行读写操作,但不能使用lseek函数来修订当前的读写位置,因为管道需要满足FIFO的原则。
有名管道和普通文件一样具有文件存放路径、文件权限,存在于磁盘中;但是,有名管道和普通文件又有区别,有名管道不能直接存储文件,它存储的通信信息在两个进程结束后自动丢失。通信的两个进程结束后,有名管道的文件本身仍然存在,这是和无名管道不一样的地方。
- TCP/IP协议四层模型名称和功能。
网络接口层:负责将二进制流转换为数据帧,并进行数据帧的发送和接收。数据帧是独立的网络信息传输单元。
网络层:负责将数据帧封装成IP数据包,并运行必要的路由算法。
传输层:负责端到端之间的通信会话连接与建立。传输协议的选择根据数据传输方式而定。
应用层:负责应用程序的网络访问,这里通过端口号来识别各个不同的进程。
- 常见的Socket有哪三种,分别描述。
- 流式socket(SOCK_STREAM)流式:流式套接字提供可靠的、面向连接的通信流;它使用TCP协议,从而保证了数据传输的正确性和顺序性。
- 数据报socket(SOCK_DGRAM)数据报套接字定义了一种无连接的服务,数据通过相互独立的报文进行传输,是无序的,并且不保证是可靠的、无差错的。它使用数据报协议UDP。
- 原始socket:原始套接字允许对底层协议如IP和ICMP进行直接访问,它功能强大但使用较为不便,主要用于一些协议的开发。
- 用Socket实现TCP通信服务端程序,接收客户端内容并打印到终端。
- 用Socket实现TCP通信客户端程序,客户端向服务端发送hello world 信息。
选择题
1:设float a=2, b=4, c=3;,以下C语言表达式与代数式 (a+b)+c计算结果不一致的是
A.(a+b)*c/2
B.(1/2)*(a+b)*c
C.(a+b)*c*1/2
D.c/2*(a+b)
参考答案:B,因为a,b,c三个变量都是浮点数,所以在B答案中其结果是0,因为在计算1/2是就是0,如果改成1/2.0就正确了。
2:为了向二进制文件尾部增加数据,打开文件的方式应采用
A.″ab″
B.″rb+″
C.″wb″
D.″wb+″
参考答案:D
3:下述程序执行后的输出结果是
#include
main()
{
int x='f';
printf("%c ",'a'+(x-'a'+1));
}
A.g
B.h
C.i
D.j
参考答案:A
4:C语言中,下列运算符优先级最高的是
A.!
B.%
C.>>
D.= =
参考答案:A
5:数组定义为" int a [ 4 ] ; ",表达式 ( ) 是错误的。
A.*a
B.a [ 0 ]
C.a
D.a++
参考答案:D
6:执行语句" k=7>>1; "后,变量 k 的当前值是
A.15
B.31
C.3
D.1
参考答案:C
7:定义函数时,缺省函数的类型声明,则函数类型取缺省类型
A.void
B.char
C.float
D.int
参考答案:D
8:若main()函数带参数,参数个数最多是
A.0
B.1
C.2
D.3
参考答案:C 只知道有定义形式main(int argc,char* argv[]))
9:若有宏定义:#define MOD(x,y) x%y
则执行以下语句后的输出结果是
int a=13,b=94;
printf(″%d ″,MOD(b,a+4));
A.5
B.7
C.9
D.11
参考答案:B
10:下列各个错误中,哪一个不属于编译错误
A.改变 x 原值 3 为 5 ,写作" x==5 ;"
B.花括号不配对
C.复合语句中的最后一条语句后未加分号
D.变量有引用、无定义
参考答案:A
11:下列程序段运行后, x 的值是( )
a=1;b=2;x=0;
if(!( -- a))x -- ;
if(!b)x=7;else ++x;
A.0
B.3
C.6
D.7
参考答案:A
12:设
#define N 3
#define Y(n) ((N+1)*n)
则表达式2*(N+Y(5+1))的值是
A.42
B.48
C.54
D.出错
参考答案:B Y(5+1) 传递过去的应该是6,而不是简单的把5+1给替换掉
13:若定义了char ch[]={″abc def″},*p=ch;则执行printf(″%c″,*p+4);语句的输出结果是
A.def
B.d
C.e
D.0
参考答案:C
14:下列转义字符中错误的是
A.′