嵌入式面试问答类

struct与union的区别

struct:
a、结构体中的每个成员都有自己独立的地址,它们是同时存在的;
b、sizeof(struct)是内存对齐后所有成员长度的总和。
union:
a、联合体中的所有成员占用同一段内存,它们不能同时存在;
b、sizeof(union)是内存对齐后最长数据成员的长度。

static与volatile

static:
1). 在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。
2). 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。
3). 在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用
volatile:
Q: 一个参数既可以是const还可以是volatile吗?解释为什么。
答:是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它
Q: 一个指针可以是volatile 吗?解释为什么。 。
答:是的。尽管这并不很常见。一个例子是当一个中断服务子程序修该一个指向一个buffer的指针时。

进程和线程的区别

  1. 线程在进程下行进
  2. 一个进程可以包含多个线程
  3. 不同进程间数据很难共享
  4. 同一进程下不同线程间数据很易共享
  5. 进程要比线程消耗更多的计算机资源
  6. 进程间不会相互影响,一个线程挂掉将导致整个进程挂掉
  7. 进程使用的内存地址可以上锁,即一个线程使用某些共享内存时,其他线程必须等它结束,才能使用这一块内存。

消息队列的原理

内存碎片产生的原因及解决方式

  1. 内部碎片是由于已经被分配出去的内存空间不经常使用,并且分配出去的内存空间大于实际所需的内存空间,通常内部碎片不可避免

  2. 外部碎片是由于某些未分配的连续内存区域太小,以至于不能满足任意进程的内存分配请求,从而不能被进程利用的内存空间空闲块。

解决办法

采用内存分页方式:整个虚拟内存和物理内存切成一段段固定尺寸的大小。
虽然内存也会不连续,但是仍然可以申请使用。

多任务间通信方式

管道:
信号:信号是在软件层次上对中断机制的一种模拟,比如说串口调试的模拟就可以采用信号的方式模拟串口接收机制。用sigaction函数
套接字(socket):套接字最常用的就是在网络编程中,但是在多线程间很少使用
消息队列:消息队列是消息的链接表,包括Posix消息队列SystemV消息队列.它克服了前两种通信方式中信息量有限的缺点,按照消息对列的数据结构进行读写数据。
共享内存:可以说这是最有效的进程间通信方式,它使得多个进程可以访问同一块内存空间,不同进程可以及时看到对方进程中对共享内存中数据的更新.这种通信方式需要依靠某种同步机制,如互斥锁和信号量等.
互斥锁:互斥锁主要用于线程同步,它可以对共享资源加锁
信号量:主要作为进程之间以及同一进程的不同线程之间的同步和互斥的一种方法

共享内存需要注意的地方

需要注意内存空间内资源的保护

有操作系统和无操作系统的区别

1.框架结构不同:
无操作系统:
无操作系统
有操作系统:
在这里插入图片描述
2.无操作系统支持单任务架构,功能单一,控制不复杂的任务设计。
3.有操作系统时支持多任务调度,文件系统,内存管理等复杂功能。而且应用程序将可使用统一的系统调用接口来访问各种设备。

linux内核线程调度

简述协程

内存管理机制

什么是虚拟内存,解决了什么问题

虚拟内存是一种内存管理技术,在进程启动的时候,操作系统会通过mmu管理单元为每个进程提供连续的虚拟内存空间。这个空间被分割成很多块,每块称为一页,每一页地址都是连续的地址范围。这些页被映射到物理内存,但不要求是连续的物理内存,也不需要所有的页都映射到物理内存,而是按需分配,在程序片段需要分配内存时由硬件执行映射(通常是 MMU),调入内存中执行。
目的:
1.由于地址的连续性,方便了进程对于内存的访问
2.可以使有限的物理内存运行一个比它大很多的程序。

简述分页和分段的机制

分页是实现虚拟内存的技术,虚拟内存按照固定的大小分为页面,物理内存也会按照固定的大小分成页框,页面和页框大小通常是一样的,一般是 4KB,页面和页框可以实现一对一的映射。分页是一维的,主要是为了获得更大的线性地址空间。但是一个地址空间可能存在很多个表,表的数据大小是动态增长的,由于多个表都在一维空间中,有可能导致一个表的数据覆盖了另一个表。

分段是把虚拟内存划分为多个独立的地址空间,每个地址空间可以动态增长,互不影响。每个段可以单独进行控制,有助于保护和共享

内存是如何分配的

Linux 分配物理内存的主要机制是页面分配机制(页分配器),使用了著名的伙伴算法,主要用来分配页大小的整数倍的内存(4n KB)。如果是小于页大小的内存分配,通常使用 slab 管理器。通过 slab 分配的内存通常会缓存起来,方便下次使用。

内存是如何回收的

应用程序用完内存后,可以调用 free() 释放内存,或调用 unmap() 取消内存映射,归还系统。

在内存紧张时,会通过一系列机制来回收内存,如以下三种方式:
1.回收缓存。主要是页缓存。回收不常访问的页面。
2.使用页面置换算法,把不常用的页面放到交换区中。
3.通过 OOM 杀死占用大量内存的进程,释放内存。
了解项:

页表的作用?为什么引入多级页表

页面置换算法有哪几种

上下文切换原理

数组和链表的区别

数组的优点

随机访问性强
查找速度快

数组的缺点

插入和删除效率低
可能浪费内存
内存空间要求高,必须有足够的连续内存空间。
数组大小固定,不能动态拓展

链表的优点

插入删除速度快
内存利用率高,不会浪费内存
大小没有固定,拓展很灵活。

链表的缺点

不能随机查找,必须从第一个开始遍历,查找效率低

arm寻址方式

死锁,自旋锁

死锁的定义

死锁:两个或两个以上的进程(线程)在执行过程中,因争夺资源而造成的一种互相等待的现象,这种现象导致临界区的资源不被释放。所以被称为死锁。

死锁的场景

1.一个线程已经获取到锁,现在又去获取锁,就会出现死锁(调用lock的时候,如果当前的mutex变量已经被加锁,lock函数就会阻塞等待,一直等到unlock)亦或者一个线程获取到锁,但是执行到内核态时发生了阻塞,另一个线程此时获取该锁时也会产生死锁现象。

2.现在有两个线程,分别为消线程A和线程B,线程A获取了1号锁,线程B获取了2号锁,现在A尝试获取2号锁,线程B尝试获取1号锁,这个时候双方都无法拿到对方的锁,并且会在获取锁的函数(lock)中阻塞等待程序跑起来之后,因为两个线程互相去获取对方已经持有的锁,导致环路等待,出现死锁

死锁产生的条件

1.互斥条件
一个锁每次只能被一个线程或者进程使用;
2.请求和保持条件
一个进程或者线程因为请求某个锁而阻塞时,不会释放自己已经拿到的锁;
3.不剥夺条件
进程或者线程已经拿到的锁,自己未使用完毕之前,其他线程或者进程不能强行剥夺;
4.环路等待条件
若干进程或者线程之间形成一种头尾相接的循环等待锁的关系;

预防死锁的方法

根据死锁产生的四种方法,可以针对性的进行解决。
1、互斥条件,这是防止多进程、多线程间不产生冲突的根本所在,所以不能进行改变。
2、持有,在创建进程或线程时就一次性分配这么多的资源,如果当前存在这么多资源,则允许其运行,如果没有,则等待;每次在申请新资源时,必须释放他之前所占有的资源。
3、不可剥夺,如果某个进程或线程在持有某个资源的同时,申请另外的资源,则必须释放最初占有的资源,若后续还会用到,则再次申请;或者根据抢占的原理,即再优先级高于对方的情况下,如果对方只是申请资源,并没有使用资源,则可以对这份资源进行抢占。
4、对所有资源进行统一编号。进程读资源的申请必须以资源编号的升序方式提出

IO操作

IO分为同步操作和异步操作,异步操作必定是非同步。

二叉树下最优算法找到某个节点的方法

当低优先级task运行堆上资源时被高优先级抢占,此时由于堆上资源未被释放导致泄露,怎么处理避免该情况

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值