os 1- 内核、系统调用、进程和线程

ddatsh

dev #os

os很多思想、经典算法都可在日常开发各种工具或框架中找到它们的影子

学好OS提高思考深度及对技术理解力

内核

硬件与软件之间的一个中间层,将硬件资源抽象到一个更高的层次上,帮助上层应用高效地使用资源

当若干个程序并发地运行时,内核扮演着一个资源管理器的角色,将共享资源(CPU 时间,磁盘,网络等)分配到各个进程

Linux

单内核结构,同时吸收微内核的优点:模块化设计,支持动态装载内核模块

还避免了微内核设计上的缺陷,让一切都运行在内核态,直接调用函数,无需消息传递

系统调用

user、kernel mode

系统调用大致分类:


进程和线程

层级管理

两个系统调用配合,创建出一个新的进程

线程

程序会需要多个代码执行流,多个进程来处理这个又需要通信机制来交换数据

用线程来解决就不需要这部分通讯工作,所有线程共享该进程的数据和资源,只需同步机制对资源进行互斥的访问即可

Linux 通过 clone 方法创建线程,工作方式类似于 fork,确认哪些资源与父进程共享,哪些资源为线程独立创建

命名空间

使不同的进程可以看到不同的系统视图,以前的全局资源现在具有了不同的分组,如,每个命名空间内只能看到同组内的 PID 集合

进程状态

进程间通信方式

  1. 匿名管道(Pipes)

    有亲缘关系的父子或兄弟进程间通信

  2. 有名管道(Names Pipes) :

    可无亲缘关系通信,遵循 FIFO,以磁盘文件方式存在

  3. Signal

    通知接收进程某个事件已经发生

  4. 消息队列(Message Queuing)

    可随机查询,不一定要FIFO读取,可按消息类型读取。克服信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺陷

  5. Semaphores

    计数器,用于多进程对共享数据的访问,意图在于进程间同步,解决同步相关问题并避免竞争条件

  6. 共享内存(Shared memory)

    多个进程可访问同一块内存空间,及时看数据更新。要依同步操作,如互斥锁和信号量等。可以说这是最有用的进程间通信方式

  7. Sockets :

    可看做不同主机间的进程进行双向通信的端点

线程间同步的方式

  1. Mutex

    拥有互斥对象的线程才有访问公共资源的权限。因为互斥对象只有一个,所以可以保证公共资源不会被多个线程同时访问

    Java 中 synchronized 和各种 Lock 都是这种机制

  2. 信号量(Semphares)

    允许同一时刻多个线程访问同一资源,但需要控制同一时刻访问此资源的最大线程数量

  3. 事件(Event) :

    Wait/Notify:通过通知操作的方式来保持多线程同步,还可以方便的实现多线程优先级的比较操作

进程调度算法

地址空间和特权空间

内存通过指针寻址,CPU 字长决定了所能管理的内存地址空间最大尺寸,32 位系统4GB,64 位系统是 2^64 B

地址空间的最大长度和实际可用的物理内存大小无关,因此称之为虚拟地址空间

从进程的角度来看,地址空间中只有自身这一个进程,无法感知到其他进程的存在


Linux 将虚拟地址空间划分为两个部分,内核空间和用户空间

用完整的 64 位字长描述地址空间,所能描述的虚拟地址空间是巨大,用不了这么大的空间,一般用较短的位数来描述地址空间,比如 42 或者 47 位

CPU 提供了几种特权级别,进程可以驻留在某一特权级别。每个特权级别都有各种限制,例如对执行某些汇编语言指令或访问虚拟地址空间某一特定部分的限制