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

网站建设百度首页导视设计案例分析

网站建设百度首页,导视设计案例分析,网站建设需要有什么特点,设计官网首页在学习的时候找到几个十分好的工程和个人博客#xff0c;先码一下#xff0c;内容都摘自其中#xff0c;有些重难点做了补充#xff01; 才鲸 / 嵌入式软件笔试题汇总 嵌入式与Linux那些事 阿秀的学习笔记 小林coding 百问网linux 嵌入式软件面试合集 2022年春招实习十四面…在学习的时候找到几个十分好的工程和个人博客先码一下内容都摘自其中有些重难点做了补充 才鲸 / 嵌入式软件笔试题汇总 嵌入式与Linux那些事 阿秀的学习笔记 小林coding 百问网linux 嵌入式软件面试合集 2022年春招实习十四面嵌入式面经 文章目录 一、进程和线程1.1进程和线程的概念1.2 进程和线程的区别1.3 进程和线程使用场景1.4 进程的五种状态1.4.1 如何唤醒被阻塞的socket线程 1.5 创建进程的几种方式1.6 进程间通信1.6.1 方式1.6.2 优缺点 1.7 线程间同步1.7.1 方式 1.8 内核线程和用户线程1.8.1 概念1.8.2 区别1.8.3 优缺点 1.9 僵尸进程孤儿进程守护进程1.9.1 概念1.9.2 如何清理僵尸进程 二、堆和栈2.1 为什么堆的空间是不连续的2.2 用户栈和内核栈2.2.1 概念2.2.2用户栈和内核栈为什么不能共用一个栈2.2.3 线程是否具有相同的堆栈? 三、并发和互斥3.1 概念3.2 自旋锁和信号量3.2.1 定义3.3.2 区别 3.3 自旋锁和信号量可以睡眠吗为什么3.4 自旋锁和信号量可以用于中断中吗3.5 死锁3.5.1 产生死锁的原因3.5.2 死锁的4个必要条件是什么3.5.3 死锁的处理方式有哪些3.5.4 如何避免死锁 四、Linux系统4.1 内核与系统4.1.1 Linux内核的组成部分4.1.2 Linux系统的组成部分4.1.3 用户空间与内核通信方式有哪些4.1.4 系统调用与普通函数调用的区别?4.1.5 bootloader、内核 、根文件和应用程序的关系?4.1.6 Bootloader启动的两个阶段 4.2 程序4.2.1 一个程序从开始运行到结束的完整过程四个过程 4.3 中断和异常4.3.1 中断和异常的区别4.3.2 什么是缺页中断 一、进程和线程 1.1进程和线程的概念 进程是资源分配的基本单位它是程序执行时的一个实例在程序运行时创建。线程是程序执行的最小单位是进程的一个执行流一个进程由多个线程组成的。 1.2 进程和线程的区别 进程是资源分配的最小单位。线程是程序执行的最小单位也是处理器调度的基本单位但进程不是两者均可并发执行。进程有自己的独立地址空间每启动一个进程系统就会为它分配地址空间建立数据表来维护代码段、堆栈段和数据段这种操作非常昂贵。而线程是共享进程中的数据使用相同的地址空间因此CPU切换一个线程的花费远比进程小很多同时创建一个线程的开销也比进程小很多。线程之间的通信更方便同一进程下的线程共享全局变量、静态变量等数据而进程之间的通信需要以通信的方式IPC)进行。不过如何处理好同步与互斥是编写多线程程序的难点。但是多进程程序更健壮多线程程序只要有一个线程死掉整个进程也跟着死掉了而一个进程死掉并不会对另外一个进程造成影响因为进程有自己独立的地址空间。进程切换时消耗的资源大效率低。所以涉及到频繁的切换时使用线程要好于进程。同样如果要求同时进行并且又要共享某些变量的并发操作只能用线程不能用进程。执行过程每个独立的进程有一个程序运行的入口、顺序执行序列和程序入口。但是线程不能独立执行必须依存在应用程序中由应用程序提供多个线程执行控制。线程执行开销小但是不利于资源的管理和保护。线程适合在SMP机器双CPU系统上运行。进程执行开销大但是能够很好的进行资源管理和保护可以跨机器迁移。 1.3 进程和线程使用场景 对资源的管理和保护要求高不限制开销和效率时使用多进程。要求效率高频繁切换时资源的保护管理要求不是很高时使用多线程。 1.4 进程的五种状态 进程可以分为五个状态分别是 创建状态就绪状态运行状态阻塞状态终止状态 创建状态 一个应用程序从系统上启动首先就是进入创建状态需要获取系统资源创建进程管理块PCBProcess Control Block完成资源分配。 就绪状态 在创建状态完成之后进程已经准备好但是还未获得处理器资源无法运行。 运行状态 获取处理器资源被系统调度开始进入运行状态。如果进程的时间片用完了就进入就绪状态。 阻塞状态 在运行状态期间如果进行了阻塞的操作如耗时的I/O操作此时进程暂时无法操作就进入到了阻塞状态在这些操作完成后就进入就绪状态。 终止状态 进程结束或者被系统终止进入终止状态。 进程的状态转换图 1.4.1 如何唤醒被阻塞的socket线程 同步阻塞 等待锁的释放 等待阻塞 使用Thread.sleep造成的阻塞:时间结束后自动进入RUNNABLE状态使用Thread.wait造成的阻塞:使用Thread.notify或者Thread.notifyAll唤醒使用Thread.join造成的阻塞:等待上一个线程执行完后自动进入RUNNABLE状态使用Thread.suspend造成的阻塞:使用Thread.resum唤醒使用LockSupport.park造成的阻塞:使用LockSupport.unpark唤醒使用LockSupport.parkNanos造成的阻塞:指定时间结束后自动唤醒使用LockSupport.parkUntil造成的阻塞:到达指定的时间自动唤醒 1.5 创建进程的几种方式 创建进程的多种方式但凡是硬件都需要有操作系统去管理只要有操作系统就有进程的概念就需要有创建进程的方式一些操作系统只为个应用程序设计比如扫地机器人一旦启动所有的进程都已经存在。 而对于通用系统跑很多应用程序需要有系统运行过程中创建或撤销进程的能力主要分为4种形式 创建新的进程 系统初始化查看进程 linux中用ps命令 windows中用任务管理器前台进程负责与用户交互后台运行的进程与用户无关运行在后台并且只在需要时才唤醒的进程称为守护进程如电子邮件、web页面、新闻、打印一个进程在运行过程中开启了子进程如 nginx开启多进程os. fork, subprocess Popen等用户的交互式请求而创建一个新进程如用户用鼠标双击任意款软件图片q微信暴风影音等—个批处理作业的初始化只在大型机的批处理系统中应用无论哪-种新进程的创建都是由—个已经存在的进程执行了—个用于创建进程的系统调用而创建的。 1.6 进程间通信 1.6.1 方式 管道(pipe) 管道这种通讯方式有两种限制一是半双工的通信数据只能单向流动二是只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。流管道s_pipe: 去除了第一种限制,可以双向传输全双工。管道可用于具有亲缘关系进程间的通信。命名管道name_pipe克服了管道没有名字的限制因此除具有管道所具有的功能外它还允许无亲缘关系进程间的通信命名管道也交FIFO。 信号量(semophore) 信号量是一个计数器可以用来控制多个进程对共享资源的访问。它常作为一种锁机制防止某进程正在访问共享资源时其他进程也访问该资源。因此主要作为进程间以及同一进程内不同线程之间的同步手段。 消息队列(message queue) 消息队列是由消息组成的链表存放在内核中并由消息队列标识符标识。消息队列是消息的链接表包括Posix消息队列system V消息队列。有足够权限的进程可以向队列中添加消息被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少管道只能承载无格式字节流以及缓冲区大小受限等缺点。 信号(singnal) 信号是一种比较复杂的通信方式用于通知接收进程某个事件已经发生。主要作为进程间以及同一进程不同线程之间的同步手段。 共享内存(shared memory) 共享内存就是映射一段能被其他进程所访问的内存这段共享内存由一个进程创建但多个进程都可以访问。共享内存是最快的 IPC 方式它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制如信号量配合使用来实现进程间的同步和通信。 套接字(socket) 套解字也是一种进程间通信机制与其他通信机制不同的是它可用于不同机器间的进程通信。 1.6.2 优缺点 管道 速度慢容量有限只有父子进程能通讯。 FIFOFirst In, First Out 任何进程间都能通讯但速度慢。 消息队列 容量受到系统限制且要注意第一次读的时候要考虑上一次没有读完数据的问题消息队列可以不再局限于父子进程而允许任意进程通过共享消息队列来实现进程间通信并由系统调用函数来实现消息发送和接收之间的同步从而使得用户在使用消息缓冲进行通信时不再需要考虑同步问题使用方便但是信息的复制需要额外消耗CPU的时间不适宜于信息量大或操作频繁的场合。此种方法不太常用。 信号量 不能用来传递复杂消息只能用来同步。 共享内存 利用内存缓冲区直接交换信息无须复制快捷、信息量大是其优点。共享内存块提供了在任意数量的进程之间进行高效双向通信的机制。每个使用者都可以读取写入数据但是所有程序之间必须达成并遵守一定的协议以防止诸如在读取信息之前覆写内存空间等竞争状态的出现。 进程间通信方式的选择 PIPE和FIFO(有名管道)用来实现进程间相互发送非常短小的、频率很高的消息这两种方式通常适用于两个进程间的通信。 共享内存用来实现进程间共享的、非常庞大的、读写操作频率很高的数据这种方法适用于多进程间的通信。 其他考虑用socket。主要应用在分布式开发中。 1.7 线程间同步 1.7.1 方式 现在流行的进程线程同步互斥的控制机制其实是由最原始、最基本的4种方法临界区、互斥量、信号 量和事件实现的。 临界区通过对多线程的串行化来访问公共资源或一段代码速度快适合控制数据访问。在任意时刻只允许一个线程访问共享资源如果有多个线程试图访问共享资源那么当有一个线程进入后其他试图访问共享资源的线程将会被挂起并一直等到进入临界区的线程离开临界在被释放后其他线程才可以抢占。 互斥量为协调对一个共享资源的单独访问而设计只有拥有互斥量的线程才有权限去访问系统的公共资源因为互斥量只有一个所以能够保证资源不会同时被多个线程访问。互斥不仅能实现同一应用程序的公共资源安全共享还能实现不同应用程序的公共资源安全共享。 信号量为控制一个具有有限数量的用户资源而设计。它允许多个线程在同一个时刻去访问同一个资源但一般需要限制同一时刻访问此资源的最大线程数目 事件用来通知线程有一些事件已发生从而启动后继任务的开始。 读写锁Reader-Writer Lock读写锁是一种特殊的锁它可以分为读锁和写锁两种。当一个线程需要读取共享资源时可以获取读锁此时其他线程也可以同时获取读锁但无法获取写锁当一个线程需要修改共享资源时需要获取写锁此时其他线程无法获取读锁或写锁。读写锁适用于读操作远远多于写操作的场景可以提高程序的并发性能。 屏障Barrier屏障是一种线程同步机制它可以让多个线程在某个点上等待直到所有线程都到达该点后再继续执行。屏障适用于多阶段任务的场景可以保证多个线程在某个阶段完成后再开始下一阶段任务。 1.8 内核线程和用户线程 1.8.1 概念 用户线程指不需要内核支持而在用户程序中实现的线程其不依赖于操作系统核心应用进程利用线程库提供创建、同步、调度和管理线程的函数来控制用户线程。不需要用户态/核心态切换速度快操作系统内核不知道多线程的存在因此一个线程阻塞将使得整个进程包括它的所有线程阻塞。由于这里的处理器时间片分配是以进程为基本单位所以每个线程执行的时间相对减少。内核线程由操作系统内核创建和撤销。内核维护进程及线程的上下文信息以及线程切换。一个内核线程由于I/O操作而阻塞不会影响其它线程的运行。 1.8.2 区别 内核支持线程是OS内核可感知的而用户级线程是OS内核不可感知的。用户级线程的创建、撤消和调度不需要OS内核的支持是在语言如Java这一级处理的而内核支持线程的创建、撤消和调度都需OS内核提供支持而且与进程的创建、撤消和调度大体是相同的。用户级线程执行系统调用指令时将导致其所属进程被中断而内核支持线程执行系统调用指令时只导致该线程被中断。在只有用户级线程的系统内CPU调度还是以进程为单位处于运行状态的进程中的多个线程由用户程序控制线程的轮换运行在有内核支持线程的系统内CPU调度则以线程为单位由OS的线程调度程序负责线程的调度。用户级线程的程序实体是运行在用户态下的程序而内核支持线程的程序实体则是可以运行在任何状态下的程序。 1.8.3 优缺点 内核线程的优点 当有多个处理机时一个进程的多个线程可以同时执行。 缺点 由内核进行调度。 用户线程的优点 线程的调度不需要内核直接参与控制简单。可以在不支持线程的操作系统中实现。创建和销毁线程、线程切换代价等线程管理的代价比内核线程少得多。允许每个进程定制自己的调度算法线程管理比较灵活。这就是必须自己写管理程序与内核线程的区别线程能够利用的表空间和堆栈空间比内核级线程多。同一进程中只能同时有一个线程在运行如果有一个线程使用了系统调用而阻塞那么整个进程都会被挂起。另外页面失效也会产生同样的问题。 缺点 资源调度按照进程进行多个处理机下同一个进程中的线程只能在同一个处理机下分时复用。 1.9 僵尸进程孤儿进程守护进程 1.9.1 概念 僵尸进程是一个进程使用fork创建子进程如果子进程退出而父进程并没有调用wait或waitpid获取子进程的状态信息那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵死进程。 孤儿进程是因为父进程异常结束了然后被1号进程init收养。 守护进程是创建守护进程时有意把父进程结束然后被1号进程init收养 区分一个正常运行的子进程如果此刻子进程退出父进程没有及时调用wait或waitpid收回子进程的系统资源该进程就是僵尸进程如果系统收回了就是正常退出如果一个正常运行的子进程父进程退出了但是子进程还在该进程此刻是孤儿进程被init收养如果父进程是故意被杀掉子进程做相应处理后就是守护进程 1.9.2 如何清理僵尸进程 僵尸进程的产生是因为父进程没有 wait() 子进程。所以如果我们自己写程序的话一定要在父进程中通过wait() 来避免僵尸进程的产生。 当系统中出现了僵尸进程时我们是无法通过 kill 命令把它清除掉的。但是我们可以杀死它的父进程让它变成孤儿进程并进一步被系统中管理孤儿进程的进程收养并清理。 二、堆和栈 2.1 为什么堆的空间是不连续的 堆包含一个链表来维护已用和空闲的内存块。在堆上新分配用 new 或者 malloc内存是从空闲的内存块中找到一些满足要求的合适块。所以可能让人觉得只要有很多不连续的零散的小区域只要总数达到申请的内存块就可以分配。 但事实上是不行的这又让人觉得是不是零散的内存块不能连接成一个大的空间而必须要一整块连续的内存空间才能申请成功呢。 申请和释放许多小的块可能会产生如下状态在已用块之间存在很多小的空闲块。进而申请大块内存失败虽然空闲块的总和足够但是空闲的小块是零散的不连续的不能满足申请的大小这叫做“堆碎片”。 当旁边有空闲块的已用块被释放时新的空闲块会与相连的空闲块合并成一个大的空闲块这样就可以有效的减少堆碎片的产生。 堆分配的空间在逻辑地址虚拟地址上是连续的但在物理地址上是不连续的因为采用了页式内存管理,windows下有段机制、分页机制如果逻辑地址空间上已经没有一段连续且足够大的空间则分配内存失败。 综上所述堆内存的空间不连续是由于堆内存的动态分配和释放方式所导致的。 2.2 用户栈和内核栈 2.2.1 概念 用户栈和内核栈都是计算机系统中用于处理函数调用、中断处理和系统调用等操作时保存程序状态和临时数据的栈。 用户栈指的是在用户空间中的栈用于保存应用程序的函数调用现场和临时数据。当应用程序调用函数时函数的参数和返回地址等数据会被压入用户栈中函数执行完毕后这些数据会从栈中弹出程序会回到调用函数的位置继续执行。用户栈通常由操作系统在进程创建时分配每个进程都有自己的用户栈。 内核栈指的是在内核空间中的栈用于保存内核中断处理程序和系统调用处理程序执行时的现场和临时数据。当系统发生中断或者进行系统调用时处理程序会被调用并执行此时处理程序需要保存中断或者系统调用前的现场和数据这些数据会被压入内核栈中。当处理程序执行完毕后这些数据会从栈中弹出系统会回到中断或系统调用前的状态继续执行。内核栈通常由操作系统在内核初始化时分配每个CPU核心都有自己的内核栈。 需要注意的是用户栈和内核栈是分开的它们的作用范围和访问权限是不同的。用户栈只能被应用程序访问而内核栈只能被内核代码访问。此外用户栈和内核栈的大小也是不同的通常内核栈比用户栈要小。 2.2.2用户栈和内核栈为什么不能共用一个栈 用户栈和内核栈不能共用一个栈的原因主要有以下几点 权限不同用户栈和内核栈的访问权限不同。用户栈只能被应用程序访问而内核栈只能被内核代码访问。如果共用一个栈由于应用程序可以直接访问栈就有可能会破坏内核栈中的数据导致系统出现错误或崩溃。 大小不同用户栈和内核栈的大小不同。用户栈通常比内核栈大因为应用程序需要保存更多的函数调用现场和临时数据。如果共用一个栈就可能会出现栈溢出的情况导致数据丢失或程序崩溃。 安全性问题共用一个栈可能会导致安全性问题。由于用户栈和内核栈的数据是混合在一起的攻击者有可能通过修改用户栈中的数据来影响内核代码的执行从而攻击系统。如果使用不同的栈就可以更好地保障系统的安全性。 2.2.3 线程是否具有相同的堆栈? 在计算机系统中每个线程都有自己的堆栈线程之间的堆栈是独立的不共享。线程的堆栈用于存储线程函数的局部变量、函数参数、函数返回地址等数据以及线程调用其他函数时的现场信息。 由于每个线程都有自己的堆栈因此线程之间的堆栈是相互独立的不会相互干扰。这也意味着在多线程编程中每个线程都需要分配独立的堆栈空间。如果多个线程共享同一个堆栈空间就会导致数据冲突和互相干扰的问题从而引发程序崩溃等严重后果。 需要注意的是虽然每个线程都有自己的堆栈但是线程之间可以共享堆空间。堆空间是由操作系统分配和管理的不属于任何一个线程的私有空间因此线程之间可以通过堆空间来共享数据。不过在使用堆空间进行数据共享时需要采取相应的同步措施来避免数据竞争和冲突的问题。 三、并发和互斥 3.1 概念 并发是指多个任务或进程可以在同一时间段内执行它可以提高系统的效率和资源利用率。并发执行的任务或进程之间可能需要共享一些资源如内存、文件、网络连接等。 互斥是指多个任务或进程对同一资源的访问是互相排斥的。在多任务或多进程的环境下如果多个任务或进程同时访问同一个资源可能会导致数据的不一致性、死锁等问题。因此需要采用互斥控制来保证同一时间只有一个任务或进程能够访问共享资源。 解决竞态问题的途径是保证对共享资源的互斥访问所谓互斥访问就是指一个执行单元在访问共享资源并发指的是多个执行单元同时、并行被执行而并发的执行单元对共享资源硬件资源和软件上的全局变量、静态变量等的访问则很容易导致竞态。 的时候其他的执行单元都被禁止访问。 访问共享资源的代码区域被称为临界区临界区需要以某种互斥机制加以保护。中断屏蔽原子操作自旋锁和信号量都是linux设备驱动中可采用的互斥途径。 3.2 自旋锁和信号量 3.2.1 定义 自旋锁顾名思义我们可以把他理解成厕所门上的一把锁。这个厕所门只有一把钥匙当我们进去时把钥匙取下来进去后反锁。那么当第二个人想进来必须等我们出去后才可以。当第二个人在外面等待时可能会一直等待在门口转圈。 我们的自旋锁也是这样自旋锁只有锁定和解锁两个状态。当我们进入拿上钥匙进入厕所这就相当于自旋锁锁定的状态期间谁也不可以进来。当第二个人想要进来这相当于线程B想要访问这个共享资源但是目前不能访问所以线程B就一直在原地等待一直查询是否可以访问这个共享资源。当我们从厕所出来后这个时候就“解锁”了只有再这个时候线程B才能访问。 假如在厕所的人待的时间太长怎么办外面的人一直等待吗如果换做是我们肯定不会这样简直浪费时间可能我们会寻找其他方法解决问题。自旋锁也是这样的如果线程A持有自旋锁时间过长显然会浪费处理器的时间降低了系统性能。我们知道CPU最伟大的发明就在于多线程操作这个时候让线程B在这里傻傻的不知道还要等待多久显然是不合理的。因此自旋锁只适合短期持有如果遇到需要长时间持有的情况我们就要换一种方式了互斥体。 信号量和自旋锁有些相似不同的是信号量会发出一个信号告诉你还需要等多久。因此不会出现傻傻等待的情况。比如有100个停车位的停车场门口电子显示屏上实时更新的停车数量就是一个信号量。这个停车的数量就是一个信号量他告诉我们是否可以停车进去。当有车开进去信号量加一当有车开出来信号量减一。 比如厕所一次只能让一个人进去当A在里面的时候B想进去如果是自旋锁那么B就会一直在门口傻傻等待。如果是信号量A就会给B一个信号你先回去吧我出来了叫你。这就是一个信号量的例子B听到A发出的信号后可以先回去睡觉等待A出来。 因此信号量显然可以提高系统的执行效率避免了许多无用功。 3.3.2 区别 由于争用信号量的进程在等待锁重新变为可用时会睡眠所以信号量适用于锁会被长时间持有的情况。相反锁被短时间持有时使用信号量就不太适宜了因为睡眠引起的耗时可能比锁被占用的全部时间还要长。由于执行线程在锁被争用时会睡眠所以只能在进程上下文中才能获取信号量锁因为在中断上下文中使用自旋锁是不能进行调度的。你可以在持有信号量时去睡眠当然你也可能并不需要睡眠因为当其它进程试图获得同一信号量时不会因此而死锁因为该进程也只是去睡眠而已而你最终会继续执行的。在你占用信号量的同时不能占用自旋锁因为在你等待信号量时可能会睡眠而在持有自旋锁时是不允许睡眠的。信号量锁保护的临界区可包含可能引起阻塞的代码而自旋锁则绝对要避免用来保护包含这样代码的临界区因为阻塞意味着要进行进程的切换如果进程被切换出去后另一进程企图获取本自旋锁死锁就会发生。信号量不同于自旋锁它不会禁止内核抢占自旋锁被持有时内核不能被抢占所以持有信号量的代码可以被抢占这意味着信号量不会对调度的等待时间带来负面影响。 3.3 自旋锁和信号量可以睡眠吗为什么 自旋锁不能睡眠信号量可以。 原因 自旋锁禁止处理器抢占而信号量不禁止处理器抢占。 基于这个原因如果自旋锁在锁住以后进入睡眠由于不能进行处理器抢占其他系统进程将都不能获得CPU而运行因此不能唤醒睡眠的自旋锁因此系统将不响应任何操作除了中断或多核的情况下面会讨论。而信号量在临界区睡眠后其他进程可以用抢占的方式继续运行从而可以实现内存拷贝等功能而使得睡眠的信号量程序由于获得了等待的资源而被唤醒从而恢复了正常的代码运行。 当然自旋锁的睡眠的情况包含考虑多核CPU和中断的因素。自旋锁睡眠时只是当前CPU的睡眠以及当前CPU的禁止处理器抢占所以如果存在多个CPU那么其他活动的CPU可以继续运行使操作系统功能正常并有可能完成相应工作而唤醒睡眠了的自旋锁从而没有造成系统死机自旋锁睡眠时如果允许中断处理那么中断的代码是可以正常运行的但是中断通常不会唤醒睡眠的自旋锁因此系统仍然运行不正常。 3.4 自旋锁和信号量可以用于中断中吗 信号量不能用于中断中因为信号量会引起休眠中断不能休眠。 自旋锁可以用于中断。在获取锁之前一定要先禁止本地中断也就是本CPU中断对于多核SOC来说会有多个CPU核否则可能导致锁死现象的发生。 3.5 死锁 3.5.1 产生死锁的原因 死锁是多线程或多进程并发执行时经常遇到的一种问题它发生在两个或多个进程或线程之间每个进程或线程都在等待其他进程或线程释放其所持有的资源而无法向前执行。死锁的产生通常有以下几个原因 竞争资源两个或多个进程或线程同时竞争某个共享资源例如文件、网络连接、共享内存等。如果某个进程或线程持有了该资源其他进程或线程就无法访问该资源从而导致死锁。竞争顺序进程或线程在访问多个资源时访问资源的顺序不一致导致互相等待。例如进程A持有资源X请求资源Y而进程B持有资源Y请求资源X这种情况会导致死锁。缺少资源如果系统中的资源不足以满足所有进程或线程的需要就可能导致死锁。例如如果系统只有一个打印机而多个进程或线程都需要打印文件就可能导致死锁。饥饿某个进程或线程一直无法获取所需的资源导致一直等待无法继续执行这种情况称为饥饿。如果某个进程或线程一直处于饥饿状态会导致死锁。 3.5.2 死锁的4个必要条件是什么 死锁的4个必要条件也称为死锁产生的充分条件是指在满足以下4个条件的情况下才有可能发生死锁 互斥条件Mutual Exclusion指一个资源同时只能被一个进程或线程占用如果一个进程或线程已经占用了该资源其他进程或线程就不能再占用该资源。请求与保持条件Hold and Wait指一个进程或线程在持有某些资源的同时又请求其他进程或线程所持有的资源而其他进程或线程又在等待该进程或线程所持有的资源。不可剥夺条件Non-preemption指一个进程或线程已经获得了某个资源在该进程或线程自己不释放该资源之前其他进程或线程不能夺取该资源。循环等待条件Circular Wait指系统中存在一个进程或线程资源的循环等待链每个进程或线程都在等待下一个进程或线程所持有的资源。 3.5.3 死锁的处理方式有哪些 死锁的处理方式主要从预防死锁、避免死锁、检测与解除死锁这四个方面来进行处理。 预防死锁 资源一次性分配破坏请求和保持条件可剥夺资源即当某进程新的资源未满足时释放已占有的资源破坏不可剥夺条件资源有序分配法系统给每类资源赋予一个编号每一个进程按编号递增的顺序请求资源释放则相反破坏环路等待条件 避免死锁 预防死锁的几种策略会严重地损害系统性能。因此在避免死锁时要施加较弱的限制从而获得较满意的系统性能。由于在避免死锁的策略中允许进程动态地申请资源。因而系统在进行资源分配之前预先计算资源分配的安全性。若此次分配不会导致系统进入不安全状态则将资源分配给进程否则进程等待。其中最具有代表性的避免死锁算法是银行家算法。 检测死锁 首先为每个进程和每个资源指定一个唯一的号码然后建立资源分配表和进程等待表。 解除死锁 当发现有进程死锁后便应立即把它从死锁状态中解脱出来常采用的方法有 剥夺资源从其它进程剥夺足够数量的资源给死锁进程以解除死锁状态撤消进程可以直接撤消死锁进程或撤消代价最小的进程直至有足够的资源可用死锁状态消除为止所谓代价是指优先级、运行代价、进程的重要性和价值等。 3.5.4 如何避免死锁 下面将具体举例说明如何通过不同的措施来避免死锁的发生 **避免资源竞争**例如在多线程程序中不同的线程可以使用不同的变量或对象避免多个线程同时访问同一个变量或对象从而减少资源竞争和死锁的发生。**避免持有资源的同时继续请求其他资源**例如在操作系统中进程可以一次性请求所有需要的资源避免在持有某些资源的同时请求其他资源从而避免产生循环等待的情况。**引入资源有序分配策略**例如在银行家算法中系统会按照一定的顺序分配资源避免不同进程之间的资源竞争和循环等待。在实现时可以设置一个资源分配的优先级根据优先级依次分配资源避免资源竞争和死锁。**引入资源剥夺机制**例如在操作系统中当某个进程占用的资源被其他进程请求时可以剥夺该进程所占用的资源以满足其他进程的需要。在实现时可以设置一个资源分配的策略当某个进程请求的资源已被其他进程占用时可以剥夺该进程的资源以满足其他进程的需要。**引入资源预分配机制**例如在分布式系统中可以预先分配所有需要的资源避免了资源竞争和循环等待的情况。在实现时可以在系统启动时预先分配所有需要的资源并将资源分配给不同的进程或节点避免资源竞争和死锁。**采用死锁预防算法**例如在银行家算法中根据进程的资源需求和系统中的资源情况动态地分配资源避免系统进入死锁状态。在实现时可以通过监测进程的资源占用情况和资源请求情况及时调整资源分配策略避免死锁的发生。 四、Linux系统 4.1 内核与系统 4.1.1 Linux内核的组成部分 Linux内核主要由五个子系统组成进程调度内存管理虚拟文件系统网络接口进程间通信。 4.1.2 Linux系统的组成部分 Linux系统一般有4个主要部分内核、shell、文件系统和应用程序。 4.1.3 用户空间与内核通信方式有哪些 **系统调用**系统调用是用户空间程序向内核发起请求的标准方式。用户空间程序通过调用系统调用接口向内核发送请求内核收到请求后执行相应操作并返回结果。proc 文件系统proc 文件系统是一个虚拟文件系统它提供了一种方便的方式让用户空间程序通过文件的形式读写内核的信息。用户空间程序可以通过读取 /proc 文件系统中的文件来获取内核的状态信息也可以通过写入 /proc 文件系统中的文件来修改内核的配置参数。sysfs 文件系统sysfs 文件系统也是一个虚拟文件系统它提供了一种以属性的形式表示设备和驱动程序的方式用户空间程序可以通过读写 sysfs 文件系统中的属性来与内核进行通信。netlink 套接字netlink 套接字是一种专门用于内核与用户空间通信的套接字它支持异步通信和多路复用等特性。用户空间程序可以通过创建 netlink 套接字向内核发送请求和接收事件通知。ioctl 接口ioctl 接口是一种特殊的系统调用它允许用户空间程序向内核发起一些特定的控制操作。用户空间程序通过调用 ioctl 函数向内核传递特定的命令代码和参数来实现与内核的通信。procfs 文件系统procfs 文件系统是一种虚拟文件系统与 /proc 文件系统类似但它提供了一种更加灵活的方式让用户空间程序通过文件的形式读写内核的信息。与 /proc 文件系统不同的是procfs 文件系统中的文件可以支持任意格式的数据而不仅仅是文本格式。共享内存共享内存是一种特殊的内存映射方式它允许用户空间程序和内核共享一块物理内存。用户空间程序可以将共享内存映射到自己的地址空间中然后直接读写共享内存中的数据从而实现与内核的通信。系统信号系统信号是一种异步通知机制它允许内核向用户空间程序发送一些特定的事件通知。用户空间程序可以通过注册信号处理函数来处理这些事件通知从而实现与内核的通信。内核模块参数内核模块参数是一种特殊的配置参数它们可以被内核模块读取和修改。用户空间程序可以通过修改内核模块参数的值来影响内核模块的行为和功能。 4.1.4 系统调用与普通函数调用的区别? 调用机制不同普通函数调用是在用户空间内部完成的(无堆栈切换)而系统调用是需要将控制权从用户空间切换到内核空间有堆栈切换由内核完成操作然后再将控制权返回用户空间。权限限制不同系统调用需要进行一些敏感操作如修改系统状态、访问硬件资源等因此需要具有特殊的权限。而普通函数调用则不需要特殊权限任何用户空间程序都可以调用它。调用开销不同由于系统调用需要将控制权从用户空间切换到内核空间需要进行一些额外的操作因此系统调用的调用开销通常比普通函数调用要高。参数传递方式不同在普通函数调用中函数参数通常是通过堆栈传递的而在系统调用中参数通常是通过寄存器或内存传递的。返回值不同普通函数调用的返回值通常是直接返回给调用者的而系统调用的返回值通常是通过寄存器或内存返回给调用者的。 4.1.5 bootloader、内核 、根文件和应用程序的关系? BootloaderBootloader 是系统启动的第一阶段它的主要作用是加载内核并将控制权转交给内核。在加载内核之前bootloader 还可以提供一些启动参数和配置信息例如指定内核的启动参数、指定根文件系统的位置等。内核内核是系统启动的第二阶段它是操作系统的核心负责管理计算机的硬件资源和提供系统调用等服务。在启动过程中内核会通过挂载根文件系统来获取系统所需的文件和配置信息。根文件系统根文件系统是 Linux 系统的基本文件系统它包含了操作系统的所有文件和目录包括设备文件、配置文件、库文件和可执行文件等。在 Linux 系统中根文件系统是由内核挂载的第一个文件系统它通常位于硬盘的一个分区中也可以是一个网络文件系统NFS。应用程序应用程序是运行在 Linux 系统中的程序它们可以是系统自带的一些工具和服务也可以是用户自己编写的程序。应用程序需要依赖系统的库和配置文件这些文件通常位于根文件系统的特定目录下例如 /usr/lib、/etc 等。 因此bootloader、内核、根文件系统和应用程序之间的关系是bootloader 会在系统启动时加载内核内核会在启动过程中挂载根文件系统并从根文件系统中读取所需的文件和配置信息最终启动应用程序并提供相应的服务。这四个组成部分共同构成了一个完整的 Linux 系统。 4.1.6 Bootloader启动的两个阶段 Stage1:汇编语言 基本的硬件初始化关闭看门狗和中断MMU带操作系统CACHE。配置系统工作时钟;为加载stage2准备RAM空间;拷贝内核映像和文件系统映像到RAM中;设置堆栈指针sp;跳到stage2的入口点. Stage2:c语言 初始化本阶段要使用到的硬件设备led uart等;检测系统的内存映射 ;加载内核映像和文件系统映像 ;设置内核的启动参数. 嵌入式系统中广泛采用的非易失性存储器通常是Flash而Bootloader就位于该存储器的最前端所以系统上电或复位后执行的第一段程序便是Bootloader。 4.2 程序 4.2.1 一个程序从开始运行到结束的完整过程四个过程 预处理Pre-Processing、编译Compiling、汇编Assembling、链接Linking。 4.3 中断和异常 4.3.1 中断和异常的区别 触发方式不同中断是由外部设备或者其他程序发起的用于通知 CPU 处理某个事件例如键盘输入、网络数据到达等。而异常则是由 CPU 内部发起的通常是因为程序执行出现了错误或者非法操作例如除以零、访问非法内存等。处理方式不同当 CPU 接收到中断信号时它会暂停当前任务保存当前上下文转而处理中断事件。而当 CPU 接收到异常信号时它会立即停止当前任务保存当前上下文并跳转到异常处理程序。异常处理程序通常会尝试修复错误并恢复程序的执行。响应时间不同中断通常需要等待外部设备或者其他程序发出信号而异常通常发生在程序的执行过程中几乎是实时发生的。处理结果不同中断处理完成后CPU 会回到之前的任务继续执行。而异常处理完成后程序可能会继续执行也可能会被终止这取决于异常的类型和处理方式。 4.3.2 什么是缺页中断 缺页中断在请求分页系统中可以通过查询页表中的状态位来确定所要访问的页面是否存在于内存中。每当所要访问的页面不在内存是会产生一次缺页中断此时操作系统会根据页表中的外存地址在外存中找到所缺的一页将其调入内存。 缺页本身是一种中断与一般的中断一样需要经过4个处理步骤 保护CPU现场分析中断原因转入缺页中断处理程序进行处理恢复CPU现场继续执行。 但是缺页中断是由于所要访问的页面不存在于内存时由硬件所产生的一种特殊的中断因此与一般的中断存在区别 在指令执行期间产生和处理缺页中断信号一条指令在执行期间可能产生多次缺页中断缺页中断返回是执行产生中断的一条指令而一般的中断返回是执行下一条指令。
http://www.hkea.cn/news/14348712/

相关文章:

  • 深圳工程建设信息网站搜索引擎推广方案案例
  • 湖北建设厅网站上查询html网站设计作品
  • 网站哪个服务器好网站域名属于哪里管
  • dw做网站投票wordpress原创公司主题
  • 新建网站怎么做优化微信网站特征
  • 网站审核备案wordpress用vps搭建
  • 有哪些做共享充电宝的网站上海网络营销公司
  • 做自媒体怎么在其它网站搬运内容北京集团公司注册流程
  • 网站404报错深圳企业黄页网站
  • 佛山网站建设公司哪家最好上海网络公司查询
  • 衡阳网站网站建设厦门seo关键词优化运营
  • 怒江企业网站建设哪个企业做网站
  • 网站制作流程详解(学做网站第一步)wordpress 最强大主题
  • 自己如何建立网站电影网站开发技术
  • 中小型企业网站建设企业上海虹口网站建设
  • 东莞做营销型网站软件技术是什么专业
  • 添加网站关键词建设网站方法
  • 重庆专业网站推广报价云主机上传网站
  • 有声小说网站开发百姓网站制作
  • 龙岗网站建设多少钱中国做视频网站有哪些
  • 怎样创建网站网站换模板对seo
  • 做国外商品的网站推荐网站网页
  • 个人网站怎么做才能值钱建设移动门户
  • 基础网站建设的实施步骤wordpress权限控制
  • 中文绿色环保网站模板泰安做网站建设的公司
  • 侵入别人的网站怎么做制作网站协议书
  • 沈阳网站建设选网龙建立选区快捷键ps
  • 网站推广优化wordpress还是thinkphp
  • 谷歌网站地图怎么做免费的企业网站
  • 医院信息化建设网站通用软件开发