资源描述
简答题与应用题:
1、 什么是嵌入式系统?主要有什么特点?
答:以应用为中心,以计算机技术为基础的,并且软件硬件是可剪裁的,能满足应用系统对功能、可靠性、成本、体积、功耗等指标的严格要求的专用计算机系统。他可以实现对其他设备的控制、监视或者管理等功能。
与通用的计算机系统相比,特点为:
(1) 面向特定应用,一般都有实时要求;
(2) 集先进性的计算机技术、半导体工艺、电子技术和通信网络技术于一体的并且在不断创新的知识集成系统;
(3) 嵌入式系统是和具体应用对象有机结合在一起,因而其升级换代也是和具体的产品同步进行的。
(4) 嵌入式系统的软硬件设计着重于高效率性。在最大限度满足应用需求的前提下,降低成本是必须要考虑的主要问题。
(5) 嵌入式系统软件一般都固化在存储器芯片中。
2、 嵌入式系统有哪几个部分?
答:嵌入式系统通常由嵌入式处理机、嵌入式外围设备、嵌入式操作系统和嵌入式应用软件等几大部分组成。
3、嵌入式操作系统的作用是什么?
*实际是一组软件模块集合
满足多任务处理、稳定运行 、安全可靠 、占用系统资源少 、特有的实时事件处理 、便于维护和管理、简洁良好的用户界面
4、 什么是Linux?什么是嵌入式Linux?
答:严格来讲,Linux是指由Linux本人维护并不断更新的内核 。
一个嵌入式Linux系统指的是一个基于Linux内核的,但不包含有关这个内核的任何专业的库或是用户工具的嵌入式系统。
5、 用Linux内核构建嵌入式操作系统有什么优势(优良特性)?
答:(1)程度代码是可以获取的,可靠度高;
(2) 有完整的源码,软件丰富并且免费;
(3) 得到众多硬件生产家的广泛支持;包括cpu、计算机外围设备
(4) 完善的通信协议、软件标准和文件管理机制;
(5) 提供完全免费且优秀的开发工具;
(6) 广泛的社群支持
(7) 无需购买licence,是免费的;
(8) 不依赖特定厂商、供应商;
(9) 成本相对低廉。
6、 RTOS(嵌入式操作系统)强调的实时是什么概念?与中断的关系?
答:实时指的是特定操作所消耗的时间(以及空间)的上限是可预知的。操作系统能够在规定响应时间内完成客户服务程序。中断程序响应中断并完成 是在固定时间内。
7、 什么是实时Linux?涉及到哪些软硬件内容?
答:实时Linux(RT-Linux)通过在Linux内核与硬件中断之间增加一个精巧的可抢先的实时内核,把标准的Linux内核作为实时内核的一个进程与用户进程一起调度,标准的Linux内核的优先级最低,可以被实时进程抢断。正常的Linux进程仍可以在Linux内核上运行,这样既可以使用标准分时操作系统即Linux的各种服务, 又能提供低延时的实时环境。它在硬件上涉及到硬件中断,软件上涉及到对高优先级的实时硬件中断的快速响应。
能在规定的时间内完成对突发事件的处理的Linux系统;
软件:中断服务程序、进程调度程序,硬件:嵌入式系统所采用的中断管理硬件。
8、 试简要说明Linux内核构成,并简要说明各部分的功能?
答:
MMU:内存管理单元,完成地址映射(应用虚拟地址方式)
VFS:虚拟文件管理系统,提供了统一管理计算机资源的途径。使统一规范计算机资源的使用格式成为可能,方便传输
SCHED:进程调用单元。支持多任务运行。利用软件中断的特点,将CPU 的时间线划分给各个任务,完成多任务管理
IPC:进程间通信单元。实现多个不同程序在运行时可以进行数据交换、通信。
NET:网络。网络不做为通用设备,以特定工作单元存在。负责计算机系统与其他计算机相互通信的接口。
9、 通常可采用哪几种方式来开发嵌入式Linux系统?给出示意图。
答:方式有:
(1)连接型(宿主机/目标板链接开发)
(2)可移动连接型(利用可移动的存储器作为宿主机/目标板之间的中介)
(3)标准化(在开发板上进行独立开发)
主机
跨平台开发环境
目标板
引导加载程序
内核
根文件系统
主机
跨平台开发环境
(1)
目标板
引导加载程序
第二引导加载程序
内核
根文件系统
(2)
目标板
引导加载程序
内核
完整的根文件系统
固有的开发环境
(3)
10、 为什么要建立交叉开发平台?在何种情形下可以不必建立?
答:嵌入式系统的构造决定。嵌入式处理器多为专用的cpu,1、必须将用C编写的程序编译成能在该专用平台上运行的机器码。2、C语言库是必需的,必需提供能在专用cpu上运行的库的二进制代码。以上两点要求有这么一种编译工具能够实现两种CPU之间的交叉。当执行应用程序的平台和用来建立应用程序的平台相同时就可以不建立交叉开发平台。
11、 试简要叙述GNU及其所提供的开发工具链。
答: GNU是“GNU's Not Unix”的递归缩写,它是一个自由软件工程项目组织。提供各种开源代码。提供一整套的开发工具链包括:GNU工具链基础,内核头文件安装程序,Binutils(二进制工具)的安装程序,引导编译器安装程序,C库安装程序,全编译器安装程序,完成工具链的设置。
12、 试解释make和makefile的关系?简单举例说明。
答:使用make就必须写makefile文件,它描述工程中文件之间的关系,提供更新每个文件的命令。Makefile就是一组规则,它指导make程序的运行,告诉make需要做什么,多数情况是怎样编译和链接一个程序。目标和目标运行规则一旦建立,make就会按此进行工作。
edit : main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
cc -o edit main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
main.o : main.c defs.h
cc -c main.c
kbd.o : kbd.c defs.h command.h
cc -c kbd.c
command.o : command.c defs.h command.h
cc -c command.c
display.o : display.c defs.h buffer.h
cc -c display.c
insert.o : insert.c defs.h buffer.h
cc -c insert.c
search.o : search.c defs.h buffer.h
cc -c search.c
files.o : files.c defs.h buffer.h command.h
cc -c files.c
utils.o : utils.c defs.h
cc -c utils.c
clean :
rm edit main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o (此段为Makefile)
make clean (此为make执行上述Makefile规则)
13、 GCC是什么?为什么说它是必不可少的?
答:GCC是由GNU组织开发的一个免费的C/C++编译工具,由它将高级语言转换为机器语言。因为GCC是一个交叉平台的编译器,几乎所有主流CPU处理平台上目标代码的变换,它有力的支持了Linux系统的发展。没有就无法获得可执行程序。
14、 C库是什么概念?在嵌入式Linux系统中对此有何要求?
答:提供C语言里包含常用函数的源代码。在嵌入式Linux系统中是必不可少的。否则无法获得可执行程序的完整代码。因为操作系统是用C语言编写的。
15、 在设计嵌入式Linux系统时为什么要配置内核?可用哪几种命令来配置?
答:针对嵌入式系统,内核需要知道运行在怎么样的平台上,它要管理的硬件单元,这就需要我们重新组装内核来达成上述目标。因为完整的Linux的内核比较庞大,不适合嵌入式系统这样的对速度、容量要求苛刻的系统上面运行,因此我们需要去掉那些与目标系统无关的、只编译系统需要的功能的代码。
我们通常使用内核配置命令make config(字符界面);make oldconfig;make menuconfig(文本图形界面);make xconfig(x-window图形界面)来配置内核。通常使用后两个命令,在图形界面下比较直观。显然,在makefile中详细定义了界面是如何生成的,以及配置和编译内核的规则。此外还有make oldconfig命令。
16、 重新编译内核应考虑哪几个方面的因素? 模块是什么概念?
答:建立依存关系,建立内核,建立模块。模块的概念:可动态、静态加载的二进制代码。
17、 什么是根文件系统?Linux内核启动与根文件系统的关系?
答:根文件系统是Linux系统的安装点,应该包括支持Linux系统正常运行的基本内容,包含着系统使用的软件和库,以及所有用来为用户提供支持构架和用户使用的应用软件。Linux内核在运行期必须要用到的存储代码体系,与内核同时存在,只在内核运行时才存在于内存中。根文件系统必须要能够提供Linux内核启动过程中要加载的模块
18、 在构建嵌入式Linux系统时,对根文件系统的目录项有什么要求?
答:构建嵌入式操作系统时应包括的目录项有:/bin;/boot;/dev;/ect;/home;/lib;/mnt;/opt;/proc;/root;/sbin;/tmp;/usr;/var
其中/bin;/dev;/ect;/lib;/proc;/sbin;/tmp;/usr;/var这9项必须包含,另外5项可有可无。
19、 Linux内核在目标板上启动过程(简要叙述)?需要考虑哪些因素?
答:
1、通过合适的bootloader 找到内核源代码,加载到内存
2、内核源代码开始进行初始化
3、内核源代码初始化完毕,开始调用和用户有关的进程。用户进程初始化
选用和目标板相配的启动装载程序
20、 如何理解文件系统?常用的文件系统有哪几种?
答:
文件系统是对一个存储设备上的数据和元数据进行组织的机制
另一种看待文件系统的方式是把它看作一个协议。网络协议(比如 IP)规定了互联网上传输的数据流的意义,同样,文件系统会给出特定存储媒体上数据的意义。
常用的文件系统:CRAMFS;JFFS2;Ext2 over NFTL;Ext3 over NFTL;Ext2 over RAM disk;EXT4。
21、 什么是VFS?它在Linux内核中的主要作用是什么?
答:VFS(虚拟文件系统)是物理文件系统与服务之间的接口层。它对Linux的每个文件系统的所有细节进行抽象,使得不同的文件系统在Linux核心以及系统中运行的其它进程看来,都是相同的。作用为:记录可用的文件系统类型,将设备同对应的文件系统联系起来,处理一些面向文件的通用操作,涉及到针对文件系统的操作时,VFS把它们影射到与控制文件、目录以及inode。
22、内核模块的编程和普通程序的编程有哪些区别?(6分)
参考答案:
主要区别为:
(1)因为内核模块运行在内核态,所以包含的头文件是内核程序相关的头文件,而普通程序则包含的是glibc的头文件(1分)
(2)模块程序没有main函数,而是通过init_module函数在加载后初始化。(2分)
(3)模块程序内可直接调用内核函数,而普通程序则只能通过系统调用使用内核函数。(2分)
(4)普通用户程序可运行多次,而内核函数通常则只能加载1次(1分)。
23、什么是交叉编译?为什么要采用交叉编译(5分)
参考答案:所谓交叉编译,是指在一个平台上编译生成在另一个平台上运行的可执行程序。(3分)。之所以采用交叉编译,是因为目标平台上不具备直接运行开发环境的条件。(2分)
24、简述嵌入式Linux系统的初始化过程(5分)
参考答案:
嵌入式Linux系统开机首先运行BootLoader,然后由BootLoader引导启动内核,由内核检查和初始化硬件设备,载入设备的驱动程序模块,安装root文件系统,然后内核将启动一个名为init的进程(2分)。在init运行完成并启动其它必要的后续进程后,系统开始运行,引导过程结束。init进程启动时需要读取inittab配置文件,该文件确定init在系统启动和关机时的工作特性。(3分)
应用题
1、管道是Linux中进程通信的一种方式,以下程序在父进程和子进程之间创建了一个管道,然后建立它们之间的通信,实现父进程向子进程写数据的功能。说明标号所在行代码的功能。
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
int pipe_fd[2];
pid_t pid;
char buf_r[100];
char* p_wbuf;
int r_num;
memset(buf_r,0,sizeof(buf_r)); (1)
if(pipe(pipe_fd)<0) (2)
{
printf("pipe create error\n");
return -1;
}
if((pid=fork())==0) (3)
{
printf("\n");
close(pipe_fd[1]); (4)
sleep(2);
if((r_num=read(pipe_fd[0],buf_r,100))>0) (5)
{
printf( "%d numbers read from the pipe is %s\n",r_num,buf_r);
}
close(pipe_fd[0]); (6)
exit(0);
}
else if(pid>0) (7)
{
close(pipe_fd[0]); (8)
if(write(pipe_fd[1],"Hello",5)!=-1) (9)
printf("parent write1 success!\n");
if(write(pipe_fd[1]," Pipe",5)!=-1)
printf("parent write2 success!\n");
close(pipe_fd[1]); (10)
sleep(3);
waitpid(pid,NULL,0);
exit(0);
}
}
答案要点:(1) 将数据缓冲区清0 (2) 创建管道 (3) 创建子进程 (4) 关闭子进程写描述符 (5) 子进程读取管道内容 (6) 关闭子进程读描述符 (7) 父进程运行控制语句 (8) 关闭父进程的读描述符 (9) 将数据写入缓冲区
(10) 关闭父进程写描述符
2、由于Boot Loader的实现依赖于 CPU 的体系结构,因此大多数Boot Loader都分为 stage1 和 stage2 两大部分。依赖于 CPU 体系结构的代码,比如设备初始化代码等,通常都放在 stage1 中,而且通常都用汇编语言来实现,以达到短小精悍的目的。而stage2 则通常用C语言来实现,这样可以实现给复杂的功能,而且代码会具有更好的可读性和可移植性。请根据你对嵌入式系统中bootloader的理解,简要设计一下stage1和stage2需要完成的功能。
参考答案:
BootLoader 的 stage1 通常包括以下步骤(以执行的先后顺序):(3分)
基本硬件设备初始化。
为加载 Boot Loader 的 stage2 准备 RAM 空间。
拷贝 Boot Loader 的 stage2 到 RAM 空间中。
设置好堆栈。
跳转到 stage2 的C入口点。
BootLoader 的 stage2 通常包括以下步骤(以执行的先后顺序): (3分)
初始化本阶段要使用到的硬件设备。
检测系统内存映射(memory map)。
将 kernel 映像和根文件系统映像从 flash 上读到 RAM 空间中。
为内核设置启动参数。
调用内核。
3、Qt/Embedded对嵌入式GUI提供了强大的支持,信号和插槽机制是QT的核心机制,使用QT实现如下界面的登陆程序,其原代码如下所示,请回答如下问题.
1)什么是Qt中的信号插槽机制?(3分)
2)应用程序中用到了哪些控件,列举2个并说明该控件的特点?(4分)
3)根据注释完成程序中相应的语句?(4分)
#include <QtGui/QtGui>
#include "window.h"
CWinDlg::CWinDlg(QWidget* parent) : QDialog(parent)
{
setWindowTitle("Example"); /*设置窗口的标题*/
Edit1 = new QLineEdit; /*创建一个Edit1和一个Buttion1*/
Button1 = new QPushButton("OK");
Edit1->setEchoMode(QLineEdit::Password);
QVBoxLayout* Layout1 = new QVBoxLayout; /*创建一个布局对像Layout1*/
Layout1->addWidget(Edit1); /*把Edit1加入到Layout1*/
Layout1->addWidget(Button1); /*把Button1加入到Layout1*/
(1) setLayout(Layout1); /*应用Layout1布局*/
(2) connect(Button1, SIGNAL(clicked()), this, SLOT(function())); /*建立Signal-Slot,
使button1与function()相关联*/
}
CWinDlg::~CWinDlg()
{
delete Edit1; /*删除Edit1与Button1对象*/
delete Button1;
}
void CWinDlg::function()
{
if(Edit1->text() == "example") /*如果Edit1输入"example"*/
{ /*显示"Pass!"消息框*/
QMessageBox::warning(this, "warning", "Pass!", QMessageBox::Yes);
}
else
{ /*显示"Error!"消息框*/
QMessageBox::warning(this, "warning", "Error!", QMessageBox::Yes);
}
}
#include <QtGui/QtGui>
#include "window.h"
int main(int argc, char* argv[])
{
QApplication app(argc, argv); /*创建QT应用程序*/
CWinDlg dlg; /*创建窗口*/
return dlg.exec(); /*运行程序*/
}
答案要点:
1)什么是Qt中的信号插槽机制?与回调函数机制有何不同?(3分)
答案要点:回调函数机制是事先将一个回调函数指针传递给一个处理过程,当这个处理过程得到执行时,回调预先定义好的回调函数以期实现激活其他处理程序的目的。不同与回调函数机制,Qt提供了信号和插槽机制,信号是一个特定的标识;一个槽就是一个函数,与一般函数不同,槽函数既能和信号关联,当某个事件出现时,通过发送信号,可以将与之相关联的槽函数激活,执行相应代码。
2)应用程序中用到了哪些控件,列举2个并说明该控件的特点?(4分)
答案要点:应用程序中用到的控件有(1)文本框控件Edit,文本框控件主要用来显示或接收用户的输入信息。(2)按钮控件Button,按钮控件主要响应用户单击功能。
3)根据注释完成程序中相应的语句?(4分)
(1)setLayout(Layout1);
(2)connect(Button1, SIGNAL(clicked()), this, SLOT(function()));
4.在Linux操作系统下,完成下列任务:
1、 编程实现以下功能
² 主程序hello.c(打印Hello World!)
² 主程序通过头文件hello.h调用message函数
² 头文件hello.h(声明message函数)
² message函数由message.c定义(打印This is a message!)
1、答:
hello.c:
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include "head.h"
int main (int argc,char *argv[])
{
printf("Hello World!\n");
message();
return 0;
}
head.h:
void message(void);
message.c:
# include <stdio.h>
void message (void){
printf("This is a message!\n");
}
5. 用C语言编写一个源程序main.c,(1)用以在打开当前目录下的文件“test.txt”,如果没有创建该文件,并使其具有读写属性,(2)编写一个makefile实现自动编译,生成可执行文件main。注:头文件可忽略。
1、
(1)(5分)
Void main(void)
{
int fid;
fid = open(“./test.txt”,O_RDWR|O_CREAT);
if(fid==-1)
{
Printf(“open or create error \n”);
exit(0);
}
Close(fid);
}
(2)(5分)
objects = main.o
exec = main
all:$(objects)
gcc –o $(exec) $(objects)
main.o:main.c
gcc –c main.c
clean:
rm –r $(exec) $(objects)
6、 假定你在目录/home/arm下有一个C程序,他由几个单独的文件组成,而这几个文件又分为包含了其他文件,如下图所示:
文件
包含文件
main.c
stdio.h, table.h
list.c
list.h
symbol.c
symbol.h
table.c
table.h
table.h
symbol.h, list.h
完成下列任务:
1. 编写makefile文件,最终的目标文件为hello(交叉编译器为arm-linux-gcc)
2. 在目标机上通过网络文件系统挂载/mnt 到宿主机上的/home/arm目录
1、答:
hello: main.o list.o symbol.o table.o
gcc -o prog main.o list.o symbol.o table.o
main.o: main.c table.h symbol.h list.h
gcc -c -o main.o main.c
list.o: list.c list.h
gcc -c -o list.o list.c
symbol.o: symbol.c symbol.h
gcc -c -o symbol.o symbol.c
table.o: table.c table.h symbol.h list.h
gcc -c -o table.o table.c
clean:
rm hello *.o
2、Mount –t nfs –o noclock 192.168.0.10:/home/armtest/hello /mnt
7、假如你需要设计一个BootLoader,在具体开发之前,你需要确定哪几个主要问题?
参考答案:
需要考虑的问题:(1)与主机连接的方式(2)硬件CPU类型,如何初始化 (3)内存空间大小以及如何使用 (4)内核运行前需要准备哪些条件(5)BootLoader需要支持几种模式。(每点各2分)
展开阅读全文