linux–进程
1、程序 program
-
程序 = 数据结构 + 算法 数据结构 = 数据 + 结构 算法: 指令的集合 计算机:执行程序(使用指令 处理 数据)
2、 多个程序的执行方式
(1)顺序执行
-
(2)并发执行一个程序执行完毕之后,才能执行下一个程序 假如: a : 输入 计算 输出 b : 输入 计算 输出 ====>a: 输入(IO) 计算(CPU) 输出(IO) b:输入(IO) 计算(CPU) 输出(IO) ====>CPU 以及 IO利用率低
-
a:输入 计算 输出 b: 输入 计算 输出 =====》并发执行:在重合的时间点上,有多个程序在执行 并发:在某些时间点内,多个程序同时执行 并行:在任何一个时间点上,多个程序同时执行 =====>为了实现“并发",特地引入了"进程"的概念
3.什么是进程?(process)
- 正在运行的 程序
进程是具有独立功能的程序 在某个数据集合上的 一次运行活动
process(v 动作的处理过程) 和procedure(n 步骤)的区别:
(1)程序 是 静态的概念 进程是一个动态的概念(开始 ---》结束)
main main运行的时候
(2)进程是独立活动单位 是竞争资源的基本单位
(3)程序中 是 可以启动 多个进程的
thinking:
进程1是CPU运行的,CPU发现有更高优先级的进程, 进程1是可以切换到另一进程2(可以抢占的)
切换的时候:
保存当前进程的所有信息,
当进程2处理完成,CPU切换回进程1 ,恢复原本保存的信息 继续运行
3.1进程从生到死 会经历的状态转换
就绪状态
阻塞状态
运行状态
A 就绪 ---》阻塞 X
B 就绪----》运行
C 阻塞---》运行 X
D 运行-时间片完--》就绪
4.进程 如何 实现 并发?
程序: main
运行程序main(即启动一个进程):
(1)把可执行程序的内容 加载 到内存 中
(2)CPU决定执行该进程,CPU开始执行 内存中存储的指令
======>涉及到的硬件?
内存 和 CPU
(1)CPU可以访问的内存空间有多大呢? (x86 linux系统32位)---->4G
4G的内存空间分布(存储的内容):
int a=10; //.data
int b; //.bss
int main()
{
char* p=malloc(10); //p: 栈 分配的空间(堆)
char* str1="abcde";//str1:栈 abcde :rodata
}
====》每个进程都认为自己有4G的内存。
=====>OS运行多个进程,如果每个进程真正占用4G的内存,
物理内存不够,如何实现的呢?
====>4G 虚拟内存
====>as a code farmer ,我在程序中可以使用4G内存可用
内存操作空间
(2) 如何实现并发?----》 CPU
CPU给每个进程进行时间分片
-
进程名 1 2 3 4 | | | | | | | | | | | |
====》实现并发,CPU给每个进程一个时间片,在对应的时间片
运行进程,CPU速度极快,感觉所有程序 在同时运行
5.使用进程 -
./main —》运行main的时候,就已经有一个进程了
(1)创建进程 fork -
#include <unistd.h> pid_t fork(void); 返回值: 如果成功 父进程返回子进程的PID 子进程返回 0 如果失败 -1 errno被设置 NOTE: (1)fork之前本身有一个进程,fork之后,创建一个子进程。 (2)fork创建的子进程和父进程执行的代码一样的. fork之后子进程的地址空间是 完全从父进程 拷贝的 (3)fork之后创建的进程,运行的先后顺序undefine (4)子进程运行分配资源的,子进程的资源必须要由父进程回收, 如果父进程不回收子进程的资源,子进程就会成为僵尸进程 父进程比子进程先结束,子进程即成为 孤儿进程(继续运行),会把子进程的交给init (当子进程结束的时候,请init进程回收资源) ====保证=>子进程 比父亲进程 先结束 ====>父进程回收子进程 的资源
(2)父进程等待子进程执行结束 回收资源
-
#include <sys/types.h> #include <sys/wait.h> pid_t wait(int *status); 功能: 调用进程 等待 子进程状态改变: ①子进程结束 ②子进程被信号暂停 ③子进程被唤醒了 函数才会返回,否则一直阻塞。 status:NULL 如果非空,可以使用(*status)来判断子进程退出的信息 WIFEXITED(status);//是否正常退出 WEXITSTATUS(status)//退出码 .. 返回值: 成功 返回结束进程的ID号 失败 返回-1
(3)进程如何退出
-
主动退出: ①当所有的指令执行结束 即(main函数执行结束) int main() { return 0; } ②使用函数 exit :进程正常退出 (清理缓冲区) #include <stdlib.h> void exit(int status); status: 表示进程的退出码 功能:正常退出 && status&0377交给父进程 _exit 直接退出进程 #include <unistd.h> void _exit(int status); status:status&0377交给父进程 打开文件的文件关闭,子进程交给init进程
练习:
1.下列程序会创建几个进程?
int main() { fork(); int i; for(i=0;i<2;i++) { fork(); } printf("*************\n"); }
答案:8 个
2.下列程序的输出结果是什么?
-
int main() { pid_t pid=fork(); for(i=0;i<1;i++) { if(pid==0) { printf("son\n"); }else if(pid> 0) { wait(NULL); printf("father"); fork(); } } }//son father
答案: son 10,father 11
3.输出下列程序的执行结果?why? -
-
int a=10; int main() { int pid=fork(); if(pid==0) { a++; printf("son: %d\n",a); }else if(pid>0) { wait(NULL); printf("father: %d\n",a); } return 0; } son:11 father 10
父子进程的 地址空间(虚拟内存)4G 独立。
父进程 修改的变量 自己的私有地址空间
子进程 修改的变量 自己的私有地址空间4.创建一个进程,子进程进行冒泡排序,父进程输出结果
答: 父进程输出的一定是:原有的未排序的数组