嵌入式操作系统应用开发复习题及答案.docx
《嵌入式操作系统应用开发复习题及答案.docx》由会员分享,可在线阅读,更多相关《嵌入式操作系统应用开发复习题及答案.docx(20页珍藏版)》请在冰豆网上搜索。
嵌入式操作系统应用开发复习题及答案
1、简述Linux操作系统具有的特点。
答:
开放的源代码,良好的兼容性,完备的帮助手册页,优秀的网络支持
支持多用户多任务多处理器
支持多种文件系统,独特的挂载方式确保数据的安全性
将应用程序的核心实现为库,可重用性良好
采用模块化分层的程序设计方法,可靠易维护
将设备等一切都看做是文件,提供统一的文件操作接口对设备等进行操作
2、解释POSIX。
答:
POSIX表示可移植操作系统接口,可以提高UNIX环境下应用程序的可移植性。
POSIX标准定义了标准的API,只要是符合这一标准的应用程序,就能够在多种操作系统中运行。
3、解释通用公共许可证GPL。
答:
GPL保证软件对所有用户来说是自由的。
遵循GPL的软件提供给用户时必须提供源码,一旦用户得到遵循GPL的软件,就能够对其任意地改写,修改之后如果要提供给其他人也必须遵循GPL,并开放源码,允许被修改。
4、Linux系统下,常用的在线帮助文件有哪些?
答:
1、man手册2、info手册3、How-To。
5、Linux系统下进行C程序开发的主要两个标准。
答:
1、ANSIC标准2、POSIX标准。
6、一般Linux系统调用函数,如果执行成功将返回什么值?
如果执行失败将返回什么值?
并对哪个系统全局变量进行赋值,以指示具体的错误情况。
答:
成功时返回为0,不成功时一般返回-1,也可能返回一些非0值。
失败时将会在全局变量errno中赋值指示错误类型
7、画出Linux函数库调用和系统调用的示意图,简单说明系统调用(API)函数的作用。
答:
API是操作系统和用户程序之间的接口,应用程序通过API与操作系统进行通信,使用操作系统提供的服务。
API同时保证了操作系统数据和程序的安全性。
因此,API提供给用户安全地使用操作系统提供的服务。
8、简单说明在Linux程序开发过程中,利用GCC工具将C语言程序编译成一个可执行程序文件的四个步骤。
答:
1、预处理2、编译3、汇编4、连接
9、解释gcc工具的o、c、I、L、l等5个参数的功能作用。
答:
o:
把文件输出到output_filename,c:
只编译,不连接I:
L:
在库文件的搜索路径列表中添加dirname目录l:
-ofile指定输出文件为file
-c预处理,编译,汇编源文件,但是不做连接,产生.o(OBJ)文件
-Idirname在头文件的搜索路径列表中添加dirname目录
-Ldirname在“-I”的搜索目录中添加dirname目录,在连接库文件时候使用
-lname如果一个库文件的名称为“libname.a”,程序执行时若要连接这个库文件,就要使用该选项进行连接,省略库名中的前缀“lib”和后缀“.a”
10、可执行程序文件在存储时(没有调入到内存)分为几部分,说明各段的主要内容。
答:
1、可执行代码区(text):
存放CPU执行的机器指令。
2、已初始化数据区(data):
包含了在程序中已经被初始化的全局变量和静态变量。
3、未初始化数据区(bss):
未初始化的全局变量和静态变量,在程序开始执行之前被内核初始化为0或空指针。
11、可执行程序文件调入到内存产生进程后,分为几个存储区域,说明各区域的主要内容与作用。
答:
前三个与10中内容相同4、堆区:
用于动态内存分配5、栈区(heap):
由编译器自动分配释放,存放函数的参数值、返回值、局部变量等。
。
12、Linux系统下,用C语言编程,进行文件管理,有哪两类函数可用?
试比较两类函数的优缺点。
答:
ANSIC优点:
1.具有丰富的函数可供使用。
2.直接对内存缓冲区进行操作,可以高效的写任意长度的数据块,在数据长度满足要求时安排底层系统调用,降低的系统的开销且没有数据块大小的限制,整体的效率要比直接对硬件操作的系统调用高3.具有更好的兼容性
缺点:
对系统调用进行封装,因此使用时会在库函数中再调用系统调用,就一次读写相同的数据来说,效率比系统调用要低
POSIX优点:
在类UNIX等系统中有很好的可移植性,可以直接设置对硬件的控制
缺点:
1.使用时会影响系统性能,如果一次只存取很少的内容,效率会很低2.硬件会限制对底层系统调用一次能读写的数据块大小,如果数据很小,会留下空隙。
3.兼容性不是很好
13、Linux系统中,系统默认为每个进程打开了几个个文件?
即每个进程可以直接操作哪几个流?
答:
3个,STDIN_FILENO标准输入文件,STDOUT_FILENO标准输出文件,STDOUT_FILENO标准错误文件。
每个进程可以直接操作STDIN:
标准输入流,STDOUT标准输出流,STDERR:
标准错误输出流。
14、标准输入输出设备的文件描述符和文件流指针分别是什么?
文件流指针与文件描述符有什么区别?
答:
使用系统调用open()成功返回一个文件描述符,文件描述符是任何打开的文件都被分配一个唯一非负整数用于表示该打开的文件,内核通过文件描述符对文件进行操作。
文件流指针:
在操作一个文件时要打开该文件使用ANSIC库函数fopen打开一个文件后返回一个文件流指针与该文件关联,所有对该文件的读写操作都可以通过该指针流完成。
在Linux中,文件流指针中封装了文件描述符,才能使通过文件流指针对文件操作成为可能。
15、Linux文件类型,在shell应用层面用ls-l查看命令不同类型的文件分别显示什么内容?
答:
文件的类型,文件权限,应连接个数,拥有者,拥有者所在组,文件大小,最后一次修改时间。
文件类型标识:
目录文件d,普通文件f,字符设备文件c,块设备文件b,管道文件p,链接文件l,socket文件s
16、在Linux某个文件系统下,文件属性中惟一标识某个文件的是什么?
惟一标识一个打开的文件是什么?
答:
索引节点,文件描述符。
17、ls–lc,-lu,-lt分别列出的是什么时间?
答:
–lc:
最后一次修改i结点时间.-lu:
最后一次访问时间.-lt:
最后一次修改内容时间
18、一个文件设置了setuid位,该可执行文件在执行时有什么主要的影响。
答:
会使得拥有执行该文件权限的用户执行该文件时,即使不是文件所有者也会使用文件所有者的权限。
19、一个常规文件的大小可以为0(st_size字段定义),那么目录和符号连接的长度是否可以为0?
答:
不为0.因为每当目录文件创建时,会自动产生两个“.”开头的隐含文件,符号链接,文件包含着另一个文件的路径名。
20、Linux系统下,进程结束的方法有哪几种?
答:
1.在本进程或者其它进程中使用kill()调用发送SIGKILL信号。
2.进程运行过程中遇到内存段冲突,非法指令等错误,由操作系统发送相应的信号终止进程。
3.进程执行到return或者调用exit()或者运行到最后自然结束。
4.执行exec类函数执行新的进程
21、Linux系统下,线程结束的方法有哪几种?
答:
1、调用pthread_exit()退出。
2、调用pthread_cancel函数取消该线程。
3、创建线程的进程退出或者整个函数结束。
4、其中的一个线程执行了exec类函数执行新的进程。
5.线程调用pthread_exit()或者执行到return或者执行完毕自然终止。
6.线程执行中出错由系统终止
22、线程间通信的机制有哪几种?
答:
1.信号量2.互斥量3.共享全局变量
23、进程间通信的机制有哪几种?
答:
本地主机通信:
1.信号2.信号量,消息队列,共享内存3.管道(包括有名管道和无名管道)4.共享内存
网络通信:
1.socket2.rpc
24、画出面向连接的(TCP)socket通信模型,并解释说明其中主要的socket函数。
答:
socket():
创建一个socket,作为通信的一个端点
bind():
为socket命名,若是创建的AF_INET套接字将其关联到一个IP端口号,若是AF_UNIX套接字将其关联到一个文件系统的路径名
listen():
创建一个队列用来保存等待处理的连接
accept():
阻塞等待连接请求,在有连接请求时创建一个新的socket来与客户进行通信
recv()/read():
接收数据
send()/write():
发送数据
connect():
用户通过在一个命名的或者未命名的socket和服务器的socket建立连接
25、画出面向非连接的(UDP)socket通信模型,并解释说明其中主要的socket函数。
26、
socket,bind
27、Linux系统IO操作有哪几种方式?
答:
1、阻塞I/O2、非阻塞I/O3、多路选择I/O4、信号驱动I/O
28、字节排列顺序有几种方式?
答:
大端方式,小端方式
采用大端方式将高位存放在低地址,小端方式将低位存放在低地址。
采用大端方式进行数据存放符合人类的正常思维,而采用小端方式进行数据存放利于计算机处理。
29、POSIX标准下,文件管理的基本操作函数有哪些?
答:
open打开文件close关闭文件read()从文件或设备中读读数据write()向文件或者设备中写数据fcntl():
传递控制信息到设备驱动程序
编程
30、如何使用ANSIC标准库,实现文件拷贝操作。
答:
假如要从file.in文件中拷贝数据到file.out中
#include
#include
intmain()
{
intc;
FILE*in,*out;//定义两个文件流指针
in=fopen("file.in","r");//in与file.in文件关联,使用只读方式打开
out=fopen("file.out","w");//out与file.out文件关联,用只写方式打开
while((c=fgetc(in))!
=EOF)
fputc(c,out);//每次循环从file.in中用fgetc()读出一个字符放到c中,再从c中写入到file.out。
如果没有读到文件尾(EOF),就继续下一次循环
exit(0);
}
31、如何使用POSIXIO库,实现文件拷贝操作。
答:
#include
#include
#include
#include
#include
intmain()
{
intc[50];//暂存从file.in中读出的字符
intin,out;
intnread;//存放read()返回值,即成功读取的字符数
in=open("file.in",O_RDONLY);//以只读方式打开file.in
out=open("file.out",O_CREAT|O_WRONLY,S_IRUSR|S_IWRUSR);//以只写方式打开file.out,如果该文件不存在,就使用所有者可读可写的方式创建它
while((nread==read(in,c,50))>0)//请求从file.in中读取50个字符放入c中,并返回实际读取的字符数放入nread中
write(out,c,nread);//将c中的有效字符写入file.out,如果还有字符未读出,循环,如果返回值为0(即已经读完了所有字符),退出循环
if(nread<0)//如果返回值为-1,出现错误,在终端输出“read()error!
”
write(2,"read()error!
",13);
exit(0);
}
32、如何编程实现文件夹的拷贝。
答:
/*输入格式如./cpfilefile1file2*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#defineBUFSIZE1024
#definePERMS0666
#defineDUMMY0
intcpfile(char*source_file,char*target_file)
{
intsource,target,num;
chariobuffer[BUFSIZE];
if((source=open(source_file,O_RDONLY,DUMMY))==-1)
{
printf("Sourcefileopenerror!
\n");
return1;
}
if((target=open(target_file,O_WRONLY|O_CREAT,PERMS))==-1)
{
printf("Targetfileopenerror!
\n");
return2;
}
while((num=read(source,iobuffer,BUFSIZE))>0)
if(write(target,iobuffer,num)!
=num)
{
printf("Targetfilewriteerror!
\n");
return3;
}
close(source);
close(target);
return0;
}
intcpdir(char*source_dir,char*target_dir){
DIR*source=NULL;
DIR*target=NULL;
structdirent*ent=NULL;
charname1[100],name2[100];
source=opendir(source_dir);
mkdir(target_dir,S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH);
target=opendir(target_dir);
if(source!
=NULL&&target!
=NULL)
{
while((ent=readdir(source))!
=NULL)
{
if(strcmp(ent->d_name,"..")!
=0&&strcmp(ent->d_name,".")!
=0)
{
strcpy(name1,"\0");
strcat(name1,source_dir);
strcat(name1,"/");
strcat(name1,ent->d_name);
strcpy(name2,"\0");
strcat(name2,target_dir);
strcat(name2,"/");
strcat(name2,ent->d_name);
if(ent->d_type==4)
cpdir(name1,name2);
if(ent->d_type==8)
cpfile(name1,name2);
}
}
closedir(source);
closedir(target);
}
return0;
}
intmain(intargc,char*argv[])
{
cpdir(*(argv+1),*(argv+2));
return0;
}写一创建(fork)新进程的程序,利用管道机制,实现在子进程中写入数据,在父进程中读出数据。
答:
#include
#include
#include
#include
intmain()
{
intdata_processed;
intfile_pipes[2];//管道的描述符
constcharsome_data[]="123";//存放将要传输的数据
charbuffer[BUFSIZ+1];//stdio.h中已经定义的BUFSIZ大小为8K
pid_tfork_result;
memset(buffer,'\0',sizeof(buffer));//buffer空间初始化‘\0’
if(pipe(file_pipes)==0){
fork_result=fork();
if(fork_result==-1){
fprintf(stderr,"Forkfailure");
exit(EXIT_FAILURE);
}
//子进程从管道中读出数据放到bufferr中
if(fork_result==0){
data_processed=read(file_pipes[0],buffer,BUFSIZ);
printf("Read%dbytes:
%s\n",data_processed,buffer);
exit(EXIT_SUCCESS);
}
//父进程往管道中写入数据
else{
data_processed=write(file_pipes[1],some_data,strlen(some_data));
printf("Wrote%dbytes\n",data_processed);
}
}
exit(EXIT_SUCCESS);
}
33、编程实现who|sort
答:
#include
#include
#include
#include
#include
#include
intmain(intargc,char*argv[])
{
intfds[2];
if(pipe(fds)==-1)
{
perror("pipe");
exit(EXIT_FAILURE);
}
if(fork()==0)
{
charbuf[128];
dup2(fds[0],0);
close(fds[1]);//mustinclude,orblock
execlp("sort","sort",(char*)0);
//execlp("cat","cat",(char*)0);
}
else
{
if(fork()==0)
{
dup2(fds[1],1);
close(fds[0]);
execlp("who","who",(char*)0);
}
else
{
close(fds[0]);
close(fds[1]);
wait(NULL);
wait(NULL);
}
}
return0;
}
34、利用信号机制,定时在屏幕上输出一些信息。
答:
#include
#include
#include
#include
#include
//方法1:
使用系统调用alarm()发送SIGALRM
staticintalarm_fired=0;//设置标志位
voidding(intsig)//信号处理函数,为避免使用printf()这个不安全的函数,在函数中设置标志位,在main()中检查标志使用printf()输出信息
{
alarm_fired=1;
}
intmain()
{
(void)signal(SIGALRM,ding);//注册信号处理函数(被分栏了,下页继续)
alarm(5);//在5s之后发送一个SIGALRM信号
sleep(10);//进程休眠,等待信号到达
if(alarm_fired==1)//通过标志位判断到达的信号是否是SIGALRM,如果是,输出信息
printf("5secondspast!
Ding!
\n");
}
//方法2:
使用系统调用kill()发送SIGALRM
staticintalarm_fired=0;//设置标志位
voidding(intsig)//信号处理函数,为避免使用printf()这个不安全的函数,在函数中设置标志位,在main()中检查标志使用printf()输出信息
{
alarm_fired=1;
}
intmain()
{
pid_tpid;
pid=fork();
switch(pid)
{
case-1:
perror("forkerror");
exit
(1);
case0:
//进入子进程
sleep(5);//子进程进入休眠等待父进程注册好信号处理函数并等待信号到达
kill(getppid(),SIGALRM);//通过getppid()得到父进程pid,向父进程发送SIGALRM信号
exit(0);//信号发送完毕,子进程退出
}
//下边由父进程执行
printf("waitingforSIGALRMtocome!
\n");
(void)signal(SIGALRM,ding);//注册用于捕获SIGALRM的信号处理函数
pause();//等待信号到达
if(alarm_fired==1)//通过标志位判断到达的信号是是否是SIGALRM,如果是,输出信息
printf("timeout!
\n");
printf("Done.\n");
exit(0);
}
35、利用信号量机制,实现生产消费问题的基本程序框架。
答:
消费者
#include
#include
#include
#include
#include
#include
#include
#defineSHARED_SIZE1024
staticcharshm[SHARED_SIZE];
unionsemun
{
intval;
};
voidsem_set(intsemid)
{
unionsemunsem_un;
sem_un.val=0;//设置信号量的初始值为0,作为互斥锁使用
semctl(semid,0,SETVAL,&sem_un);
}
voidsem_p(intsemid)
{
structsembufsem_buf;
sem_buf.sem_