Black Mamba

Faster, Higher, Stronger.

Linux Notes I

  • 内核

    • 进程调试: Linux 是抢占式多任务操作系统. 多个进程可同时驻留于内存, 每个进程都能获得对 CPU 的使用; 每个进程能使用多长时间, 由内核进程调度程序决定
    • 内存管理: 物理内存 RAM 属于有限资源, 内存必须公平, 高效地在进程间共享这一资源. Linux 采用了虚拟内存管理机制, 具有以下两方面的优势:
    • 进程与进程之间、进程与内核彼此隔离, 一个进程无法读取或修改内核或其他进程的内存内容
    • 只需将进程的一部分保持在内存, 不但降低了每个进程对内存的需求量, 而且还能在 RAM 中同时加载更多的进程
    • 文件系统: 内核在磁盘上有文件系统, 允许对文件执行创建, 获取, 更新和删除等操作
    • 创建和终止进程: 内核可以将新程序载入内存, 为其提供运行所需的资源, 一个运行中的程序称之为”进程”, 一旦进程执行完毕, 内核要确保释放其占用的资源, 供后续重新使用
    • 联网: 内核以用户进程的名义收发网络消息 (数据包). 该任务包括将网络数据包路由至目标系统
  • 内核态(核心态, 监管态)和用户态

    • 在用户态下运行时, CPU 只能访问用户空间内存, 试图访问属于内核空间的内存会引发异常
    • 运行于核心态时, CPU 既能访问用户空间内存, 也能访问内核空间内存
    • 仅当处理器在核心态运行时, 才能执行某些特定操作. 这样的例子包括:
    • 执行停机(halt)指令去关闭系统,
    • 访问内存管理硬件
    • 以及设备 I/O 操作的初始化
    • 实现者们利用这一硬件设计, 将操作系统置于内核空间. 确保了用户进程不能访问内核指令和数据结构, 也无法执行不利于系统运行的操作
    • 某进程可以请求内核创建另一个进程
  • Shell

    • 用于读取用户输入的命令, 并执行相应的程序以响应. 也叫 “命令解释器”
    • 术语登陆 Shell (login shell) 是指用户刚登陆系统时, 由系统创建, 用以运行 Shell 的进程
    • Shell 只是一个用户进程. 登入同一台计算机的不同用户同时可使用不同的 Shell
  • 文件 I/O 模型

    • UNIX 系统 I/O 模型最显著的特性之一是其 I/O 通用性的概念. 同一套系统调用(open(), read(), write(), close()等) 所执行的 I/O 操作, 可施之于所有文件类型, 包括设备文件在内
    • 就本质而言, 内核只提供一种文件类型: 字节流序列, 在处理磁盘文件时, 可通过 lseek() 系统调用来随机访问
  • 命令行参数

    • 程序的 main() 函数需要做如下声明: int main (int argc, char* argv[]);
    • argc: 命令行参数的总个数
    • argv: 指针数组的成员指针则逐一指向每个命令行参数字符串. 首个字符串 argv[0], 标识程序名本身
  • 进程

    • 正在执行的程序实例. 执行程序时, 内核会将程序代码载入虚拟内存, 为程序变量分配空间, 建立内核记账数据结构, 以记录与进程有关的各种信息
    • 在内核看来, 进程是一个个实体, 内核必须在它们之间共享各种计算机资源
    • 对于像内存这样的受限资源来说, 内核一开始会为进程分配一定数量的资源, 并在进程的生命周期内, 统筹该进程和整个系统对资源的需求, 对这一分配进行调整
    • 程序终止时,内核会释放所有此类资源,其他进程重新使用
    • 其他资源(如CPU、网络带宽等)都属于可再生资源,但必须在所有进程间平等共享
    • 逻辑上将一个进程划分为以下几部分(也称为段)
    • 文本: 程序的指令
    • 数据: 程序使用的静态变量
    • 堆: 程序可从该区域动态分配额外内存
    • 栈: 随函数调用、返回而增减的一片内存,用于为局部变量和函数调用链接信息分配存储空间
  • 创建进程和执行程序

    • 使用系统调用 fork() 来创建一个新进程. 调用 fork() 的进程被称为父进程, 新创建的进程则被称为子进程.
    • 内核通过对父进程的复制来创建子进程. 子进程从父进程处继承数据段, 栈段以及堆段的副本后, 可以修改这些内容, 不会影响父进程的 “原版” 内容
    • 子进程要么去执行与父进程共享代码段中的另一组不同函数, 或者, 更为常见的情况是使用系统调用 execve() 去加载并执行一个全新程序
    • execve() 会销毁现有的文件段、数据段、栈段和堆段,并根据新程序的代码, 创建新段来替换它们
  • 进程 ID 和父进程 ID

    • 每一个进程都有一个唯一的整数型进程标识符 PID. 此外, 每一个进程还具有一个父进程标识符(PPID)属性, 用以标识请求内核创建自己的进程
  • 终止进程

    • 使用 exit() 系统调用, 或相关的 exit() 库函数
    • 向进程传递信号, 将其 kill
    • 无论以任何方式退出, 进程都会生成 “终止状态”
  • init 进程

    • 系统引导时, 内核会创建一个名为 init 的特殊进程, 即”所有进程之父”, 该进程的相应程序文件为 /sbin/init
    • 系统的所有进程不是由 init (使用 fork())“亲自”创建, 就是由其后代进程创建. init进程的进程号总为1, 且总是以超级用户权限运行
    • 谁 (哪怕是超级用户) 都不能”杀死” init 进程, 只有关闭系统才能终止该进程
    • init 的主要任务是创建并监控系统运行所需的一系列进程
  • 进程间通信与同步机制

    • 信号 (signal), 用来表示事件的发生
    • 管道 (即shell中的 “|” 操作符) 和 FIFO, 用于在进程间传递数据
    • 套接字 (SOCKET), 供同一台主机或是联网的不同主机所运行的进程之间传递数据
    • 文件锁定, 为防止其他进程读取或更新文件内容, 允许某进程对文件的部分区域加以锁定
    • 消息队列, 用于在进程间交换消息(数据包)
    • 信号量 (semaphore), 用来同步进程动作
    • 共享内存, 允许两个及以上进程共享一块内存. 当某进程改变了共享内存的内容时, 其他所有进程会立即了解这一变化
  • 线程

    • 每个进程都可执行多个线程, 可将线程想象为共享同一虚拟内存及一干其他属性的进程
    • 每个线程都会执行相同的程序代码, 共享同一数据区域和堆 但是, 每个线程都拥有属于自己的栈, 用来装载本地变量和函数调用链接信息
    • 线程之间可通过共享的全局变量进行通信
    • 借助于线程 API 所提供的条件变量和互斥机制, 进程所属的线程之间得以相互通信同步行为, 尤其是在对共享变量的使用方面
    • 此外, 线程间也能彼此通信

Comments