计算机硬件需要搭配软件才能正常工作。如果广大写应用程序的程序员,直接去跟底层的硬件打交道,那么会非常痛苦。如果有那么一个系统,可以在底层的硬件跟应用软件之间搭起一座桥梁,那么编写应用程序的程序员只需要关心应用层面的细节。这个桥梁,就是操作系统。

操作系统的主要职责,就是合理、高效地管理计算机硬件,比如处理器、内存、硬盘、I/O等资源。

介于以上的概述,操作系统中,有如下的概念。

进程(Process)

进程,是操作系统中对正在运行的程序实例的一种抽象。为了更好地理解进程,需要清楚地知道。一段代码是如何在计算机中运行起来的。
以经典的Hello World为例。
当你用最心爱的编辑器,在文件hello.c中写入如下源代码

1
2
3
4
5
6
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("Hello World\n");
return 0;
}

保存之后,这份源代码就保存在于硬盘中。
上面的源代码,需要经过编译器编译为CPU可执行的二进制文件。

进程的生命周期

创建

  1. 系统初始化时
  2. 运行中的进行调用创建进程的system call
  3. 用户请求创建进程
  4. 初始化批处理任务

终止

  1. 正常exit
  2. 遇到error exit
  3. 遇到fatal error
  4. 被另一个进程kill

进程的状态

  1. Running(正在使用CPU)
  2. Ready(可以运行的,临时停下来给其它的进程执行)
  3. Blocked(不能接着执行,除非遇到额外的事件)

操作系统用一张叫process table的表来维护进程模型。
process table本质上是一个结构体数组,保存着进程状态切换时所需要的所有重要信息,比如,program counter, stack pointer,memory allocation, status of its open file,accounting and scheduling information

线程

进程中的进程,起了个名称叫线程。
除了共享进程的地址空间,其它的可以理解为迷你进程。
操作系统既然已经有了进程,为什么还要在进程里扩充线程呢?

  • 针对一些需要同时进行多个活动的场景,比如word编辑,一边编辑一边定时自动保存,如果用多进程模型处理的话,由于不同进程间的地址空间隔离,多进程之前没办法协同合作
  • 线程比进程更轻量级,相比较进程,线程容易创建,销毁
  • 线程因为无进程的上下文切换,更高性能

线程的实用场景举例

  1. word编辑器
  2. web 服务器
  3. 大数据处理

传统的线程模型

进程两个独立的概念,资源成组和执行。有时,将组里的资源分隔开来又是很有用的,所以这个时候线程就派上用场了。
进程,将程序执行所需要的资源组在一起。线程,调用CPU。在进程中引入线程,是为了让一个进程可以并行执行多条命令。在一个进程中执行多个线程,就相当于在一台计算机中执行多个进程。一个进程中的线程可以共享资源,比如地址空间,文件描述符等。
把线程当成进程中的进程来理解,也有对应的状态转换。
值得注意的是,每一个单独的线程,有它自己的栈。
在多线程编程中,通常由一个单线程的进程,由其创建其它的线程。

1
2
3
4
thread_create   //创建一个线程
thread_exit //线程退出
thread_join //一个线程阻塞等待另一个线程结束
thread_yield //让出CPU,给其它的线程执行

线程实现

可以在用户态,也可以内核态实现

地址空间(Address Space)

文件(Files)

输入/输出(Input/Output)

保护(Protection)

Shell