一.进程的概念
进程描述是一个程序执行过程。当程序执行后,执行过程开始,则进程产生;执行过程结束,则进程也 就结束。
下面是 windows 系统中,所有的进程,即正在执行的程序,一旦结束进程,就意味着程序结束
二.进程的特点
进程是一个独立的可调度的活动,由操作系统进行统一调度,相应的任务会被调度到 cpu 中进行执行。
进程一旦产生,则需要分配相关资源,同时进程是资源分配的最小单位。
三、进程与程序的区别
程序是静态的,它是保存在磁盘上的指令的有序集合,没有任何执行的概念
进程是一个动态的概念,它是程序执行的过程,包括了动态创建、调度和销毁的整个过程。
四、并发与并行
并行执行 : 表示多个任务能够同时执行,依赖于物理的支持,比如 cpu 是 8 核芯,则可以同时执行 8 个 任务。
并发执行 : 在同一时间段有多个任务在同时执行,由操作系统调度算法来实现,比较典型的就是时间片轮转。
五、Linux 进程管理
1. 在 Linux 系统中,管理进程使用树型管理方式。
2. 每个进程都需要与其它某一个进程建立父子关系,对应的进程叫做父进程。
3. Linux 系统会为每个进程分配id ,这个id作为当前进程的唯一标识,当进程结束,则会被回收。
4. 进程的id与父进程的id分别通过getpid()与getppid()来获取。
函数头文件
#include <sys/types.h>
#include <unistd.h>
函数原型
pid_t getpid(void);
pid_t getppid(void);
函数功能
获取当前进程id与父进程id
函数返回值
成功:getpid() 返回当前进程id,getppid()返回父进程id
Tips: pid_t其实是int类型。
获取当前进程的pid和ppid
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
printf("Hello World!\n");
printf("pid:%d,ppid=%d\n",getpid(),getppid());
return 0;
}
运行结果:
Hello World!
pid:2818,ppid=2489
六、进程的空间分配和堆栈大小
1、进程的空间分配
进程建立之后,系统则要为这个进程分配相应的空间,32位Linux系统中,会为每个进程分配 4G 的空间。
4G的进程空间主要分为两部分,高位1G是内核空间,低位3G是用户空间。
用户空间又具体分为如下区间:
- stack : 存放非静态的局部变量
- heap : 动态申请的内存.
- bss : 未初始化过的全局变量(包括初始化为0的,未初始化过的静态变量(包括初始化为0) .
- data : 初始化过并且值不为0的全局变量,初始化过的不为0静态变量 .
- rodata : 只读变量(字符串之类) .
- text : 程序文本段(包括函数,符号常量)
Tips: 1. 当用户进程需要通过内核获取资源时,会切换到内核态运行,此时当前进程会使用内核空间的资源 2. 用户需要切换到内核态运行时,主要是通过系统调用。
2、虚拟地址与物理地址
在程序执行过程中,操作系统会为进程分配4G的虚拟地址空间,因此可以通过下图进行理解
虚拟地址空间中的每个地址都是一个虚拟地址
- 虚拟地址 : 虚拟地址并不代表真实的内存空间,而是一个用于寻址的编号
- 物理地址 : 是指内存设备中真实存在的存储空间的编号
- 虚拟地址通过映射的方式建立与物理地址的关联,从而达到访问虚拟地址就可以访问到对应的物理地址
- 在 cpu 中有一个硬件 MMU(内存管理单元) ,负责虚拟地址与物理地址的映射管理以及虚拟地址访问
- 操作系统可以设置 MMU 中的映射内存段
在操作系统中使用虚拟地址空间主要是基于以下原因:
- 直接访问物理地址,会导致地址空间没有隔离,很容易导致数据被修改
- 通过虚拟地址空间可以实现每个进程空间都是独立的,操作系统会映射到不用的物理地址区间,在访问时互不干扰.
3、进程的堆栈大小
1>Linux下进程栈的默认大小是8M,可以通过 ulimit -s 查看
2>堆的大小理论上大概等于进程虚拟空间大小-内核虚拟内存大小,Linux下,进程的高位1G留给内核, 低位3G留给用户,所以进程堆大小小于3G。
3>最大进程数 在Linux下,通过 ulimit -u 查看系统的最大进程数。