当前位置: 首页 > article >正文

《拉依达的嵌入式\驱动面试宝典》—操作系统篇(一)

《拉依达的嵌入式\驱动面试宝典》—操作系统篇(一)

在这里插入图片描述
你好,我是拉依达。
感谢所有阅读关注我的同学支持,目前博客累计阅读 27w,关注1.5w人。其中博客《最全Linux驱动开发全流程详细解析(持续更新)-CSDN博客》已经是 Linux驱动 相关内容搜索的推荐首位,感谢大家支持。

《拉依达的嵌入式\驱动面试宝典》 最开始我个人的面试学习笔记,里面整合了所有我认为可能遇到的技术面试问题。随着我个人的学习以及参与面试,对内容不断完善。现在我已经步入工作阶段,空闲时间将之前的学习内容进行重新编排整理,并且加入了工作后更新系统的理解。是所有博客中投入最大的一个系列。包含我个人学习中所有的精华内容,希望可以最大限度的帮助到你。

所有问题及其答案均是我个人学习后查阅资料总结,每个回答都做了仔细的分析,在嵌入式及其驱动面试相关问题解析做到独一无二。

其中包含嵌入式软件开发、嵌入式驱动开发、linux驱动开发等职位遇到的所有技术方向问题。**尤其是对驱动等底层问题的解析,适合准备相关工作或者学习提升的同学 **

————————————————————————————————————————————

三、操作系统

3.1 进程线程管理

操作系统定义?

整个系统完成最基本功能系统管理的部分。

操作系统组成?

内核、设备驱动程序、启动引导程序、命令行shell/用户界面、文件管理工具、系统工具

内核组成?

  • 负责响应中断——中断服务程序
  • 负责管理多个进程——调度程序
  • 负责管理进程地址空间——内存管理程序
  • 网络、进程通信等——系统服务程序

进程的生命流程

  1. 父进程调用fork()函数,从一个已有进程复制出一个全新的进程
  2. 调用exec()函数,创建新的地址空间,载入新的程序
  3. 调用exit() 函数,退出执行,终结进程并释放占用资源
  4. 父进程调用wait()函数,查询子进程是否终结

进程描述符 task_struct

  • 内核把进程存放在叫任务队列(task list)的双向链表中
  • 任务队列(链表)中每一项就是一个task_struct,进程描述符
  • 进程描述符包含进程完整信息:打开文件、进程地址空间、挂起信号、进程状态等
  • 进程描述符的分配:slab分配器
  • 进程的标识:PID号,存放在进程描述符中
    在这里插入图片描述

进程家族树

  • 初始进程——init进程,pid=1,内核启动阶段创建
  • 父进程——每个进程都有一个父进程,task_struct 中parent指针指向
  • 子进程——每个进程有多个子进程,task_struc中children子进程链表

进程的退出

  • 进程终结的清理工作和进程描述符删除工作分开进程
  • 进程最后调用exit()函数,进程释放内存资源,进行清理。保留进程的进程描述符task_struct 。
  • 父进程获得子进程的信息后,子进程的进程描述符删除

什么的进程?什么是线程?

  • 进程是资源分配的基本单位,它是程序执行时的一个实例,在程序运行时创建。拥有自己的地址空间。
  • 线程是程序执行的最小单位,是进程的一个执行流,一个进程由多个线程组成的。多个线程共用地址空间
  • Linux中线程和进程不做区分,线程是一种特殊的进程,本质都是内核的一个task_struct。线程被看作是一个和其他进程共用某些资源的进程。
  • 同一时间,如果CPU是单核,只有一个进程在执行,所谓的并发执行,也是顺序执行,只不过由于切换速度太快,你以为这些进程在同步执行而已。多核CPU可以同一时间点有多个进程在执行。

在这里插入图片描述

进程的组成

进程实体(进程映像)由三部分组成:程序段、数据段、PCB(进程控制块)组成。

PCB是进程存在的唯一标志。PCB是给操作系统用的,而程序段和数据段是给进程自己使用的。

进程和线程的区别?

  1. 进程是资源分配的最小单位。

    线程是程序执行的最小单位,也是处理器调度的基本单位。两者均可并发执行。

  2. 进程有自己的独立地址空间,每启动一个进程,系统就会为它分配地址空间,建立数据表来维护代码段、堆栈段和数据段,这种操作非常昂贵。

    而线程是共享进程中的数据,使用相同的地址空间,因此,CPU切换一个线程的花费远比进程小很多,同时创建一个线程的开销也比进程小很多。

  3. 线程之间的通信更方便,同一进程下的线程共享全局变量、静态变量等数据,

    进程之间的通信需要以通信的方式(IPC)进行。

  4. 进程切换时,消耗的资源大,效率低。多进程程序更健壮,一个进程死掉并不会对另外一个进程造成影响址空间。

    线程切换时,消耗的资源小,效率高。多线程程序只要有一个线程死掉,整个进程也跟着死掉了。

  5. 执行过程:每个独立的进程有一个程序运行的入口、顺序执行序列和程序入口。但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。

  6. 线程执行开销小,但是不利于资源的管理和保护。进程执行开销大,但是能够很好的进行资源管理和保护,可以跨机器迁移。

什么时候用多进程?什么时候用多线程?

  1. 创建和销毁较频繁使用线程,因为创建进程花销大。
  2. 需要大量数据传送使用线程,因为多线程切换速度快,不需要跨越进程边界。
  3. 安全稳定选进程;快速频繁选线程;

多进程、多线程同步(通讯)的方法

进程间通讯:

(1)有名管道/无名管道(2)信号(3)共享内存(4)消息队列(5)信号量(6)socket

线程通讯(锁):

(1)信号量(2)读写锁(3)条件变量(4)互斥锁(5)自旋锁

线程可以独立运行吗?一个线程崩溃会导致整个进程崩溃吗?

线程不能独立运行,但一个线程崩溃不一定导致整个进程崩溃。

(1)线程属于进程,线程的运行需要依赖进程的地址空间和系统资源。

(2)线程崩溃的本质就是内存出错,若出错的内存没有被其他线程访问,则不会导致其他线程出错,也就不会导致进程崩溃。

不同线程之间不共享的内容?

​ 栈、寄存器、阻塞信号掩码、线程号。

Linux进程状态

五种基本状态:创建、运行、就绪、阻塞、终止

在这里插入图片描述

  • 创建状态:一个应用程序从系统上启动,首先就是进入创建状态,需要获取系统资源创建进程管理块(PCB:Process Control Block)完成资源分配。
  • 就绪状态:在创建状态完成之后,进程已经准备好,但是还未获得处理器资源,无法运行。
  • 运行状态:获取处理器资源,被系统调度,开始进入运行状态。如果进程的时间片用完了就进入就绪状态。
  • 阻塞状态:在运行状态期间,如果进行了阻塞的操作,如耗时的I/O操作,此时进程暂时无法操作就进入到了阻塞状态,在这些操作完成后就进入就绪状态。
  • 终止状态:进程结束或者被系统终止,进入终止状态

select、poll 和epoll的区别

  • select,poll,epoll都是IO多路复用的机制。可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。但select,poll,epoll本质上都是同步I/O,因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞的,而异步I/O则无需自己负责进行读写,异步I/O的实现会负责把数据从内核拷贝到用户空间。

  • select的时间复杂度O(n)。select采用无差别轮询所有流的方式,找出事件发生的流。最大只能支持1024个文件描述符,每次使用都需要把文件描述符集合从用户态拷贝到内核态,且内核需要遍历所有的fd,这在fd很多的时候会造成大的开销。

  • poll 和select 本质没有区别,但是它没有最大连接数的限制,原因是它是基于链表来存储的

  • epoll的时间复杂度O(1)。epoll没有了文件描述符的限制,使用一个文件描述符管理多个描述符。只在注册的时候拷贝没有添加的文件描述符到红黑树上,使用回调函数来返回数据,效率大大提高。

join和detach的区别?

​ join在当前线程调用join的话,该线程会等待子线程运行结束再继续向下运行。

​ 而detach则是让子线程在后台运行。一般如果子线程和当前线程的一些资源的话,那么该线程就需要使用join来等待子线程使用完自己再向下执行,否则当前线程执行完把资源释放掉就会出错。

fork()和vfork()的作用以及区别

fork()和vfork()都是创建一个进程

  • fork()子进程拷贝父进程所有资源,只有pid和ppid不一样;(实际是写时拷贝:平时是只读共享,当写入时才会拷贝)
  • vfork()出来的子进程会共享父进程的代码段和数据段,但是子进程会拥有自己的堆栈,而父进程会暂时被挂起,直到子进程调用exec()或者exit()函数才会恢复
  • fork()父子进程的执行次序不确定;vfork()保证子进程先运行,在调用exec()或者exit()函数才运行父进程
  • clone:选择性的和父进程共享一部分东西。

子进程从父进程继承的资源有哪些?

子进程继承父进程的绝大部分资源,包括堆栈、内存、用户号和组号、打开的文件描述符、当前工作目录、根目录。

子进程独有进程号、不同的父进程号、自己的文件描述符。

cpu处理器的三种活动情况

  1. 运行用户空间,执行用户进程。(如:常规的用户态程序)
  2. 运行内核空间,处于进程上下文,代表某个特定的进程执行。进程通过进程上下文和内核关联,可以睡眠,可以进行调度(如:用户态程序进行系统调用)
  3. 运行内核空间,处于中断上下文,和任何一个进程都无关,处理特定的中断。中断上下文和进程无关,没有后备进程,不能睡眠。因为睡眠系统会进行调度,用后备进程代替当前进程(如:中断服务程序,cpu空闲的空进程)

http://www.kler.cn/a/500908.html

相关文章:

  • 怎么抓取ios 移动app的https请求?
  • 青少年编程与数学 02-006 前端开发框架VUE 18课题、逻辑复用
  • 写读后感的时候,可以适当地引用书中的内容吗?
  • Jenkins触发器--在其他项目执行后构建
  • springCloud特色知识记录(基于黑马教程2024年)
  • MATLAB语言的多线程编程
  • Maven 仓库的分类
  • Cisco认证是Cisco公司建立的网络技术证书体系
  • C#解决浮点数精度丢失的问题(参考方案)
  • [DO374] Ansible 配置文件
  • 云服务器加了安全组端口还是无法访问
  • 一分钟学会文心一言API如何接入,文心一言API接入教程
  • 基于 JavaEE 的影视创作论坛
  • fitz获取pdf内容
  • 浅谈云计算04 | 云基础设施机制
  • 游戏引擎学习第78天
  • SmartScanner:智能化网络漏洞扫描的未来先锋
  • RAID储存技术
  • [创业之路-242]:《华为双向指挥系统》-1-组织再造-纠正企业管理的长短腿-科层制优缺点以及科层制企业的特点
  • uniapp Android 原生插件开发-Module扩展为例-从开发到测试到部署到uniapp项目
  • 算法练习01
  • AF3 Transition和ConditionedTransitionBlock类解读
  • C# 与 Windows API 交互的“秘密武器”:结构体和联合体
  • 【Vue + Antv X6】可拖拽流程图组件
  • NGINX--HTTPTCP负载均衡
  • 无需昂贵GPU:本地部署开源AI项目LocalAI你在消费级硬件上运行大模型