嵌入式应用开发期末练习题.docx
《嵌入式应用开发期末练习题.docx》由会员分享,可在线阅读,更多相关《嵌入式应用开发期末练习题.docx(14页珍藏版)》请在冰豆网上搜索。
![嵌入式应用开发期末练习题.docx](https://file1.bdocx.com/fileroot1/2022-12/13/ddd10629-9ccc-436a-8084-5e6e258476c6/ddd10629-9ccc-436a-8084-5e6e258476c61.gif)
嵌入式应用开发期末练习题
一、填空题
1、linux中,对串口参数进行配置的数据结构名是__termios____。
2、gcc的编译流程分为4个步骤:
预处理、__编译____、汇编、__链接____。
3、获取当前进程ID的方法是__getpid()____。
4、对文件的打开操作有open和fopen,它们哪个是标准库函数__fopen()____它的返回值是__指向FILE的指针____。
5、一个由c语言占用的内存分为代码区和数据区,数据区又可以分为__静态数据区____和动态数据区,动态数据区分为堆、__栈____。
6、linux的管道通信可以分为匿名管道、___有名管道___和__标准管道____。
7、linux中的网络编程是通过套接字接口来进行的,常见的套接字有三种类型:
___流式套接字___、__数据报套接字____和__原始套接字____。
8、在linux中,用户空间的进程可以直接通过___系统调用___来获取操作系统内核提供的服务。
9、linux中,对串口进行操作的函数中,激活串口配置的函数是__tcsetattr()____。
10、linux中使用较多的进程间通信方式包括管道、信号、信号量、___消息队列___、__共享内存____。
11、makefile规则是make进行处理的依据,它包括了__依赖文件____、___目标体___及其之间的命令语句。
12、互斥锁和信号量为linux中的线程同步机制,其中___信号量___适合于同时可用的资源为多个的情况。
13、系统调用分为进程控制、进程间通信、文件系统管理、系统管理、存储管理、网络管理、socket管理、用户管理等。
14、终端分为3种模式规范模式、非规范模式和原始模式
二、选择题
1.下面关于linux下串口操作正确的描述是【C】
A.串口的奇偶校验必须使能B.不能通过linuxapi设置串口的停止位
C.串口配置好后,其读写操作和普通文件就是一样的了
D.串口文件可以通过lseek改变读写指针
2.下列关于makefile说法错误的是【B】
A.创建目标体的命令必须以制表符开头B.makefile变量名可以包含“#”字符串
C.makefile变量对大小写敏感D.“-Cdir”表示读入指定目录dir下的makefile
3.下列关于linux多线程编程不正确的是【D】
A.不同进程的线程间不能用信号量来同步;
B.pthread线程库符合POSIX接口;
C.必须包含头文件pthread.h;
D.phtread_join()作用是将参数中的指定线程挂起;
4.下列关于linux网络编程不正确的说法是【C】
A.send()既可用在tcp中,也可用在udp中;
B.sendto()既可用在tcp中,也可用在udp中;
C.不管是客户端还是服务器端必须调用bind;
D.每一个socket都用一个半相关描述{本地地址、本地端口}
5.从文件描述符fd中读出200个字节到首地址为buff的缓冲区的正确底层IO操作是【B】
A.read(buff,200,fd);B.read(fd,buff,200);
C.read(fd,200,buff);D.read(200,buff,fd);
6.使用下面哪条命令可以查询目标文件所依赖的动态链接库。
【B】
A.nm;B.readelf;
C.ld;D.objcopy
7.下面关于linux进程控制不正确的描述的是【A】
A.wait()调用一定会使得父进程阻塞
B.exit()会清理IO缓冲,而_exit()不会清理IO缓冲
C.在执行execl函数后,原调用进程的内容除了进程号外,其他全部被新的进程替换了
D.fork()的返回值在父子进程中是不一样的
8.将max.c生成动态链接库的正确命令是。
【B】
A.gcc–cmax.c
B.gcc-fpic–shared–olibmax.somax.c
C.gcc–olibmax.somax.c
D.gcc–static–olibmax.somax.c
9.下面关于linux进程通信正确的是【C】
A.信号量是进程间通信机制中唯一同步机制
B.消息队列读取函数msgrcv()只能读取队头的消息
C.共享内存的实现分为两个步骤:
创建或打开共享内存和映射共享内存
D.信号量既可以解决进程间的同步问题,但不能解决进程间的互斥问题。
10.linux网络编程中,下面哪个函数是客户端、服务端所必须调用的。
【C】
A.listen()
B.accept()
C.socket()
D.bind()
11.使用下面哪个函数返回值可知道文件操作已到文件末尾【C】
A.fopenB.ftellC.feofD.fseek
三、判断题
1.select主要解决了多路IO复用的问题。
(√)
2.嵌入式linux的底层IO函数(如read())带有缓冲区,可直接对文件进行读写操作。
(X)不带缓冲区
3.嵌入式linux的标准IO函数(如fread())不带有缓冲区,可直接对文件进行读写操作。
(X)不可直接对文件操作
4.linuxapi是linux操作系统直接提供的函数接口。
(X)不是直接
5.参数“-static”的作用是告诉gcc及库进行静态链接。
(√)
6.internet上的数据在网络上是以高位字节优先的顺序在网络上传输的。
(√)
7.创建线程的实质就是确定该线程函数的入口点,通常使用的函数是pcreate_thread。
(X)pthread_create
8.当linux线程出现错误的时候,可以使用exit()终止线程。
(X)pthread_exit
9.fork()函数是linux中一个非常重要的函数,在子进程中其返回值等于0。
(√)
10.linux中不是所有的socket都要调用bind函数进行端口绑定。
(√)
11.标准IO函数fread读取成功时返回的是成功读取的记录数。
(X)记录数的数目
12.底层IO函数read读取成功返回的的时成功读取字节数(√)
13.在linux中,每个api都会对应一个或多个系统调用(X)可以不对应
14.Internet上的数据在网络上是以低位字节优先的顺序在网络上传输的(X)高位字节
15.select主要解决了多路IO复用的问题(√)poll也是
16.linux中socket一定要调用bind函数进行端口绑定(X)TCP要,UDP不用
17.参数“-static”的作用是告诉gcc及库进行静态链接(√)“-shared”动态链接
18.fork()函数是linux中一个非常重要的函数,如果成功,父进程中其返回值大于1(√)子进程返回0,父进程返回子进程的进程号
19.参数“-fpic”的作用是告诉gcc生产及位置相关的目标代码(X)无关
20.普通可实现进程间的全双工通信(X)半双工
四、简答题
1.画图说明linux系统下用TCP协议网络编程时客户端和服务器的步骤。
2.画图说明linux系统下用UDP协议网络编程时客户端和服务器的步骤。
3.简述linux系统调用、API及系统命令之间的关系。
系统调用是指操作系统提供给用户程序调用的一组“特殊”接口,用户程序可以通过这组“特殊”接口来获得操作系统内核提供的服务。
而实际使用过程中,我们通常调用的用户编程接口就是API;系统命令相对API更高了一层,它实际上一个是可执行程序,它的内部引用了用户编程接口(API)来实现相应的功能。
他们的关系:
4.#简述在linux下实现进程通信的几种方式的各自特点?
匿名管道:
具有亲缘关系的进程间,半双工,数据在内存中
有名管道:
可用于任意进程间,双工,有文件名,数据在内存
信号:
唯一的异步通信方式
消息队列:
常用于cs模式中,按消息类型访问,可有优先级,无须同步机制。
共享内存:
效率最高(直接访问内存),需要同步、互斥机制
信号量:
用于解决进程间的同步及互斥问题的一种进程间通信机制
5.#共享内存是如何实现进程通信的?
它是用什么方法(函数):
创建、映射、撤销映射、删除?
。
创建/打开共享内存.ftok(),shmget()
映射共享内存,即把指定的共享内存映射到进程的地址空间用于访问.shmat()
撤销共享内存映射.shmdt()
删除共享内存对象.shmctl()
6.#创建守护进程的过程:
①调用fork创建子进程。
父进程终止,让子进程在后台继续执行。
②子进程调用setsid产生新会话期并失去控制终端
调用setsid()使子进程成为新会话组长和新的进程组长,同时失去控制终端
③改变当前工作目录为根目录chdir()
一般将工作目录改变到根目录,这样进程的启动目录也可以被卸掉。
④重设文件创建掩码umask()
清除从父进程那里继承来的文件创建掩码,设为0。
⑤关闭打开的文件描述符close()
⑥用openlog函数建立及syslogd的连接
五、编程题
1、请使用open、read、write、lseek、fork、pipe、sleep和waitpid
等函数实现如下功能:
1)子进程把src.txt文件末尾的5个字符读出来;
2)再通过管道发送给父进程;
3)父进程收到后将它们输出到显示终端。
注意:
请自行定义运行过程中的提示信息,头文件可省略!
#include
#include
#include
#include
#include
#include
#include
#definesrc"src.txt"
intmain()
{
intsrc_file,pipe_fd[2];
pid_tpid;
unsignedcharbuff[5],buff1[10];
intreal_read;
src_file=open(src,O_RDONLY);
if(src_file<0)
{
printf("opensrcfailed!
\n");
exit
(1);
}
if(pipe(pipe_fd)<0)
{
printf("Pipecreatfailed!
\n");
exit
(1);
}
memset(buff,0,sizeof(buff));
memset(buff1,0,sizeof(buff1));
pid=fork();
if(pid==0)
{
close(pipe_fd[0]);
sleep(3);
lseek(src_file,-6,SEEK_END);
real_read=read(src_file,buff,5);
write(pipe_fd[1],buff,real_read);
close(pipe_fd[1]);
exit(0);
}
else
{
close(pipe_fd[1]);
sleep
(1);
wait();
read(pipe_fd[0],buff1,sizeof(buff1));
printf("Receivedatafromson:
%s\n",buff1);
close(pipe_fd[0]);
close(src_file);
exit(0);
}
}
2、用tcp协议实现(只须编写服务器程序)
服务器端首先建立起socket,然后及本地端口进行绑定,接着就开始接收从客户端的连接请求并建立及它的连接,接下来,接收客户端发送的消息并显示出来,当收到“exit”时退出。
#include
#include
#include
#include
#include
#include
#include
#include
#definePORT4321
#defineBUFFER_SIZE1024
#defineMAX_QUE_CONN_NM5
intmain()
{
structsockaddr_inserver_sockaddr,client_sockaddr;
intsin_size,recvbytes;
intsockfd,client_fd;
charbuf[BUFFER_SIZE];
/*建立socket连接*/
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
perror("socket");
exit
(1);
}
printf("Socketid=%d\n",sockfd);
/*设置sockaddr_in结构体中相关参数*/
server_sockaddr.sin_family=AF_INET;
server_sockaddr.sin_port=htons(PORT);
server_sockaddr.sin_addr.s_addr=INADDR_ANY;
bzero(&(server_sockaddr.sin_zero),8);
inti=1;/*允许重复使用本地地址及套接字进行绑定*/
setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&i,sizeof(i));
/*绑定函数bind()*/
if(bind(sockfd,(structsockaddr*)&server_sockaddr,
sizeof(structsockaddr))==-1)
{
perror("bind");
exit
(1);
}
printf("Bindsuccess!
\n");
/*调用listen()函数,创建未处理请求的队列*/
if(listen(sockfd,MAX_QUE_CONN_NM)==-1)
{
perror("listen");
exit
(1);
}
printf("Listening....\n");
sin_size=sizeof(structstructsockaddr);
/*调用accept()函数,等待客户端的连接,并创建一个新的socket为本次连接服务*/
if((client_fd=accept(sockfd,
(structsockaddr*)&client_sockaddr,&sin_size))==-1)
{
perror("accept");
exit
(1);
}
/*调用recv()函数接收客户端的请求*/
memset(buf,0,sizeof(buf));
if((recvbytes=recv(client_fd,buf,BUFFER_SIZE,0))==-1)
{
perror("recv");
exit
(1);
}
printf("Receivedamessage:
%s\n",buf);
close(sockfd);
exit(0);
}
2、用UDP协议实现(只须编写服务器端程序):
服务器端首先建立起socket,然后及本机IP和端口进行绑定,接着可循环接收客户端发送的消息并显示出来,当收到“exit”时退出。
#include
#include
#include
#include
#include
#include
#include
intmain(void)
{
intsockfd;
structsockaddr_inserver,client;
intport=1234;
intopt=SO_REUSEADDR;
intrt;
intaddrlen;
//charsendbuf[100];
charrbuf[100];
intnum;
sockfd=socket(AF_INET,SOCK_DGRAM,0);
if(sockfd==-1)
{
perror("socket");
exit
(1);
}
//避免出现地址已经使用的错误
setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
bzero(&server,sizeof(server));
server.sin_family=AF_INET;
server.sin_addr.s_addr=INADDR_ANY;//回送地址,指本地机,一般用来测试使用
server.sin_port=htons(port);
rt=bind(sockfd,(structsockaddr*)&server,sizeof(server));
if(rt==-1)
{
perror("bind");
exit
(1);
}
addrlen=sizeof(client);
while
(1)
{//接收客户端信息
num=recvfrom(sockfd,rbuf,sizeof(rbuf),0,(structsockaddr*)&client,&addrlen);
if(num<0)
{
perror("recvfrom");
break;
}
rbuf[num]='\0';
//显示客户端信息,如果客户端发来exit则退出循环
printf("%s:
%d%s\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port),rbuf);
if(strcmp(rbuf,"exit")==0)
break;
}
close(sockfd);
}
3、利用信号量实现:
主线程负责从键盘获取两个整数,子线程1负责对这两个整数完成求和运算并把结果打印出来,子线程2负责对这两个整数完成乘法运算并打印出来。
三个线程要求遵循如下同步顺序:
a)主线程获取两个数;
b)子线程1计算;
c)子线程2计算;
d)转到a。
#include
#include
#include
#include
sem_tcan_add;//能够进行加法计算的信号量
sem_tcan_multiply;
sem_tcan_scanf;//能够进行键盘输入数的信号量
doublex,y;
void*thread_add(void*arg)//加法线程入口函数
{
while
(1)
{
sem_wait(&can_add);//申请信号量
printf("x+y=%.3lf\n",x+y);
sem_post(&can_multiply);//释放信号量
}
}
void*thread_multiply(void*arg)//乘法线程入口函数
{
while
(1)
{
sem_wait(&can_multiply);
printf("x*y=%.3lf\n",x*y);
sem_post(&can_scanf);
}
}
intmain()
{
pthread_ttid1,tid2;
sem_init(&can_add,0,0);//初始化can_add信号量
sem_init(&can_multiply,0,0);
sem_init(&can_scanf,0,1);//初始化can_scanf信号量
if(pthread_create(&tid1,NULL,thread_add,NULL)<0)
{
printf("Createthread_addfailed!
\n");
exit(0);
}
if(pthread_create(&tid2,NULL,thread_multiply,NULL)<0)
{
printf("Createthread_multiplyfailed!
\n");
exit(0);
}
while
(1)
{
sem_wait(&can_scanf);//申请信号量
printf("Pleaseinputtwonumbers:
");
scanf("%lf%lf",&x,&y);
if(x==0&&y==0)
{
pthread_cancel(tid1);
pthread_cancel(tid2);
break;
}
sem_post(&can_add);//释放信号量
}
exit(0);
}