嵌入式培训 百分网手机站

嵌入式软件助理工程师认证考试试题题库(5)

时间:2018-04-01 11:42:31 嵌入式培训 我要投稿

2016年嵌入式软件助理工程师认证考试试题题库

  in tints[20]={

  10, 20, 30, 40, 50, 60, 70, 80, 90, 100,

  110, 120, 130, 140, 150, 160, 170, 180, 190, 200

  };

  (Other declarations)

  int *ip=ints+3;

表达式

ints

__   ____

ints[4]

__   ____

ip

__   ____

ip[4]

__   ____

*(ip+4)

__   ____

  答:(每项1分)

表达式

ints

__     100   ____

Ints[4]

    50   ____

ip

__  112 ____

ip[4]

__  80 ____

*(ip+4)

__   80____

  5、请对下列shell程序加注释,并说明程序的功能和调用方法:

  #!/bin/sh

  #

  # /etc/rc.d/rc.httpd

  #

  # Start/stop/restart the Apache web server.

  #

  # To make Apache start automatically at boot, make this

  # file executable: chmod 755 /etc/rc.d/rc.httpd

  #

  case "$1" in

  'start')

  /usr/sbin/apachectl start ;;

  'stop')

  /usr/sbin/apachectl stop ;;

  'restart')

  /usr/sbin/apachectl restart ;;

  *)

  echo "usage $0 start|stop|restart" ;;

  esac

  答:

  1)程序注释

  #!/bin/sh 定义实用的shell

  #

  # /etc/rc.d/rc.httpd 注释行,凡是以星号开始的行均为注释行。

  #

  # Start/stop/restart the Apache web server.

  #

  # To make Apache start automatically at boot, make this

  # file executable: chmod 755 /etc/rc.d/rc.httpd

  #

  case "$1" in #case结构开始,判断“位置参数”决定执行的操作。本程序携带一个“位置参数”,即$1

  'start') #若位置参数为start

  /usr/sbin/apachectl start ;; #启动httpd进程

  'stop') #若位置参数为stop

  /usr/sbin/apachectl stop ;; #关闭httpd进程

  'restart') #若位置参数为stop

  /usr/sbin/apachectl restart ;; #重新启动httpd进程

  *) #若位置参数不是start、stop或restart时

  echo "usage $0 start|stop|restart" ;; #显示命令提示信息:程序的调用方法

  esac #case结构结束

  (2)程序的功能是启动,停止或重新启动httpd进程

  (3)程序的调用方式有三种:启动,停止和重新启动。

  七、应用实践题

  1、管道是Linux中进程通信的一种方式,以下程序在父进程和子进程之间创建了一个管道,然后建立它们之间的通信,实现父进程向子进程写数据的功能。说明标号所在行代码的功能。

  #include

  #include

  #include

  #include

  #include

  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、用Shell编程,判断一文件是不是字符设备文件,如果是将其拷贝到 /dev 目录下。

  答:

  #!/bin/sh

  FILENAME=

  echo “Input file name:”

  read FILENAME

  if [ -c "$FILENAME" ]

  then

  cp $FILENAME /dev

  fi

  3.下列程序实现了著名的生产者—消费者问题的模型,主程序中分别启动了生产者线程和消费者线程。生产者不断顺序地将0-1000的数字写入共享的循环缓冲区,同时消费者线程不断地从共享的循环缓冲区中读取数据。完成如下问题。

  进行生产(put) 进行消费(get)

  1)生产者 写入共享的循环缓冲区PUT函数的流程图如下,试完成流程图中标号所在处的内容。(4.5分)

  (1)写指针+1是否等于读指针 (2)等待条件变量not full (3) 设置条件变量notempty

  2)生产者 写入共享的循环缓冲区PUT函数的流程图如下,试完成流程图中标号所在处的内容。(4.5分)

  (4)写指针是否等于读指针 (5) 等待条件变量not empty (6) 设置条件变量notfull

  void put(struct prodcons * b, int data)

  { pthread_mutex_lock(&b->lock);

  while ((b->writepos + 1) % BUFFER_SIZE == b->readpos) {

  printf("wait for not full\n");

  pthread_cond_wait(&b->notfull, &b->lock);

  }

  b->buffer[b->writepos] = data;

  b->writepos++;

  if (b->writepos >= BUFFER_SIZE) b->writepos = 0;

  pthread_cond_signal(&b->notempty);

  pthread_mutex_unlock(&b->lock);

  }

  int get(struct prodcons * b)

  {

  int data;

  pthread_mutex_lock(&b->lock);

  while (b->writepos == b->readpos) {

  printf("wait for not empty\n");

  pthread_cond_wait(&b->notempty, &b->lock);

  }

  data = b->buffer[b->readpos];

  b->readpos++;

  if (b->readpos >= BUFFER_SIZE) b->readpos = 0;

  pthread_cond_signal(&b->notfull);

  pthread_mutex_unlock(&b->lock);

  return data;

  }

  void * producer(void * data)

  { int n;

  for (n = 0; n < 1000; n++) {

  printf(" put-->%d\n", n);

  put(&buffer, n);

  }

  put(&buffer, OVER);

  printf("producer stopped!\n");

  return NULL;

  }

  void * consumer(void * data)

  { int d;

  while (1) {

  d = get(&buffer);

  if (d == OVER ) break;

  printf(" %d-->get\n", d);

  }

  printf("consumer stopped!\n");

  return NULL;

  }

  int main(void)

  { pthread_t th_a, th_b;

  void * retval;

  init(&buffer);

  pthread_create(&th_a, NULL, producer, 0);

  pthread_create(&th_b, NULL, consumer, 0);

  pthread_join(th_a, &retval);

  pthread_join(th_b, &retval);

  return 0;

  }

  4、设计一个Shell程序,在/userdata目录下建立50个目录,即user1~user50,并设置每个目录的权限,其中其他用户的权限为:读;文件所有者的权限为:读、写、执行;文件所有者所在组的权限为:读、执行。

  答:

  #!/bin/sh

  i=1

  while [ i -le 50 ]

  do

  if [ -d /userdata ];then

  mkdir -p /userdata/user$i

  chmod 754 /userdata/user$i

  echo "user$i"

  let "i = i + 1" (或i=$(($i+1))

  else

  mkdir /userdata

  mkdir -p /userdata/user$i

  chmod 754 /userdata/user$i

  echo "user$i"

  let "i = i + 1" (或i=$(($i+1))

  fi

  done

  5、用变量a给出下面的定义

  f) 一个指向整型数的指针(A pointer to an integer)

  g) 一个指向指针的的指针,它指向的指针是指向一个整型数(A pointer to a pointer to an integer)

  h) 一个有10个整型数的数组(An array of 10 integers)

  i) 一个有10个指针的数组,该指针是指向一个整型数的(An array of 10 pointers to integers)

  j) 一个指向有10个整型数数组的指针(A pointer to an array of 10 integers)

  2、答:

  a) int *a; // A pointer to an integer

  b) int **a; // A pointer to a pointer to an integer

  c) int a[10]; // An array of 10 integers

  d) int *a[10]; // An array of 10 pointers to integers

  e) int (*a)[10]; // A pointer to an array of 10 integers

  6.根据下面给出的声明和数据,对每个表达式进行求值并写出他的值。在每个表达式进行求值是使用原来给出的值(也就是说,某个表达式的结果不影响后面的表达式)。假定ints数组在内存中的起始位置是100,整型值和指针的长度都是4字节。

  in tints[20]={

  10, 20, 30, 40, 50, 60, 70, 80, 90, 100,

  110, 120, 130, 140, 150, 160, 170, 180, 190, 200

  };

  (Other declarations)

  int *ip=ints+3;

表达式

ints

__   ____

ints[4]

__   ____

ip

__   ____

ip[4]

__   ____

*(ip+4)

__   ____

  答:(每项1分)

表达式

ints

__     100   ____

Ints[4]

    50   ____

ip

__  112 ____

ip[4]

__  80 ____

*(ip+4)

__   80____

  7、由于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 空间中。

  为内核设置启动参数。

  调用内核。

  8、Qt/Embedded对嵌入式GUI提供了强大的支持,信号和插槽机制是QT的核心机制,使用QT实现如下界面的登陆程序,其原代码如下所示,请回答如下问题:

  1)什么是Qt中的信号插槽机制?(3分)

  2)应用程序中用到了哪些控件,列举2个并说明该控件的特点?(4分)

  3)根据注释完成程序中相应的语句?(4分)

  #include

  #include "window.h"

  CWinDlg::CWinDlg(QWidget* parent) : QDialog(parent)

  {

  setWindowTitle("Example");

  Edit1 = new QLineEdit;

  Button1 = new QPushButton("OK");

  Edit1->setEchoMode(QLineEdit::Password);

  QVBoxLayout* Layout1 = new QVBoxLayout;

  Layout1->addWidget(Edit1);

  Layout1->addWidget(Button1);

  (1) ;

  (2) ;

  }

  CWinDlg::~CWinDlg()

  {

  delete Edit1;

  delete Button1;

  }

  void CWinDlg::function()