(嵌入式八股)第5章 操作系统(三)

5.21 用户空间与内核通信方式

1. 系统调用(System Call)

系统调用是用户程序通过内核执行特权操作的方式。用户程序通过系统调用向内核请求服务,如读写文件、创建进程等。

代码例程:文件操作系统调用

  • open():系统调用,用于打开文件。如果文件不存在,则会创建它。返回一个文件描述符。
  • write():系统调用,用于向打开的文件中写入数据。它将数据从缓冲区写入文件。
  • close():系统调用,关闭打开的文件并释放资源。
  • 在用户空间程序中,系统调用如 openwriteclose 使得程序能够向内核请求操作文件的服务。通过这些接口,用户程序能访问到硬盘上的文件,而不需要直接操作硬件。

    2. 文件接口(File Interface)

    文件接口是用户程序通过标准文件操作与内核进行通信的常见方式,允许用户程序通过文件进行数据的读写。

    代码例程:文件读写

  • fopen():打开文件用于读取操作。
  • fgets():从文件中读取一行内容到缓冲区。
  • fclose():关闭文件操作。
  • 文件接口通过标准的 C 库函数,如 fopen()fgets()fclose(),允许用户程序与内核中的文件系统进行交互。这是用户程序与内核进行数据交换和管理的一种常见方式。

    3. procfs

    /proc 是一个虚拟文件系统,用户空间程序通过读取和写入 /proc 文件系统的文件与内核通信,获取或修改内核状态和信息。

    代码例程:读取 /proc/cpuinfo

  • /proc/cpuinfo 提供了关于系统 CPU 的信息。
  • 使用 fopen() 打开文件,并通过 fgets() 逐行读取文件内容。
  • 通过读取 /proc 文件系统中的虚拟文件,用户空间程序可以获取系统级的硬件和内核状态信息。

    4. sysfs

    /sys 是另一个虚拟文件系统,用于提供内核、硬件设备的状态信息。通过读取 /sys 中的文件,用户空间程序可以查询或修改设备属性。

    代码例程:读取 /sys/class/net/eth0/address

  • /sys/class/net/eth0/address 提供了网络接口 eth0 的 MAC 地址。
  • 通过 fopen()fgets() 读取文件内容。
  • 通过访问 /sys 文件系统,用户程序可以查询硬件设备的属性和内核参数。这样可以动态地获取或修改设备信息,常用于设备管理和配置。

    5. 共享内存(Shared Memory)

    共享内存是一种进程间通信(IPC)机制,允许多个进程共享一块内存区域。这是最快的进程间通信方式,因为进程之间无需复制数据。

    代码例程:创建和使用共享内存

  • shmget():创建共享内存并返回一个标识符。
  • shmat():将共享内存附加到当前进程的地址空间。
  • shmdt():分离共享内存。
  • shmctl():删除共享内存。
  • 6. 设备文件(Device Files)

    设备文件是用户空间程序与内核之间进行通信的常见方式,设备文件代表了硬件设备,如串口、硬盘、字符设备等。

    代码例程:通过设备文件访问串口设备

  • open():打开设备文件(如串口设备文件 /dev/ttyS0)。
  • write():将数据写入设备文件,设备驱动程序会将数据发送到硬件。
  • close():关闭设备文件。
  • 通过设备文件,用户空间程序可以与内核中的硬件设备进行通信。该例子展示了如何通过打开、写入和关闭设备文件来与串口设备进行交互。

    5.22 进程、线程及之间区别

    进程(Process)

    • 定义:进程是操作系统资源分配的基本单位,表示一个正在运行的程序。每个进程都有自己的地址空间、数据、程序计数器和系统资源。
    • 资源:每个进程拥有独立的地址空间和系统资源(如内存、文件描述符等)。进程之间相互独立,不共享资源。
    • 功能:进程是程序的实体,负责管理程序的运行,包含代码、数据以及程序的执行状态。
    • 创建与销毁:进程的创建和销毁需要较大的开销,因为操作系统需要分配和回收大量的资源。
    • 通信:进程之间不能直接共享数据,通常需要通过进程间通信(IPC)机制,如管道、消息队列、共享内存等进行数据交换。

    线程(Thread)

    • 定义:线程是进程中的实际执行单位,是操作系统调度的最小单位。一个进程可以有多个线程,这些线程共享进程的地址空间和资源。
    • 资源:线程共享同一进程的地址空间和资源(如内存、文件描述符),但每个线程有自己的栈空间、程序计数器和局部变量。
    • 功能:线程负责在进程中执行具体的任务。线程之间的协作比进程之间的协作更加高效。
    • 创建与销毁:线程的创建和销毁比进程轻便,开销较小,因为线程之间共享资源,操作系统只需要为每个线程分配最小的资源。
    • 通信:线程之间通信更加方便,因为它们共享同一进程的内存,可以直接访问共享内存或通过互斥锁等机制同步数据。

    进程与线程的主要区别

    进一步分析:

    1. 内存和资源

    • 进程:每个进程都有自己的内存空间和资源,这意味着一个进程崩溃时不会直接影响到其他进程。但是,进程之间的通信需要通过特定的机制(如消息队列、管道、共享内存等)。
    • 线程:线程共享同一个进程的内存和资源,这使得线程间的通信更加高效,但也带来了同步问题(如数据竞争、死锁等)。如果一个线程崩溃,可能导致整个进程崩溃。

    2. 性能

    • 进程:由于每个进程都有自己的地址空间和资源,进程间的切换开销较大。创建和销毁进程需要更多的系统资源。
    • 线程:线程之间共享资源,创建和销毁线程的开销较小。线程间切换比进程切换更快,因此在需要频繁调度的情况下,使用线程可以提高性能。

    3. 安全性和稳定性

    • 进程:进程相互独立,避免了一个进程的崩溃影响其他进程。操作系统可以为每个进程分配不同的资源和优先级。
    • 线程:线程共享进程的内存,因此它们之间的错误(如访问未初始化的内存)可能导致整个进程崩溃。因此,线程的管理和同步需要特别注意。

    总结

    • 进程是资源分配的基本单位,它有独立的地址空间和资源。每个进程相互独立,进程间通信相对较慢,但更加稳定。
    • 线程是执行单位,多个线程共享进程的资源,线程间通信更加高效。线程的创建和销毁较为轻量,但一个线程的崩溃可能影响整个进程的稳定性。

    5.23 进程的状态

    操作系统中的进程可以处于多种不同的状态,这些状态反映了进程在不同阶段的活动或等待。进程状态管理是操作系统中至关重要的部分,因为它决定了进程如何被调度和执行。以下是六种主要的进程状态:

    1. 就绪态(Ready)

    • 定义:就绪态是指进程已经准备好执行,只等待 CPU 调度。该进程已经分配了必要的资源,并且可以立即运行,只要操作系统为其分配 CPU 时间。
    • 特征:进程进入就绪态后,操作系统会将其放入就绪队列中,等待 CPU 分配时间。此时,进程已经准备好执行,但还没有被调度执行。
    • 典型操作:当一个进程的时间片用完后,它会从运行态转为就绪态,等待下次 CPU 调度。

    2. 运行态(Running)

    • 定义:运行态是指进程正在 CPU 上执行。进程从就绪态进入运行态后,会被操作系统调度到 CPU 上,并开始执行程序的指令。
    • 特征:在运行态下,进程会执行其代码,并使用 CPU 来进行计算和处理任务。运行中的进程是唯一可以执行的进程,除非它被抢占或执行完成。
    • 典型操作:一旦调度程序选择一个就绪态的进程并分配 CPU 时间片,进程就会进入运行态。

    3. 僵尸态(Zombie)

    • 定义:僵尸态进程是已经终止(退出)的进程,但是其父进程尚未调用 wait()waitpid() 来回收该进程的资源。此时,虽然进程已经完成执行,但它仍然保留在系统中,等待父进程清理。
    • 特征:在僵尸态下,进程的资源(如内存)已经释放,但进程的进程控制块(PCB)还没有被完全销毁。进程仅占用进程表中的一个条目,等待父进程清理。
    • 典型操作:一旦父进程调用 wait() 等待已终止子进程,僵尸进程将被完全清除。

    4. 可中断睡眠状态(浅度睡眠,Interruptible Sleep)

    • 定义:可中断睡眠状态表示进程正在等待某些事件或资源,但它仍然能够接收中断信号。如果有外部事件或信号发生,进程可以被唤醒并转为就绪态。
    • 特征:处于可中断睡眠的进程通常等待某些条件(如 I/O 操作完成)。如果收到信号(如 SIGINT),进程会被唤醒并进入就绪态。
    • 典型操作:一个进程发起 I/O 操作或等待某个条件时进入该状态,通常可以通过外部信号唤醒。

    5. 不可中断睡眠状态(不可中断等待,Uninterruptible Sleep)

    • 定义:不可中断睡眠状态表示进程正在等待某些资源(如 I/O 操作),并且在等待过程中不能被中断。进程必须等待所需资源或事件的完成,不能响应信号(如中断或终止信号)。
    • 特征:进程在此状态下无法被信号中断,通常用于对外部硬件或资源的等待,直到相应的资源准备好。此状态称为深度睡眠。
    • 典型操作:例如,进程等待硬盘 I/O 完成时,通常处于不可中断睡眠状态。

    6. 暂停态(Stopped)

    • 定义:暂停态表示进程被暂停,通常是由于接收到特定的信号(如 SIGSTOP 或 SIGTSTP)。在暂停态下,进程暂停执行,但它并没有完全结束,仍然存在于系统中,等待恢复。
    • 特征:进程处于暂停态时,它不再消耗 CPU 时间,但可以被操作系统恢复。恢复后,进程会转为就绪态,等待下次调度执行。
    • 典型操作:通过发送 SIGSTOP 信号暂停进程,通过 SIGCONT 信号恢复进程执行。

    总结

    状态转换的过程

    1. 从就绪态到运行态:当 CPU 调度器选择一个进程并分配 CPU 时间片时,进程从就绪态转入运行态。
    2. 从运行态到睡眠态:如果进程在运行过程中需要等待某些资源(如 I/O 完成),它会进入睡眠态。如果是可中断睡眠,可以被信号唤醒;如果是不可中断睡眠,需要等待外部条件。
    3. 从睡眠态到就绪态:当等待的条件满足时,进程会从睡眠态转回就绪态,等待 CPU 调度。
    4. 从运行态到僵尸态:进程执行完毕,但其父进程尚未回收其资源,进程变为僵尸态。
    5. 从暂停态到就绪态:当进程收到恢复信号(如 SIGCONT)时,它会从暂停态恢复,进入就绪态。

    5.24 进程/线程选用的时机

    在操作系统设计中,选择进程还是线程取决于应用程序的需求,特别是在资源管理、任务隔离、并发性和实时性等方面。进程和线程都有其独特的优势和使用场景。以下是使用进程使用线程的具体情况分析。

    使用进程的情况:

    1. 需要独立的地址空间和系统资源

    • 应用场景:当任务之间需要完全独立的环境,且需要较强的数据隔离时,应选择使用进程。每个进程有自己的内存空间和资源,不会直接影响其他进程。
    • 例子:运行多个独立的应用程序或服务,如浏览器和数据库服务器,它们需要独立的内存和文件资源。

    2. 需要更高的安全性和稳定性

    • 应用场景:如果一个任务的崩溃不应该影响其他任务的正常运行,使用进程可以提高系统的稳定性。进程是独立的,进程崩溃时不会直接影响其他进程。
    • 例子:在操作系统中,系统进程和用户进程应该分开,避免系统崩溃导致所有用户程序的崩溃。浏览器和操作系统的核心进程应该隔离,防止恶意网页或程序影响操作系统的稳定性。

    3. 并行计算需求

    • 应用场景:在多核处理器的情况下,进程可以充分利用多核的计算能力进行并行计算。每个进程可以在不同的 CPU 核心上独立执行,达到更高的计算效率。
    • 例子:大规模的科学计算或数据处理任务,例如分布式数据库和视频编码任务。

    使用线程的情况:

    1. 共享数据和资源

    • 应用场景:如果多个任务需要频繁共享数据和资源,并且需要较高效的通信,使用线程是更好的选择。线程之间可以直接访问同一个进程的地址空间,因此共享数据和资源变得更方便。
    • 例子:在 Web 服务器中处理多个请求,多个线程可以共享数据库连接池,减少资源的占用和数据传输的开销。

    2. 轻量级任务

    • 应用场景:当任务较轻且需要频繁切换时,线程比进程更加轻量级。线程切换的开销远小于进程切换,因此当任务相对简单且需要快速调度时,线程更合适。
    • 例子:一个图形界面程序中的按钮点击事件处理,每个事件可以通过一个线程来处理,线程切换快速且开销小。

    3. 实时性要求

    • 应用场景:如果任务对实时性有较高的要求,线程能够快速响应并处理任务。线程在同一进程内共享资源,因此线程之间的调度和通信速度较快,适合实时任务的处理。
    • 例子:音视频处理、游戏开发等需要快速响应用户输入和数据处理的场景。多个线程可以在后台处理实时数据流,同时保持界面的响应性。

    进程与线程的对比

    总结

    • 使用进程:当需要隔离任务、提高系统稳定性或进行计算密集型任务时,使用进程。进程是操作系统中资源分配的基本单位。
    • 使用线程:当任务之间需要共享数据、高效通信并且任务轻量时,使用线程。线程之间的创建和销毁较为轻便,适合处理实时任务和频繁切换的任务。

    5.25 多进程、多线程的优缺点

    多进程的优点:

    1. 独立性

    • 每个进程有独立的内存空间和资源。当一个进程发生崩溃时,它不会影响到其他进程的执行。因此,进程之间相互独立,可以有效地避免一个进程的错误影响整个系统的稳定性。
    • 例子:如果浏览器进程崩溃,它只会影响当前打开的标签页,而其他标签页的浏览器进程不受影响。

    2. 安全性

    • 进程之间的内存是隔离的,进程无法直接访问或修改其他进程的内存空间。这种内存隔离为进程之间提供了较高的安全性,尤其是在处理敏感数据时。

    剩余60%内容,订阅专栏后可继续查看/也可单篇购买

    作者简介:仅用几个月时间0基础天坑急转嵌入式开发,逆袭成功拿下华为、vivo、小米等15个offer,面试经验100+,收藏20+面经,分享求职历程与学习心得。 专栏内容:这是一份覆盖嵌入式求职过程中99%问题指南,详细讲解了嵌入式开发的学习路径、项目经验分享、简历优化技巧、面试心得及实习经验,从技术面,HR面,AI面,主管面,谈薪一站式服务,助你突破技术瓶颈、打破信息差,争取更多大厂offer。

    全部评论
    已老实
    点赞 回复 分享
    发布于 02-27 13:43 浙江
    已老实
    点赞 回复 分享
    发布于 03-14 16:29 重庆
    已老实
    点赞 回复 分享
    发布于 03-19 17:00 辽宁

    相关推荐

    03-09 12:51
    已编辑
    门头沟学院 Java
    点赞 评论 收藏
    分享
    评论
    7
    8
    分享

    创作者周榜

    更多
    正在热议
    更多
    # 腾讯音乐求职进展汇总 #
    67483次浏览 364人参与
    # 机械人的薪资开到多少,才适合去? #
    91610次浏览 396人参与
    # 招行数字金融训练营 #
    53841次浏览 251人参与
    # 携程求职进展汇总 #
    218061次浏览 1893人参与
    # 投递几十家公司,到现在0offer,大家都一样吗 #
    181835次浏览 1314人参与
    # 面试之前应该如何准备? #
    9167次浏览 307人参与
    # 腾讯云智研发2025实习生招聘 #
    34002次浏览 355人参与
    # 如何看待应届生身份? #
    13914次浏览 252人参与
    # 通信和硬件还有转码的必要吗 #
    48117次浏览 494人参与
    # 双非本科的出路是什么? #
    111302次浏览 1083人参与
    # 0offer互助地 #
    303417次浏览 2530人参与
    # 你遇到过哪些神仙同事 #
    55783次浏览 552人参与
    # 总结:offer选择,我是怎么选的 #
    102126次浏览 740人参与
    # 选了这个offer,你有没有后悔? #
    499772次浏览 3606人参与
    # 腾讯云智研发工作体验 #
    15533次浏览 121人参与
    # 工作中,努力重要还是选择重要? #
    89049次浏览 1218人参与
    # 招银网络求职进展汇总 #
    95648次浏览 608人参与
    # lastday知无不言 #
    42856次浏览 404人参与
    # 学历or实习经历,哪个更重要 #
    81041次浏览 625人参与
    # 第一份工作应该选高薪还是热爱? #
    38746次浏览 347人参与
    # 今年秋招哪家公司给的薪资最良心? #
    188987次浏览 1109人参与
    # 毕业后不工作的日子里我在做什么 #
    150349次浏览 1313人参与
    牛客网
    牛客企业服务