返回
Featured image of post 操作系统 —— 进程

操作系统 —— 进程

进程

进程是操作系统中最核心的概念。

  • 定义:一个执行中的程序的实例。(对正在运行程序的一个抽象)
  • 是资源分配的基本单位。
  • 进程提供给应用程序的关键抽象:
    • 一个独立的逻辑控制流,它提供一个假象,好像程序独占地使用处理器。
    • 一个私有的地址空间,它提供一个假象,好像程序独占地使用存储器系统。
  • 逻辑流(逻辑控制流):程序计数器 PC 值的序列。
    • 异常处理程序、进程、信号处理程序、线程和 Java 进程都是逻辑流的例子。
  • 并发流(concurrent flow):一个逻辑流的执行在时间上与另一个流重叠。
  • 并发:多条流并发地执行的一般现象称为并发 (concurrecy)。
  • 多任务(multitasking):一个进程和其他进程轮流运行的概念称为多任务。
  • 时间片(time slice):一个进程执行它的控制流的一部分的每一时间段。
  • 并行流(parallel flow):两个流运行在不同的处理器上或者不同的计算机上。
  • 上下文(context):内核重新启动一个被抢占的进程所需要的状态。
  • 上下文切换:内核为每个进程维护一个上下文(context),多任务的实现依赖上下文切换。
    • 1)保存当前进程的上下文;
    • 2)恢复某个先前被抢占的进程被保存的上下文;
    • 3)将控制传递给这个新恢复的进程;

1.进程地址空间

1.1 典型进程地址空间 1

  • 代码段起始地址:
    • 32 位:0x08048000
    • 64 位:0x00400000
  • 进程从用户模式变为内核模式的方法是:中断、故障、陷入系统调用。

1.2 典型进程地址空间 2

2. 进程状态

2.1 状态转换图

2.2 基本状态

  • 1)运行态:进程实际占用 CPU;
  • 2)就绪态:可运行;
  • 3)阻塞态:除非某种外部事件发生 (使进程满足运行条件),否则进程不能运行。

2.3 引入的状态:

  • 创建状态;
  • 终止状态;
  • 挂起状态;(图中没有)

3. 进程控制

3.1 进程创建与终止

  • 导致进程创建的主要事件:
    • 1)系统初始化;
    • 2)正在运行的程序执行了创建进程的系统调用;
    • 3)用户请求创建一个新进程;
    • 4)一个批处理作业的初始化;
  • 导致进程终止的主要事件:
    • 1)正常退出(自愿的)
      • A.从 main 返回;
      • B.调用 exit;
      • C.调用_exit 或_Exit;
      • D.最后一个线程从其启动例程返回;
      • E.从最后一个线程调用 pthread_exit();
    • 2)出错退出(自愿的)
      • 调用 abort
    • 3)严重错误/被其他进程杀死(非自愿)
      • 接到终止信号;
      • 最后一个线程对取消 (cancellation) 请求做出响应;
  • 相关函数
#include <stdlib.h>
#include <unistd.h>

// 进程创建
pid_t fork(void);
// 进程退出
// 进行一些清理(关闭文件描述符之类的),然后返回内核
void exit(int status);
// 下面两个直接返回内核
void _Exit(int status);
void _exit(int status);
  • fork 失败的主要原因:
    • 系统中已经有太多进程。
    • 该实际用户 ID 的进程数超过了系统限制。

4. 守护进程

  • 守护进程:
    • 一种生存期长的进程。
    • 后台运行;
    • 没有控制终端;

4.1 编程规则

  • 1)调用 umask 将文件模式创建屏蔽字设置为一个已知的值(通常是 0);【疑问?!】
  • 2)调用 fork,然后使父进程 exit;
  • 3)调用 setsid 创建一个新会话;
    • a)进程成为新会话的首进程;
    • b)成为一个新进程组的组长进程;
    • c)没有控制终端;
  • 4)将当前工作目录更改为根目录;
  • 5)关闭不再需要的文件描述符;
  • 6)[选]打开/dev/null 使进程具有文件描述符 0/1/2。
    • 使所有读标准输入,写标准输出/错误输出的库例程都不会产生效果。

4.2 示例

4.3 守护进程的惯例

  • 锁文件放/var/run目录,命名为name.pid
  • 配置放/etc目录,命名为name.conf
  • 可用命令行启动。
    • 通常由/etc/rc*/etc/init.d/*启动。
    • 守护进程终止时,应当自动重启。(/etc/inittab中为守护进程添加respawn记录项【macOS 没有此文件!】)
  • 守护进程可通过 SIGHUP 信号,重新读取配置(当配置更新时)。

5. 进程实现

  • 进程表:操作系统维护的一张表格——一个结构数组。
  • 进程表项:也称进程控制块,是进程表的表项。
  • 典型系统中的一些关键字段:
进程管理 存储管理 文件管理
寄存器 正文段指针 根目录
程序计数器 数据段指针 工作目录
程序状态字 堆栈段指针 文件描述符
堆栈指针 用户 ID
进程状态 组 ID
优先级
调度参数
进程 ID
父进程
进程组
信号

A.拓展

A.1 进程组

  • 进程组:在类 UNIX 系统中,进程和它的所有子进程以及后裔进程共同组成一个进程组。
  • 进程组相关函数:
#include <unistd.h>

// 获取进程组ID
pid_t getpgrp(void);
// 改变自己或其他进程的进程组
// pid == 0: 使用当前进程
// pgid== 0: pid进程的PID作为进程组ID。
int setpgid(pid_t pid, pid_t pgid);
  • 僵死进程/僵尸进程:终止,但未被回收的进程。
    • 进程已经终止了,但内核仍保留它的某些状态直到父进程回收它为止。
  • 相关函数:
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>

pid_t waitpid(pid_t pid, int *status, int options);
pid_t wait(int *status);
unsigned int sleep(unsigned int secs);
int pause(void);

A.2 子进程回收方式

  • 回收子进程的方式:用 SIGCHLD 信号。子进程终止时,会发送 SIGCHLD 信号给其父进程。 【详见ex_SIGCHLD.c

A.3 C 程序的启动和终止

  • 内核使程序执行的唯一方法:exec!

A.4 进程资源限制

  • 见《Unix 环境高级编程》p175

A.5 7 个 exec 的关系

A.6 ps 命令中进程状态

  • R: TASK_RUNNING,可执行状态。
  • S: TASK_INTERRUPTIBLE,可中断的睡眠状态。
  • D: TASK_UNINTERRUPTIBLE,不可中断的睡眠状态。
  • T: TASK_STOPPED/TASK_TRACED,暂停状态或跟踪状态。
  • Z: TASK_DEAD – EXIT_ZOMBIE,退出状态,进程成为僵尸进程。
  • X: TASK_DEAD – EXIT_DEAD,退出状态,进程即将被销毁。

B.疑问/不懂

  • 孤儿进程组?
  • 文件模式创建屏蔽字是什么?有何作用?(umask() 设置的那个))

C.参考

相信美好的事情即将发生。
Built with Hugo
Theme Stack designed by Jimmy