1. 程序
程序(program)是什么?
计算机程序(computer program)一般是指以某些程序设计语言编程,能够运行于某种目标体系结构上
程序 = 数据结构 + 算法
数据结构:用来表示人们思维对象的抽象概念的物理表现叫做数据(对问题中抽象出来的实体)
对数据的处理规则叫做指令
算法:解决问题完整而且准确的描述,是一系列解决问题的清晰的指令
计算机程序就是算法和数据的集合(算法操作数据)
一个程序的执行过程就是一次计算
程序是一个静态的概念
2. 程序的执行方式
(1) 顺序执行
一个程序完全执行完毕后,另一个程序才能被执行
缺点:CPU的利用率非常低
某些程序在等待外部条件的时候,CPU是空闲的
输入数据----->计算------>输出
(2) 并发执行
多个程序同时运行(宏观),本质上还是顺序执行
一个程序有非常多的指令
把一条指令的执行过程,分为几个不同的步骤:
取指令----->执行------>回写
不同的步骤,由不同的硬件去完成
理论上来说,就可以多个程序同时运行(宏观)
为了提高cpu的利用率,增加吞吐量,引入"并发执行"
现代的操作系统为了能够让程序并发执行,特地引入"进程"的概念
正在进行的程序
3. 进程
进程是什么?
进程是具有独立功能的程序关于某一个数据集合上的一次运行活动
理解为"炒菜(进程)和菜谱(程序)"的关系
test.c -------->源程序(源代码)
int main() {
int a, b;
int sum;
scanf("%d%d", &a, &b);
sum = a + b;
printf("sum = %d\n", sum);
return 0;
}
gcc test.c -o test ===>test(程序,二进制文件)
./test // 产生一个进程
4. 进程和程序的区别
(1) 程序是静态概念(是指令和数据的集合)
进程是动态的概念(动态产生,动态的消亡)
(2) 进程是一个程序的一次执行活动,一个程序可以对应多个进程(多进程编程)
(3) 进程是一个独立的活动单位,进程是竞争系统资源的基本单位(内存, cpu时间)
OS为什么要引入进程呢?就是为了能够让程序并发运行(同一时间段有多个程序正在运行)
程序的并发,实际上就是进程的并发
5. 进程状态
OS把一个进程的执行过程,分为几个不同的阶段(状态):
就绪态(Ready): 进程所有的准备工作已经完成,只需要CPU去执行进程的指令
运行态(Running): CPU正在执行这个进程的指令
阻塞态:(Blocking, 等待Waiting): 进程正在等待其他的外部事件(如:输入......)
进程的这些状态可以进行切换
僵尸进程(Zombie):
当进程退出时,父进程没有读取到子进程退出码,子进程就会成为僵尸进程
一个进程结束了,但是它的父进程没有等待(wait / waitpid)它,那么它就会变成僵尸进程
僵尸进程会以终止状态保持在进程表中,一直等待父进程读取退出状态码
危害:占用系统资源
孤儿进程:
父进程结束了,子进程就被称为"孤儿进程"
孤儿进程被 init 系统进程收养
"就绪队列":Ready Queue
所有处于就绪态的进程,都处于一个 "队列" 中
"调度程序":负责确定下一个进入"Running"状态的进程
确定下一个占用CPU的进程
"调度策略":调度算法
分时系统:调度策略以"时间片轮转"为主要策略的系统
"时间片轮转":分时,每一个进程执行一段时间(时间片)
如:大部分的桌面操作系统,linux android windows macos unix......
实时系统:调度策略以"实时策略"为主要策略的系统"实时策略":每一次调度都取优先级最高的那个进程执行,直到这个进程执行完毕或者他主动放弃CPU或者其他更高优先级的进程抢占
如:ucos,freeRTOS...可抢占和不可抢占
6. linux进程地址空间布局
程序运行的第一件事,就是申请一块内存区域来存储程序的"数据(用户数据,指令)",不同的数据属性是不一样的
"分区域" 来存储程序的数据
"分段":分不同的逻辑区域
不同属性的数据,存储到不同的"内存段"中,不同的内存段的属性以及管理方法不同
.text 主要存放指令
只读并且共享,这段内存在程序运行期间内不会被释放
"指令段":随进程的持续性
.data 数据段
主要存放程序已经初始化的全局变量和已经初始化的静态(static)变量
可读可写,这段内存在程序运行期间内不会被释放,随进程的持续性
.bss 数据段
主要存放程序未初始化的全局变量和未初始化的静态(static)变量
可读可写,这段内存在程序运行期间内不会被释放,随进程的持续性
.bss段,在程序初始化时,可能全部被初始化为0(未初始化的全局变量和未初始化的静态(static)变量自动初始化为0)
.rodata 只读数据段
主要存储程序中的只读数据(如:字符串常量)
只读(不可以更改):这段内存在程序运行期间内不会被释放,随进程的持续性
栈(stack)空间:
主要存放局部变量(非static的局部变量)
可读可写,这段空间,会自动释放(代码块执行完了,代码块中的局部变量的空间就会自动释放),随代码块的持续性
返回一个局部变量的地址,就会有问题
堆(heap)空间:动态内存空间主要是malloc / realloc / colloc动态分配的空间
可读可写的,这段内存在程序运行期间,一旦分配就会一直存在,直到你手动free或者程序结束
防止''内存泄漏'' / "垃圾内存"
例子:
7.