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

C++/操作系统

知识点

C++基础和数据结构

共享内存是速度最快的IPC方式,因为进程可以直接读写内存,无需内核介入。

死锁 (Deadlock):
指两个或多个线程相互等待对方持有的资源,导致所有线程都无法继续执行的状态。产生死锁必须同时满足以下四个必要条件:
互斥:一个资源每次只能被一个线程使用。
请求与保持:一个线程因请求资源而阻塞时,对已获得的资源保持不放。
不剥夺:线程已获得的资源,在未使用完之前,不能被强行剥夺。
循环等待:若干线程之间形成一种头尾相接的循环等待资源关系。

操作系统和Linux应用

虚拟内存 (Virtual Memory):
  • 是什么:为每个进程提供一个统一的、连续的、独立的虚拟地址空间(如32位系统是4GB)。这个空间是对物理内存和磁盘空间的抽象。
  • 核心机制:通过内存管理单元(MMU) 和页表(Page Table) 将进程使用的虚拟地址映射到物理内存的实际地址(物理帧)或磁盘上的交换空间(Swap Space)。
  • 分页机制:虚拟内存和物理内存都被分割成固定大小的块。虚拟内存的块叫页(Page),物理内存的块叫页框(Page Frame)。当进程访问一个虚拟地址时,MMU通过查页表找到对应的物理页框。如果该页不在物理内存中,则触发一个缺页中断(Page Fault),由操作系统负责从磁盘将其调入内存。
进程内存布局:一个进程的虚拟地址空间通常被划分为以下几个经典区域:
  1. 代码段(Text Segment):存放程序的机器指令,只读。
  2. 数据段(Data Segment):存放已初始化的全局变量和静态变量。
  3. BSS段(BSS Segment):存放未初始化的全局变量和静态变量。该区域在程序开始执行前会被操作系统自动初始化为零。
  4. 堆(Heap):用于动态内存分配(如malloc/new)。空间从低地址向高地址增长。
  5. 栈(Stack):用于存放局部变量、函数参数、返回值地址等。空间从高地址向低地址增长。
  6. 内核空间:地址空间的顶部通常为内核保留,用于运行操作系统内核。
进程线程
基本定义系统中资源分配的基本单位。是程度执行的示例,拥有独立的资源和空间。CPU调度的基本单位。是进程内部的一个执行流,是进程内的一个实体。
创建/销毁创建慢、销毁慢,需要为其分配独立的空间。创建快、销毁快,共享进程空间,仅有少量需要单独分配。
资源分配拥有独立的系统资源,例如:内存地址、I/O设备、文件等。共享所属进程的全部资源,例如:全局变量、堆、打开的文件等。仅拥有少量独立资源:栈空间、寄存器状态、程序计数器等。
独立性独立性强。一个进程崩溃后一般不会影响到其余进程独立性弱。一个线程崩溃后往往会导致所属进程崩溃。
切换开销开销大、速度慢。需要切换内存地址空间、内存栈以及上下文,需要内核介入,容易导致CPU高速缓存(Cache)失效。开销小、速度快。不需要切换进程资源,仅需要切换少量线程资源,例如:栈、寄存器等。
通信机制复杂。需要程序间进程通信机制(IPC),例如:管道、记名管道、消息队列、信号量、共享内存、互斥量、条件变量等。简单。由于共享所属进程的全局变量和内存,因此可以直接读写。但是要配合互斥锁、信号量等同步机制,避免竞态条件
安全性高。进程间无法直接修改对方数据。低。同一进程下的线程共享全局变量及地址,容易误删除、误修改。
鲁棒性高。进程间相对独立。低。同一进程下的线程可以相互影响。
分布性适用于多机分布式。适用于多核多线程。
类比一间工程。拥有自己独立的土地(内存空间)、生成资料(数据、代码)、工人(线程),不同工厂间相对独立。工厂内的员工。共享工厂内资源,相互协同完成任务。
线程共享的内存资源
资源类型描述注意事项
代码段 (Text Segment)存储程序的可执行指令所有线程执行相同的代码
数据段 (Data Segment)存储已初始化的全局变量和静态变量需要同步机制保护
BSS段 (BSS Segment)存储未初始化的全局变量和静态变量需要同步机制保护
堆空间 (Heap)动态分配的内存区域 (malloc, new 等)需要同步机制保护
打开的文件描述符进程打开的文件、套接字等需要同步机制保护访问
线程的私有资源
资源类型描述注意事项
栈空间 (Stack)存储函数调用的局部变量、参数、返回地址等每个线程有独立栈,不可被其他线程直接访问
寄存器状态程序计数器(PC)、栈指针(SP)等CPU寄存器值线程切换时需要保存和恢复
线程局部存储 (TLS)使用 __threadthread_local 声明的变量每个线程有该变量的独立副本
线程ID操作系统或线程库分配给线程的唯一标识符用于区分不同线程
信号掩码线程对信号的阻塞设置每个线程可以独立设置信号处理
调度优先级线程的调度策略和优先级可独立于进程设置
错误状态变量errno (通常通过TLS实现)避免一个线程的错误状态影响其他线程
线程共享的内存资源
内存区域是否被线程共享说明
代码段 (Text Segment)存储程序的二进制指令。所有线程执行相同的代码(虽然可能在不同的执行点)。
数据段 (Data Segment)存储已初始化的全局变量和静态变量(如 static int a = 10;)。
BSS段 (BSS Segment)存储未初始化的全局变量和静态变量(如 int global_var;static int b;)。这是您问题中提到的部分,所有线程可以无障碍地读写这些变量。
堆空间 (Heap)通过 malloc, new 等动态分配的内存。所有线程都可以自由访问指向堆空间的指针。
线程的私有资源
资源是否私有说明
内核空间进程的内核空间。
栈空间 (Stack)每个线程都有自己独立的栈,用于存储函数调用时的局部变量、参数、返回地址等。一个线程无法直接访问另一个线程栈上的局部变量。
寄存器状态程序计数器(PC)、栈指针(SP)等寄存器值是完全私有的,这决定了每个线程的执行流。
线程局部存储 (TLS)一种特殊的机制(如C11的 _Thread_local 或 GCC的 __thread),允许定义全局或静态变量,但每个线程都拥有该变量的一个独立副本。

选择

C++/操作系统

关于线程同步与互斥,以下说法正确的是?( )
A. 互斥锁(mutex)的加锁和解锁操作必须由同一个线程执行。
B. 信号量(semaphore)的值可以大于1,因此可以允许多个线程同时进入临界区。
C. 条件变量(condition variable)内部自带了互斥功能,可以独立使用来保护共享资源。
D. 避免死锁的一种方法是规定所有线程都按相同的顺序申请多个锁。
答案:A, B, D
C:错误。这是常见误区。条件变量必须与互斥锁配合使用,它只负责等待和通知,互斥锁才负责保护检查条件和修改条件的代码。

以下关于malloc和new的区别,错误的是:
A. malloc是函数,new是运算符
B. malloc返回void*,new返回对应类型的指针
C. malloc不会调用构造函数,new会调用构造函数
D. malloc分配的内存可以用delete释放,new分配的内存可以用free释放
答案:D
解析:严禁混用!malloc分配的内存必须用free释放,new分配的内存必须用delete释放。

在嵌入式系统中,以下关于中断服务程序(ISR)的描述,正确的是:
A. ISR中可以使用大量的浮点运算
B. ISR中可以调用不可重入的函数
C. ISR应该尽可能短小高效
D. ISR中可以动态分配内存
答案:C
C:ISR应尽可能短小高效,以避免阻塞其他中断和任务。
A:浮点运算可能较慢且需要上下文保存。
B:不可重入函数可能导致数据竞争。
D:动态分配内存可能因为堆管理器的非重入性而导致问题。
这些都不是ISR中应该做的。

以下关于位段(Bit-field)的说法,正确的是:
A. 位段的存储顺序是标准规定的,可跨平台移植
B. 位段可以节省内存,但可能会增加代码大小和执行时间
C. 位段可以用于任何数据类型
D. 位段的地址可以被获取
答案:B
B:位段通过将多个变量打包到一个存储单元中来节省内存,但访问时需要额外的移位和掩码操作,因此可能增加代码大小和执行时间。
A:位段的存储顺序(位序)和字节序是实现定义的,不可移植。
C:位段通常用于整型家族(int, unsigned int等)。
D:不能对位段成员取地址。

以下关于嵌入式系统中栈和堆的说法,错误的是:
A. 栈的大小通常在编译时确定
B. 堆的大小通常在编译时确定
C. 栈溢出可能导致程序不可预测的行为
D. 堆溢出可能导致内存泄漏
答案:D
D:堆溢出通常指的是堆缓冲区溢出(如数组越界),这可能导致程序数据破坏或执行恶意代码,而内存泄漏是指分配的内存没有释放
A、B:栈和堆的大小通常在链接时确定(通过链接脚本),但堆的大小有时也可以在运行时调整(例如使用sbrk函数)。
C:栈溢出会导致覆盖其他内存区域,造成不可预测的行为。

以下关于static关键字用于全局变量和函数的说法,正确的是:
A. 限制该变量或函数只在当前文件内可见
B. 允许该变量或函数被其他文件访问
C. 表示该变量或函数是常量
D. 表示该变量或函数是易变的
答案:A
B:static用于全局变量或函数时,会改变其链接性,从外部链接变为内部链接,即限制其只在当前文件内可见。
C:常量关键字是const
D:易变关键字是volatile

以下关于realloc函数的说法,正确的是:
A. realloc只能用于扩大之前分配的内存块
B. realloc只能用于缩小之前分配的内存块
C. realloc可以用于扩大或缩小之前分配的内存块
D. realloc会初始化新分配的内存
答案:C
C、A、B:realloc可以调整已分配内存块的大小,可以扩大也可以缩小。
D:它不会初始化新分配的内存(除非是扩大时新扩展的部分,但标准并未规定其内容,通常是垃圾值)。

在C++中,以下关于智能指针的说法,错误的是:
A. std::unique_ptr独占所指向的对象
B. std::shared_ptr允许多个指针共享同一个对象
C. std::weak_ptr用于解决std::shared_ptr的循环引用问题
D. 智能指针可以用于管理通过malloc分配的内存
答案:D
解析:智能指针的默认删除器使用delete释放内存,因此如果使用malloc分配,则释放方式不匹配,会导致未定义行为。如果非要使用,需要自定义删除器。

在嵌入式系统中,以下哪些情况需要使用volatile关键字?( )
A. 多线程共享的变量
B. 被中断服务程序修改的全局变量
C. 内存映射的硬件寄存器
D. 循环中的计数器变量
答案:A、B、C
解析:循环中的计数器变量通常不需要volatile,因为它的修改是程序流程本身决定的。而A、B、C都需要防止编译器优化,确保每次访问都从内存读取。

以下关于static关键字的说法,正确的有?( )
A. 在函数内部,static变量只被初始化一次
B. 在文件作用域,static函数只能被本文件内的函数调用
C. 在C++类中,static成员函数不能访问类的非静态成员变量
D. 在C++类中,static成员变量需要在类外定义
答案:A、B、CD
解析:A、B、C、D都是正确的。注意D:C++中 static 成员变量在类内声明,但需要在类外定义(分配存储空间)。

以下哪些是动态内存分配的缺点?( )
A. 容易产生内存碎片
B. 分配和释放的时间不确定
C. 需要程序员手动管理,容易出错
D. 可能导致内存泄漏
答案:A、B、C、D
解析:动态内存分配在嵌入式系统中需要谨慎使用,就是因为这些缺点。

以下关于内存布局的说法,正确的有?( )
A. 栈的生长方向通常是从高地址向低地址
B. 堆的生长方向通常是从低地址向高地址
C. .bss段存放未初始化的全局变量和静态变量
D. .data段存放已初始化的全局变量和静态变量
答案:A、B、C、D
解析:这些都是典型的内存布局特征。

以下关于位段的说法,正确的有?( )
A. 位段不能取地址
B. 位段的宽度不能超过其类型的位数
C. 位段的内存布局(位序)是标准规定的,可移植
D. 位段可以用于节省内存
答案:A、B、D
解析:位段的内存布局(位序)是实现定义的,不可移植。
位段通过将多个变量打包到一个存储单元中来节省内存,但访问时需要额外的移位和掩码操作,因此可能增加代码大小和执行时间。

操作系统

以下哪些是操作系统引入虚拟内存机制的主要目的?( )
A. 使得程序可以使用比实际物理内存更大的地址空间。
B. 提高CPU的主频和运算速度。
C. 实现内存保护,防止一个进程误操作其他进程或内核的内存数据。
D. 消除内存碎片问题,提高内存利用率。
答案:A, C, D
A:正确。这是虚拟内存的核心优点之一,程序可以操作一个远大于物理内存的虚拟空间。
B:错误。虚拟内存机制需要MMU进行地址转换,理论上会增加地址转换的开销,可能降低效率,而不会直接提高CPU主频。
C:正确。每个进程有自己的页表,只能映射到自己被允许访问的物理页框。进程A的虚拟地址无法直接访问进程B或内核的物理内存,实现了隔离和保护。
D:正确。虚拟内存使用固定大小的页为单位进行映射,物理内存也被划分为页框。这有效地避免了外部碎片问题(虽然仍可能存在内部碎片)。

http://www.dtcms.com/a/392495.html

相关文章:

  • 动手学深度学习(pytorch版):第八章节—循环神经网络(4)循环神经网络
  • Jenkins与Arbess,CICD工具一文全面对比分析
  • 矩阵、线性代数
  • react常用的hooks
  • 重构的艺术:从‘屎山’恐惧到优雅掌控的理性之旅
  • 在c++中,怎么理解把析构函数设置为virtual呢?
  • CUDA性能优化 ---- 通过矢量化内存访问提高性能
  • 【序列晋升】39 Spring Data REST 的优雅实践,让数据交互更符合 REST 规范
  • 能当关系型数据库还能玩对象特性,能拆复杂查询还能自动管库存,PostgreSQL 凭什么这么香?
  • 【2025PolarCTF秋季个人赛】WEB方向wp
  • Go基础:Go语言函数和方法详解
  • Redis 遍历指定格式的所有key
  • 插入mathtype/latex公式在word中行间距变高了
  • 设计模式学习(四)代理模式、适配器模式
  • ​​[硬件电路-279]:DRV8818PWP功能概述、管脚定义
  • 【51单片机】【protues仿真】基于51单片机恒温箱系统
  • zk管理kafka有哪些不足
  • Java 大视界 -- Java 大数据机器学习模型在金融衍生品复杂风险建模与评估中的应用
  • 半导体制造中常见工艺之LPCVD
  • D01粉尘传感器详解(STM32)
  • 【小程序】微信小程序页面之间数据传递的五种方法
  • Taichi太极图形编程语言实践demo
  • [xboard]07-Makefile逐行分析1
  • 基于规则的专家系统对自然语言处理深层语义分析的影响与启示:历史演进、技术局限与未来融合路径
  • 鸿蒙分布式服务架构实战:从服务注册到远程调用的完整指南
  • PPT中设置和应用空白版式,和占位符干扰说再见
  • Elasticsearch 02
  • 283-基于Django的AppStore应用榜单数据可视化分析推荐系统
  • 星际漫游2025“∞无限”潮玩艺术周于顺德启幕,以东方符号重构潮流宇宙
  • Rust:重塑系统编程的未来,从安全到性能的技术革命