四.I/O进程

  • 标准IO和文件IO区别

标准 I/O 和文件 I/O 是编程里用于输入输出操作的两种方式,它们的区别如下:

  1. 缓冲机制
    • 标准 I/O:缓冲机制,它会先把数据存于缓冲区,等缓冲区满或者满足特定条件时再进行实际的 I/O 操作,这能减少系统调用次数,提高效率。
    • 文件 I/O:缓冲机制,数据直接进行读写操作,每次操作都会引发系统调用。
  2. 接口类型
    • 标准 I/O:提供了更高级的函数接口,像 fopen、fread、fwrite、fclose 等,使用起来较为简便,还支持格式化输入输出
    • 文件 I/O:提供了低级系统调用接口,如 open、read、write、close 等,对文件操作的控制更精细
  3. 可移植性
    • 标准 I/O:具有良好的可移植性,在不同操作系统上都能保持一致的行为。
    • 文件 I/O:不同操作系统的文件 I/O 接口存在差异,可移植性相对较差
  4. 适用场景
    • 标准 I/O:适合处理文本文件和格式化数据,能提高开发效率。
    • 文件 I/O:适合对性能要求高、需要精细控制文件操作的场景,如底层文件系统操作。

  • 简述流指针?

定义

  • 流指针类型为 FILE *,指向 FILE 结构体对象,该对象包含文件操作所需信息。

补充

  • 在 C 语言里,FILE(英文:文档,文件的意思)是一种结构体类型,用来表示文件流,涵盖了文件操作所需的各类信息,像文件状态、缓冲区等。FILE *则是指向FILE结构体对象的指针类型
  • 借助这个指针,就能对文件进行打开、读取、写入和关闭等操作
  • 例如FILE *fp = fopen("test.txt", "r");,这里的fp就是FILE *类型指针,它指向打开的文件对应的FILE结构体对象。

作用

  • 标识文件:程序通过流指针识别并操作特定文件。
  • 跟踪位置:记录文件读写位置,保证顺序读写。
  • 管理缓冲:关联文件缓冲区,提升 I/O 效率。

使用

  • 打开:fopen 返回流指针。
  • 读写:读写函数以流指针为参数。
  • 关闭:fclose 传入流指针。

注意

  • 检查:fopen 后检查是否为 NULL。
  • 释放:使用完用 fclose 释放资源。
  • 有效:文件关闭后流指针失效。

  • 简述系统调用?

定义

  • 系统调用是用户程序与操作系统内核交互的接口,是操作系统提供给用户程序调用的特殊接口集合

作用

  • 资源管理:帮助用户程序请求操作系统分配和管理 CPU、内存、文件等资源。
  • 安全保障:隔离用户程序和内核,防止用户程序直接访问敏感资源,保障系统安全稳定。
  • 功能实现:让用户程序借助操作系统实现底层功能,如创建进程、读写文件。

调用过程(类比:下矿洞)

  • 陷入内核:用户程序执行特殊指令(如 int 指令)进入内核态。
  • 参数传递:通过寄存器或栈传递系统调用号和参数。
  • 内核处理:内核根据系统调用号执行相应服务。
  • 返回结果:处理完成后返回结果,程序回到用户态。

常见类型

  • 进程控制:创建、终止进程等。
  • 文件操作:打开、读写、关闭文件等。
  • 设备管理:请求、释放设备等。
  • 信息维护:获取系统时间等。

  • 简述静态库和动态库的区别?

链接时间

  • 静态库:在编译时链接,相关代码被完整复制到可执行文件中。
  • 动态库:在运行时链接,可执行文件仅存储库的引用信息

可执行文件大小

  • 静态库:使可执行文件体积增大,因为包含了库的全部代码。
  • 动态库:可执行文件较小,多个程序可共享一份库代码。

更新维护

  • 静态库:库更新时需重新编译整个程序。
  • 动态库:只需更新库文件,程序下次运行自动使用新库。

运行性能

  • 静态库:无额外的加载开销,运行速度可能稍
  • 动态库:加载时会有一定性能开销,但多个程序可共享内存,减少内存占用

依赖关系

  • 静态库:可执行文件不依赖外部库文件,可独立运行
  • 动态库:依赖对应的动态库文件,若缺失无法正常运行

  • 如何将程序执行直接运行与后台?

以下是 Windows :

直接运行

  • 方式:双击.exe 文件或在命令行输入程序路径和名称启动。
  • 特点:程序在前台运行,占据当前窗口,用户可直接交互,需等待程序执行完毕才能进行其他操作。

后台运行

  • 任务计划程序:打开 “任务计划程序” 创建基本任务,设置名称、触发器、操作等,选择要运行的程序。
  • 注册为服务:使用 instsrv.exe 和 srvany.exe 工具,将程序注册为 Windows 服务,并通过注册表配置参数。
  • 设置应用后台权限:在 “设置”>“应用” 中找到对应应用,在 “高级选项” 中设置 “允许此应用在后台运行”。

以下是Linux :

直接运行

  • 操作:在终端输入程序名或脚本名回车,如 ./test.sh。
  • 特点:独占终端,运行时无法在该终端操作,直至结束。

后台运行

  • 启动时放后台
    • 操作:命令后加 &,如 ./test.sh &。
    • 特点:启动后后台执行,返回进程 ID,可继续用终端。
  • 运行中移后台
    • 操作:Ctrl + Z 暂停,再输入 bg。
    • 特点:适用于已前台运行的程序。
  • 管理后台程序
    • 查看:用 jobs 命令。
    • 切回前台:fg %n(n 为任务编号)。
    • 终止:kill 加进程 ID。

  • 进程的状态

三态模型

  • 运行态:进程正在 CPU 上执行指令。
  • 就绪态:进程已获取除 CPU 外所有必要资源,等待系统分配 CPU 以运行。
  • 阻塞态:进程因等待某事件(如 I/O 完成)而暂停执行,放弃 CPU。

五态模型(在三态基础上增加)

  • 新建态:进程刚被创建,尚未进入就绪队列。
  • 终止态:进程执行完毕或因错误终止,系统正回收资源。

其他特殊状态

  • 挂起就绪态:就绪进程被换出内存至外存,待重新调入内存后可参与调度。
  • 挂起阻塞态:阻塞进程被换出内存至外存,等待事件发生且被调回内存。

  • 什么是僵尸进程?

以下是关于僵尸进程的简洁介绍:

  • 定义:进程止后,进程回收其资源,处于这种状态的子进程就是僵尸进程。
  • 产生:进程结束并向父进程结束信号,进程未用 wait() 或 waitpid() 来获取退出状态与释放资源,致使进程僵尸进程。
  • 影响:占用系统的进程资源,如进程控制块,大量出现会耗尽资源,影响新进程创
  • 识别:用 ps -ef 命令查看,僵尸进程状态显示为 Z或 Z+
  • 处理:进程正时,让父进程调用 wait() 或 waitpid() 回收资源;进程有()问题则进程,让 init 进程接管回收僵尸进程资源

  • 简述创建子进程中的写时拷贝技术?

定义

写时拷贝(Copy - On - Write,COW)是一种延迟拷贝技术,在创建进程时立即进程的内存空间,父子进程共享物理内存页。

工作机制

  • 创建子进程:fork () 创建子进程后,父子进程的虚拟地址空间指向相同的物理内存页。
  • 只读访问父子进程对共享内存只读访问时,不复制物理内存页,节省内存和时间。
  • 写入操作:当父子进程任一方尝试写入内存时,操作系统为方复制一份物理内存,使写入操作只影响复制后的内存页。

优点

  • 高效内存使用:减少内存占用,尤其在创建大量子进程或处理大内存空间时。
  • 快速创建进程:避免不必要的内存复制,加快子进程创建速度。

应用场景

  • Unix/Linux 系统:广泛用于 fork () 系统调用创建子进程。
  • 数据库系统:在创建事务处理子进程时应用,提高性能。

  • 多线程较多进程的优势?

资源占用

  • 多线程共享进程源,如内存、文件句柄,切换开销;多进程有独立地址空间,切换开销大

通信同步

  • 多线程可访问共享变量,通信简单;多进程需用 IPC 机制,通信复杂

创建销毁

  • 多线程建和毁速度、开销;多进程建和

并发响应

  • 多线程细粒度并发,某线程阻塞不影响整体响应;多进程中一个进程阻塞可能影响整体

程序设计

  • 多线程设计模型贴合思维,适合紧密相关任务并发,结构清晰、易维护

  • 线程池的使用

概念

线程池是管理一组预创建线程的资源池,可避免频繁创建和毁线程的开销

使用步骤

  1. 创建线程池:设定线程数量上限、任务队列大小等参数。
  2. 提交任务:将任务提交到线程池的任务队列。
  3. 线程执行:空闲线程从队列取任务执行。
  4. 任务管理:可对任务排队、等待或拒绝。
  5. 关闭线程池:不再需要时,有序关闭。

优点

  • 提高性能:减少线程创建销毁开销。
  • 资源控制:限制线程数量,避免资源耗尽。
  • 管理方便:统一管理线程生命周期。

适用场景

  • 高并发任务:如 Web 服务器处理请求。
  • 任务执行频繁:需快速响应的场景。

  • 线程池的组成部分

线程管理器

  • 负责线程池的创建、销毁、启动和停止等管理操作。

工作线程

  • 线程池中的线程,从任务队列中获取任务并执行。

任务队列

  • 存储待执行的任务,工作线程从这里获取任务。

任务接口

  • 规定任务的基本形式,提交到线程池的任务需实现该接口。

类比       

        线程管理器如同公司的管理层,负责组建、解散、启动和暂停公司运营;

        工作线程就像员工,从任务清单里领取任务并执行;

        任务队列类似任务清单,存放着待完成的工作;

        任务接口则是工作的标准规范,所有提交给公司的任务都得按此标准来。

  • 线程的同步互斥机制?

同步机制

  • 信号量:计数器,值于 0 时线程可访问资源,于等于 0 时需等待,用于控制多个资源的访问。
  • 条件变量:与互斥锁配合,线程等待特定条件满足,条件满足时被唤醒

互斥机制

  • 互斥锁:同一时间只允许一个线程访问共享资源,线程访问前加锁,访问完解锁。
  • 读写锁:允许多个线程同时读共享资源,但写时独占,提高读操作并发性能。

  • 简述互斥锁的实现原理?

  • 原子操作:
    • 利用硬件指令或特殊 CPU 指令,如测试并设置、比较并交换等,确保锁状态更新的原子性,保证同一时刻只有一个线程能获取锁。
  • 线程阻塞与唤醒:
    • 获取不到锁的线程被设置为阻塞状态放入等待队列,持有锁的线程释放锁时,操作系统按调度策略从等待队列中唤醒一个线程,使其有机会获取锁。

  • 简述死锁的情景?

  • 资源竞争死锁:多个线程争夺资源,资源分配顺序不当,如线程 A 持资源 1 等资源 2,线程 B 持资源 2 等资源 1。
  • 环路等待死锁:线程间形成资源请求环路,如线程 A 等线程 B,线程 B 等线程 C…… 线程 N 等线程 A。
  • 信号量误用死锁:信号量 P、V 操作顺序或次数错误,如线程多次 P 操作但少 V 操作致资源无法正常释放。

  • 简述信号量的原理?

  • 定义:信号量是一个整数计数器,用于控制对共享资源的访问。
  • 操作
    • P 操作:信号量值减 1,若结果小于 0,线程阻塞等待。
    • V 操作:信号量值加 1,若有等待线程,唤醒一个。
  • 原理核心:通过 P、V 操作改变信号量值,控制线程对资源的访问权,实现同步与互斥。
  • 类型
    • 二值信号量:值为 0 或 1,用于互斥。(租单车)
    • 计数信号量:值大于 1,用于控制多个资源的并发访问。(电影院)

  • 简述进程的通信机制?

管道

  • 匿名管道:父子进程间单向通信,数据先进先出
  • 命名管道:不相关进程也能通信,有路径名。

消息队列

  • 消息按类型存取,克服管道无格式字节流限制

共享内存

  • 多个进程共享同一块物理内存,速度快但需同步。

信号量

  • 用于进程同步与互斥,保证共享资源的互斥访问。

信号

  • 用于通知进程发生了异步事件,如终止信号

套接字

  • 可实现不同主机进程间通信,常用于网络通信

  • 管道的通信原理?

  • 基本概念:管道是用于进程通信的一种机制,本质是内核中的缓冲区
  • 单向传输:数据只能单向流动,一个进程写,另一个进程读。
  • 匿名管道:
    • 父子进程通过 fork 共享进程端写数据,进程端读数据。
    • 内核自动管理缓冲区,写满时写进程阻塞,读空时读进程阻塞。
  • 命名管道:
    • 有路径名,不相关进程可通过路径名访问
    • 读写操作与匿名管道类似,遵循先进先出原则。

  • 用户进程对信号的响应方式?

  • 默认处理:系统对不同信号有处理方式,如终止进程、暂停进程等。
  • 忽略信号:进程可选择忽略特定信号,不做任何响应,但像 SIGKILL 和 SIGSTOP 不可忽略。
  • 自定义处理:进程通过 signal 或 sigaction 函数指定信号处理函数收到信号时执行该函数。

  • 共享内存通信原理?

  • 原理概述:让个进程访块物理内存区域实现通信
  • 分配内存:操作系统在物理内存开辟共享内存区,为进程建立映射关系。
  • 映射关联:各进程将共享内存映射到自己的虚拟地址空间,实现对同区域访问
  • 数据读写:进程直接读写映射的虚拟地址,数据同步到共享内存。
  • 同步控制:因可并发访问,需信号量、互斥锁等同步机制保证数据一致性

  •  
    Logo

    openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。

    更多推荐