并发程序与并行程序
并发程序是指可以被同时发起执行的程序
并行程序被设计成可以在并行的硬件上执行的并发程序。
并发程序代表了所有可以实现并发行为的程序,它是一个宽泛的概念,其中包含了并行程序。
inter-process communication(进程间通信)
- 基于通信的IPC方法:又分为以数据传送为手段的IPC方法(传送字节流的管道pipe和传送结构化的消息对象的消息队列message queue)和以共享内存(shared memory)为手段的最快的一种IPC方法
- 基于信号的IPC方法:即我们常说的操作系统的信号(signal)机制,它是唯一的一种异步IPC方法。
- 基于同步的IPC方法:最重要的就是信号量(semaphore)
go支持的IPC方法有管道、信号和socket.
进程:我们把一个程序的执行称为一个进程。(进程用于描述程序的执行过程)
进程是操作系统进行资源分配的一个基本单位。
进程使用fork(一个系统调用函数)可以创建若干个新的进程,前者称为后者的父进程,后者称为前者的子进程。每个子进程都是源自它的父进程的一个副本,它会获得父进程的数据段、堆和栈的副本,并与父进程共享代码段。
每一个副本都是独立的,子进程对属于它的副本的修改对其父进程和兄弟进程(同父进程)都是不可见的,反之亦然。全盘复制父进程的数据是一种相当低效的做法。linux系统内核使用写时复制(copy on write 简称COW)等技术来提高进程创建的效率。
通过go 标准库os可以查看当前进程的PID和PPID
pid := os.Getpid()
ppid := os.Getppid()
注:PID并不传达与进程有关的任何信息。它只是一个用了唯一标识进程的数字而已。
进程的属性信息只包含在内核中与PID对应的进程描述符里。
PPID体现了两个进程之间的亲缘关系。
进程的状态:
- 可运行状态(TASK_RUNNING,简称R)
- 可中断的睡眠状态(TASK_INTERRUPTIBLE,简称为S),当进程正在等待某个事件(如网络连接或者信号量)到来是,会进入此状态。
- 不可中断的睡眠状态(TASK_UNINTERRUPTIBLE,简称为D),此状态与可中断的睡眠状态唯一的区别就是它不可被打断。这意味着处于此中状态的进程不会对任何信号做出响应。发给此状态的进程的信号直到它从该状态转出才会被传递过去。处于此状态的进程通常是在等待一个特殊的事件,如等待同步的I/O操作完成。
- 暂停状态或者跟踪状态(TASK-STOPPED或者TASK_TRACED,简称为T),向进程发送SIGSTOP信号,就会使该进程转入暂停状态,除非该进程正处于不可中断的睡眠状态。向正处于暂停状态的进程发送SIGCONT信号,会使该进程转向可运行状态。
- 僵尸状态(TASK_DEAD-EXIT_ZOMBIE,简称为Z),处于此状态的进程即将结束运行,该进程占用的绝大多数资源也都已经被回收,不过还有一些信息未删除。如退出码以及一些系统信息。之所以保留这些信息,是考虑到该进程的父进程可能需要他们。由于此时的进程主体已经被删除而只剩下一个空壳,故此状态才称为僵尸状态。
- 退出状态(TASK_DEAD-EXIT_DEAD,简称为X)。在进程退出的过程中,有可能连退出码和统计信息都不需要保留。当一个进程消亡的时候,内核会给其父进程发送SIGCHLD信号以告知情况)。
内存区域:操作系统在内存上划分一个范围,如下
32位计算机中可有效标识2^32个内存单元
64位计算机中可有效标识2^64个内存单元
TASK_SIZE是两个空间的分界线,其值由所在计算机的体系结构决定,虚拟内存的最大容量与实际的物理内存大小无关,内核和CPU会负责维护虚拟内存与物理内存之间的映射关系。
内核会为每个用户进程分配的是虚拟内存而不是物理内存。每个用户进程的虚拟内存互不可见。
内核把进程的虚拟内存划分为若干页page, 而物理内存单元的划分由CPU负责,一个物理内存单元称为一个页框 page frame.