刚读完第一章,再略看一遍顺便记一下

第一章 简介和概述

内核的任务

  • 内核是应用程序所知道的层次结构中的最底层,时一台增强的计算机
  • 当若干程序在同一系统中并发运行时,可以将内核视为资源管理程序
  • 内核提供系统调用用于向计算机发送请求

实现策略

  • 微内核

    • 只有最基本的功能直接由中央内核实现,其他所有的功能都委托给一些独立进程,这些进程通过明确定义的通信接口与中心内核通信
  • 宏内核

    • 它是构建系统内核的传统方法,即将内核的全部功能打包到一个文件中

内核的组成部分

进程、进程切换、调度

传统上,UNIX操作系统下运行的应用程序、服务器以及其他程序都称为进程

各进程空间完全独立,进程之间并不会意识到彼此的存在

Linux是多任务系统,它支持(看上去)并发执行的若干进程。系统中真正在同时运行的进程数最多不超过CPU的数量

UNIX进程

linux对进程采用了一种层次结构,每个进程都依赖于一个父进程

内核启动init程序作为第一个进程,它负责进一步的系统初始化操作

因此init是进程树的根

pstree程序可以输出进程树

UNIX有两种创建新进程的机制:

  • fork
    • 创建当前进程的一个副本,父进程与子进程只有PID不同。父进程的内存的内容被复制给子进程。为了使fork更高效,linux使用了写时复制
  • exec
    • 将一个新程序加载到当前进程的内存中并执行。旧的内存页将被刷出,其内容将被替换成新数据。然后开始执行新程序(那么getshell应该都是用这种方式开启shell的)

线程

线程,有时又被称为轻量级进程。它与进程共享同样的地址空间

linux采用clone的方法创建线程。它的工作方式类似于fork,但是会进行更加精确的检查,以确定哪些资源是共享,哪些资源是线程独享的。在一定程度上,线程和进程是可以连续转换的

命名空间

每个命名空间可以包含一个特定的PID集合,或可以提供文件系统不同的视图,在某个命名空间中挂载的卷不会传播到其他命名空间内

我的理解就是,不同命名空间就如同科幻片中不同的地球一样,虽然都是地球,但彼此是分离的

docker就使用了这一技术

地址空间与特权级别

linux将虚拟地址划分为两个部分,分别是内核空间和用户空间:

内核空间 TASK_SIZE - $2^{32}$ or $2^{64}$
用户空间 0 - TASK_SIZE

TASK_SIZE是一个特定于计算机体系结构的常数,不同架构的系统有不同的划分

特权级别

linux只有两个不同的状态:核心态和用户态

在用户态禁止访问核心态地址空间,从用户态转到核心态的切换通过系统调用的方式来完成,且系统调用的执行因具体系统而不同

除了代表用户程序执行代码之外,内核还可以由异步硬件中断激活,然后在中断上下文运行

除了普通进程,系统中还有内核线程在运行。内核线程不予任何特定的用户空间进程相关联,因此无权处理用户空间

虚拟和物理地址空间

用页表来为物理内存分配虚拟地址。物理内存页常被称为页帧

页表

用来将虚拟地址空间映射到物理地址空间的数据结构称为页表,linux下用四级页表来管理映射关系

系统调用

系统调用是用户进程与内核交互的经典方法。传统的系统调用按不同类别分组:

  • 进程管理:创建新进程,查询信息,调试
  • 信号:发送信号,定时器以及相关处理机制
  • 文件:创建、打开和关闭文件,从文件读取和向文件写入,查询信息和状态
  • 目录和文件系统:创建、删除和重命名目录,查询信息,链接,变更目录
  • 保护机制:读取和变更UID/GID,命名空间的处理
  • 定时器函数:定时器函数和统计信息

所有这些函数都对内核提出了要求。这些函数不能以普通用户库的方式实现,因为需要特别的保护机制来保证系统稳定性或安全不受危及

设备驱动程序、块设备和字符设备

对外设的访问可以利用/dev目录下的设备文件来完成,程序对设备的处理类似于常规文件

外设可分为两类:

  • 字符设备:提供连续的数据流,应用程序可以顺序读取,通常不支持随机存取。此类设备支持按字节/字符来读写数据
  • 块设备:应用程序可以随机访问设备数据,程序可以自行确定读取数据的位置。但是,数据的读写只能以块(通常是512B)的倍数进行。其不支持基于字符的寻址

总结

许多东西上课都学过,权当复习