为了笔试兴唐.docx

上传人:b****7 文档编号:10170816 上传时间:2023-02-09 格式:DOCX 页数:20 大小:180.53KB
下载 相关 举报
为了笔试兴唐.docx_第1页
第1页 / 共20页
为了笔试兴唐.docx_第2页
第2页 / 共20页
为了笔试兴唐.docx_第3页
第3页 / 共20页
为了笔试兴唐.docx_第4页
第4页 / 共20页
为了笔试兴唐.docx_第5页
第5页 / 共20页
点击查看更多>>
下载资源
资源描述

为了笔试兴唐.docx

《为了笔试兴唐.docx》由会员分享,可在线阅读,更多相关《为了笔试兴唐.docx(20页珍藏版)》请在冰豆网上搜索。

为了笔试兴唐.docx

为了笔试兴唐

1)Linux中主要有哪几种内核锁?

自旋锁和信号量

自旋锁最多只能被一个执行线程持有,如一个执行线程试图请求一已被持有的自旋锁,则忙循环。

自旋锁可以在任何时刻防止多于一个的执行线程同时进入临界区。

可用于中断服务程序。

信号量是一种睡眠锁。

…,信号量会将其推入等待队列,然后睡眠。

信号量的睡眠特性,使得信号量适用于锁会被长时间持有的情况;只能在进程上下文中使用,因为中断上下文中是不能被调度的。

Linux内核同步机制:

原子操作、信号量、读写信号量、自旋锁、读写锁、顺序锁。

——————/

2)Linux中用户模式和内核模式什么含意?

Linux机器上,CPU要么处于受信任内核模式,要么处于受限制用户模式。

除内核本身处于内核模式以外,所有的用户进程都运行在用户模式之中。

内核模式的代码可以无限制地访问所有处理器指令集以及全部内存和I/O空间。

如果用户模式的进程要享有此特权,它必须通过系统调用向设备驱动程序或其他内核模式的代码发出请求。

——————/

3)怎样申请大块内核内存?

vmalloc线性地址连续,物理地址不连续,不能直接用于dma

kmalloc申请小内存,基于slab实现,slab为分配小内存提供一高效机制

——————/

4)用户进程间通信主要哪几种方式?

管道(亲缘关系)、命名管道(可无亲缘关系进程间通信)、信号、消息队列、共享内存(最快)、信号量(进程间或同一进程不同线程间同步手段)、套接字(不同机器进程间通信)

——————/

5)通过伙伴系统申请内核内存的函数有哪些?

alloc_pages(gfp_mask,order)

__get_free_pages(gfp_mask,order)

——————/

6)通过slab分配器申请内核内存的函数有?

——————/

7)Linux的内核空间和用户空间是如何划分的(以32位系统为例)?

——————/

9)用户程序使用malloc()申请到的内存空间在什么范围?

——————/

10)在支持并使能MMU的系统中,Linux内核和用户程序分别运行在物理地址模式还是虚拟地址模式?

——————/

11)ARM处理器是通过几级页表进行存储空间映射的?

二级,一级页表存储二级页表的指针

——————/

13)Linux虚拟文件系统的关键数据结构有哪些?

(至少写出四个)

structsuper_block;存储一已安装文件系统控制信息

structinode;索引节点对象存储文件相关信息,代表一实际物理文件

structdentry;目录项对象方便查找文件,如/home/dir/中,/、home、dir均是一目录项对象

structfile;建立进程与磁盘文件对应关系,sys_open时创建,sys_close时销毁

——————/

15)Linux中的文件包括哪些?

——————/

16)创建进程的系统调用有那些?

clone()有选择的继承父进程资源

fork()子进程复制父进程资源,运行于独立空间,使用写时复制技术(物理页)

vfork()子进程运行于父进程空间,对任何数据修改父进程都可见,为防止父进程重写子进程,父进程会被阻塞,直到子进程exit()

内核态sys_clone,sys_fork,sys_vfork,三者最终do_fork

——————/

17)调用schedule()进行进程切换的方式有几种?

1.系统调用do_fork();

2.定时中断do_timer();

3.唤醒进程wake_up_process

4.改变进程的调度策略setscheduler();

5.系统调用礼让sys_sched_yield();

——————/

18)Linux调度程序是根据进程的动态优先级还是静态优先级来调度进程的?

——————/

19)进程调度的核心数据结构是哪个?

structrunqueue;

——————/

22)Linux中的浮点运算由应用程序实现还是内核实现?

非在内核进行浮点运算需选上一配置项,严重降低效率

——————/

23)模块程序能否使用可链接的库函数?

模块运行于内核空间,不能链接库函数

——————/

24)TLB中缓存的是什么内容?

translationlookasidebuffer转换旁路缓冲,也称页表缓冲,存放虚拟地址与物理地址对应关系

——————/

26)字符设备驱动程序的关键数据结构是哪个?

——————/

28)如何唯一标识一个设备?

——————/

29)Linux通过什么方式实现系统调用?

x86软中断指令int

———————————————————————————————————/

字符设备块设备区别

字符设备是能够像字节流一样被访问的设备

块设备上能够容纳文件系统

区别仅在于内核及驱动程序之间的软件接口不同

——————/

什么是预编译,何时需要预编译:

预编译又称预处理,是作代码文本的替换工作,如文件包含#include、宏定义、条件编译指令

——————/

char*constp//常量指针

charconst*p;//指向常量的指针

——————/

IRQ和FIQ有什么区别,在CPU里面是是怎么做的?

FIQ:

INTMOD某位设为1,无需经过PRIORITY寄存器

——————/

中断分上半部和下半部分的原因?

如何实现?

中断服务例程一般是在中断请求关闭条件下执行,以避免嵌套而使中断控制复杂化。

但是,中断是一个随机事件,它随时会到来,如果关中断的时间太长,CPU就不能及时响应其他的中断请求,从而造成中断的丢失。

因此,内核的目标就是尽可能快的处理完中断请求,尽其所能把更多的处理向后推迟。

因此,内核把中断处理分为两部分:

前半部分(tophalf)和后半部分(bottomhalf),前半部分内核立即执行,而后半部分留着稍后处理。

后半部分运行时是允许中断请求的,而前半部分运行时是关中断的,这是二者之间的主要区别

——————/

#defineSECONDS_PER_YEAR(60*60*24*365)UL

预处理器标识#error的目的是什么?

#error命令是C/C++语言预处理命令之一,当预处理器预处理到#error命令时将停止并输出用户自定义的消息,如#errorSorry,anerrorhasoccurred!

——————/

嵌入式系统中经常要用到无限循环

while

(1){}

for(;;){}

Loop:

  ...

  gotoLoop;

——————/

一个指向有10个整型数数组的指针int(*a)[10]

一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数

int(*a[10])(int)

——————/const关键字

只要一听到被面试者说:

“const意味着常数”,我就知道我正在和一个业余者打交道

——————/volatile

变量值可能被意想不到地改变

在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。

例子:

1).并行设备的硬件寄存器(如:

状态寄存器)

2).一个中断服务子程序中会访问到的非自动变量(Non-automaticvariables非自动变量指的是全局变量或声明为static的局部变量。

是存储在静态存储区中的)

3).多线程应用中被几个任务共享的变量

这是区分C程序员和嵌入式系统程序员的最基本的问题

一个指针可以是volatile吗?

为什么?

可以,如多线程中

下面的函数有什么错误:

intsquare(volatileint*ptr)

{

  return*ptr**ptr;

}

等价于

intsquare(volatileint*ptr)

{

  inta,b;

  a=*ptr;

  b=*ptr;

  returna*b;

}

由于ptr值可能被意想不到地该变,因此a和b可能是不同的,结果,事与愿违

longsquare(volatileint*ptr)

{

  inta;

  a=*ptr;

  returna*a;

}

——————/

位操作使用宏,|=和&=~操作

裸机中断服务程序中:

doublearea=PI*radius*radius;

printf("Area=%f",area);错误,因

浮点一般都是不可重入的,ISR应该是短而有效率的,在ISR中做浮点运算是不明智的。

printf()经常有重入和性能上的问题

可重入代码指可被多个函数或程序凋用的一段代码(通常是一个函数),且保证被任何一函数调用时都以同样方式运行

voidtest()可重入

{

inti;static不可重入

i=2;

printf("%d\n",i);

i++;

printf("%d\n",i);

}

——————/

unsignedinta=6;

intb=-20;

(a+b>6)?

puts(">6"):

puts("<=6");//输出>6

当表达式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号类型,因此-20变成一个非常大正整

——————/

评价代码片断:

unsignedintzero=0;

unsignedintcompzero=0xFFFF;

对于一int型不是16位的处理器来说,上面的代码是不正确的,应:

unsignedintcompzero=~0;

——————/

嵌入式系统中,动态分配内存可能发生的问题是什么?

期望应试者能提到内存碎片,碎片收集的问题

char*ptr;

if((ptr=(char*)malloc(0))==NULL)

puts("null");

else

puts("valid");//valid

——————/

#definedPSstructs*

typedefstructs*tPS;//该法更好

因dPSp1,p2;

——————/

inta=5,b=7,c;

c=a+++b;

cout<

——————/

strlen只能以结尾为‘\0‘的字符串作参

编译器在编译时就计算出了sizeof的结果。

而strlen函数必须在运行时才能计算出来

数组做sizeof的参数不退化,传递给strlen就退化为指针

c++中static还可修饰类静态成员变量和静态成员函数

c中static不同函数间通信,c++不同对象间通信

——————/

malloc和new有以下不同:

(1)new、delete是操作符,可以重载,只能在C++中使用。

(2)malloc、free是函数,可以覆盖,C、C++中都可以使用。

(3)new可以调用对象的构造函数,对应的delete调用相应的析构函数。

(4)malloc仅仅分配内存,free仅仅回收内存,并不执行构造和析构函数

(5)new、delete返回的是某种数据类型指针,malloc、free返回的是void指针。

——————/

#definemin(a,b)((a)<=(b)?

(a):

(b))

((++*p)<=(x)?

(++*p):

(x)p指针就自加了两次,违背了MIN的本意。

——————/

inta[5]={1,2,3,4,5};

int*ptr=(int*)(&a+1);

printf("%d,%d",*(a+1),*(ptr-1));//2,5

——————/

从静态存储区域分配:

内存在程序编译时已分配好,这块内存在程序的整个运行期间都存在,速度快、不容易出错,因为有系统会善后。

例如全局变量,static变量等。

栈内存分配效率很高,但是分配的内存容量有限。

堆内存生存期由程序员决定,使用灵活。

…内存泄漏,另外频繁地分配和释放不同大小的堆空间将会产生堆内碎块。

——————/

memcpy两任意可操作内存地址,并不限于何种数据类型,效率非常高

C++空类有哪些成员函数?

构造函数、拷贝构造函数、析构函数,赋值运算符,取址运算符

注意:

只有实际使用这些函数时,编译器才会定义它们

——————/

拷贝构造函数和赋值运算符重载有以下两个不同之处:

1)拷贝构造函数生成新的类对象(Students2(s1)),而赋值运算符不能(Students1,s2;s2=s1)

2)拷贝构造函数是直接构造一个新类对象,所以在初始化该对象前不用检验源对象和新建对象是否相同,而赋值运算符则需这个操作(s1=s1不报错)。

注意:

当有类中有指针类型的成员变量时,一定要重写拷贝构造函数和赋值运算符,不要

使用默认的。

——————/

charstr1[]="abc";

charstr2[]="abc";

constcharstr3[]="abc";

constcharstr4[]="abc";

constchar*str5="abc";

constchar*str6="abc";//应加const,字符串常量

char*str7="abc";

char*str8="abc";

cout<<(str1==str2)<

cout<<(str3==str4)<

cout<<(str5==str6)<

cout<<(str7==str8)<

结果:

0011

str1,str2,str3,str4是数组变量,它们有各自的内存空间;而str5,str6,str7,str8是指针,它们指向相同的常量区域

str5[0]='d';//编译时保存

str7[0]='d';//运行时程序崩溃

——————/sizeof使用存在什么问题?

voidUpperCase(charstr[])//将str中的小写字母转换成大写字母

{

cout<

for(size_ti=0;i

if('a'<=str[i]&&str[i]<='z')

str[i]-=('a'-'A');

}

charstr[]="aBcDe";

cout<

UpperCase(str);

cout<

蜕化为指针,故64位机sizeof(str)/sizeof(str[0])=8/1

——————/

char*str="lyl";

printf(str);//打印lyl,同printf("lyl");

——————/

c和c++中的struct有什么不同?

主要区别是c中struct不可以含有成员函数,而c++中的struct可以。

c++中struct和class的主要区别在于默认的存取权限不同,struct默认为public,而class默认为private

——————/

task有几种状态?

#defineTASK_RUNNING0//就绪或运行

#defineTASK_INTERRUPTIBLE1//阻塞,可唤醒

#defineTASK_UNINTERRUPTIBLE2//阻塞,不可..

#defineTASK_ZOMBIE4//进程结束,但进程控制块为销毁

#defineTASK_STOPPED8//挂起,调试目的

——————/

线程间的通信方式:

线程间通信目的主要是用于线程同步,所以没有像进程通信中的用于数据交换的通信机制

锁机制:

如互斥锁、读写锁、条件变量

信号量机制

信号机制

——————/

#pragmapack(8)

structtagS1

{

charc;

inti;

};

#pragmapack()

#pragmapack

(2)

structtagS2

{

charc;

inti;

};

#pragmapack()

cout<

cout<

86

——————/

网络字节序:

网络字节顺序是TCP/IP中规定好的一种数据表示格式,它与具体的CPU类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释。

网络字节顺序采用bigendian排序方式

网络上的数据流是字节流,对于一个多字节数值,在进行网络传输时,先传递哪个字节?

也就是说,当接收端收到第一个字节的时候,它是将这个字节作为高位还是低位来处理呢?

收到的第一个字节被当作高位看待,这就要求发送端发送的第一个字节应当是高位。

而在发送端发送数据时,发送的第一个字节是该数字在内存中起始地址对应的字节。

可见多字节数值在发送前,在内存中数值应该以大端法存放

——————/

什么是段错误?

访问了未申请的内存

访问系统保护的内存:

int*p=0;

访问只读的内存

栈溢出:

main(){main();}

——————/

控制型、等时型(不可靠)、中断型、批量型(可靠),这四种传输类型中,哪些属于可靠传递,哪些不是可靠传递?

——————/

copy_to_user:

传入指针,返回变量或buffer

put_user:

要复制的内存为简单类型,如char、int、long等

intput_read(structfile*filp,char__user*buff,size_tcount,loff_t*offp)

{

chartemp=100;

put_user(temp,buff);

return0;

}

——————/

copy_to_user和__copy_to_user的区别

__copy_to_user没有判断用户传入的指针是否合法

——————/

如何处理jiffies的溢出问题?

处理jiffies回绕问题可使用宏time_before或time_after判断

unsignedlongtimeout=jiffies=HZ/2;

if(time_before(jiffies,timeout))//返回true或false

没有超时

else

超时

——————/

ttl电平5v为逻辑1,ov为0

rs232电平逻辑1=-3V~-15V,逻辑0=+3~+15V

MAX232实现电平转换

——————/

linux驱动开发工作,涉及驱动开发模式、内核相关知识和硬件相关知识

——————/

关于i节点和超级块,下列论述不正确的是(B)

Ai节点是一个长度固定的表

B超级块在文件系统的个数是唯一的

Ci节点包含了描述一个文件所必需的全部信息(存储区地址,大小等,不包含文件名,文件名存于目录项)

D超级块记录了i节点表和空闲块表信息在磁盘中存放的位置

选b

——————/

C与C++各自是如何定义常量的?

有什么不同?

C中是使用宏#define定义(不能调试),C++使用更好的const来定义。

——————/

C++中引用和指针的区别?

别名,操作引用即操作该对象,须在创建同时初始化,且初始化后不能再重新声明为另一变量的别名(但devc++可以);引用具有指针的效率,又具有变量使用的方便性和直观性,引用一般都是通过指针来实现的,编译器帮我们完成了转换。

——————/

在C++程序中调用被C编译器编译后的函数,为何要加extern"C"?

C++支持重载,被C++编译后的函数名与C不同,如函数原型voidfoo(intx,inty)被C编译器编译后在库中名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字。

C++提供了C连接交换指定符号extern"C"来解决名字匹配问题。

——————/

多态性通过派生类和虚函数实现,基类和派生类中使用相同函数名

——————/

拷贝构造函数:

单个参数,为同类对象的常引用

浅拷贝:

简单赋值而没有拷贝分配给该成员的资源,如给其指针变量分配了动态内存

深拷贝反之

——————/

软实时、硬实时

哈佛结构主要特点是程序存储器与数据存储器独立,即存于不同空间,独立编址独立访问

提供Linux系统实时性:

①缩短中断响应时间②缩短进程上下文切换时间③缩短进程调度时间

ARM7种工作模式:

用户模式、快中断模式、中断模式、管理模式、未定义指令终止模式、系统模式、数据访问终止模式

两种工作状态:

ARMthumb

Linux内核主要由5个子系统组成:

进程调度、内存管理、vfs、网络接口、进程间通信

tcp/ip:

应用层、传输层、网络层、接口层

——————/

中断延迟,是指中断发生到中断得到处理所消耗的时间。

中断延迟的主要原因是中断关闭,故降低中断延迟主要方法是减少中断关闭时间,把主要工作放到下半部分完成。

Semaphore和Mutex的区别:

①初始状态不一样,Mutex的初始值是1(表锁可用),而Semaphore初始值是0

②用法不一样,Mutex使用者必须为同一个线程,避免临界区被并行执行,而Semaphore可由不同线程进行P和V操作,即由一个线程P一资源,另一个线程V一资源,故可用于生产者-消费者模型等资源同步的场合

信号量本身会记录阻塞在它上面的进程。

在释放信号量的时候,会唤醒一个/一些进程。

而后,调度器根据调度策略选择一个进程执行

——————/

为了避免并发,防止竞态,内核提供了一组同步方法来提供对共享数据的保护:

中断屏蔽、原子操作、自旋锁(读写锁、顺序锁)、信号量、互斥体

应用:

信号量:

不能用于分布式操作系统

自旋锁:

死锁、过多占用cpu资源

管程

会和

分布式系统

——————/

死锁产生的必要条件:

互斥、不可剥夺、请求与保持、循环等待

——————/

产生死锁的原因:

资源竞争、进程推进顺序非法

——————/

死锁的处理:

预防策略、避免策略、鸵鸟策略

——————/

纯虚函数如何定义?

使用时应注意什么?

virtualvoidf()=0;是接口,子类必须要实现

——————/

轮询任务调度与抢占式任务调度的区别在于抢占式调度可以因为优先级高的任务抢占cpu,而轮询的不能

在RTOS中,主要的调度算法是基于任务优先级的抢占式调度。

在这种调度算法中,系统总是选择优先级别的最高的算法进行调度,并且一旦高优先级别的任务准备就绪之后,它就会马上被调度而不等待低优先级的任务主动放弃CPU。

在时间片轮转调度算法中,只有等任务主动放弃CPU,高优先级的任务才有调度的优先权。

——————/

什么叫存储

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 表格模板 > 合同协议

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1