进程基本概念:
1. 进程:
程序:存放在外存中的一段数据组成的文件
进程:是一个程序动态执行的过程,包括进程的创建、进程的调度、进程的消亡
2. 进程相关命令:
1. top:
动态查看当前系统中的所有进程信息(根据CPU占用率排序)
PID:唯一识别进程的ID号(>0)
优先级:Linux系统中数据高,优先级高(-20 到 19)Windows系统中数值高,优先级高
进程状态:
R 运行态/就绪态
S 睡眠态/可唤醒等状态
D 不可唤醒等待态
T 暂停态
Z 僵尸态
X 结束态
q 退出
2. nice/renice:
nice:以指定优先级来运行进程
示例:
nice -n 优先级 要执行的集成任务
renice:重新设定一个正在运行的进程的优先级
示例:
renice -n 优先级 进程PID
3. kill/killall:
kill:杀死指定的进程任务
示例:
kill -9 进程PID
killall:杀死进程名对应的所有进程任务
示例:
killall -9 进程名
4. ps -ef:
查看当前时刻所有进程的信息
PPID:父进程的ID号
PID:子进程的ID号
ps -ef | grep a.out
5. pstree:
查看进程树关系
6. ps -aux:
查看当前时刻的进程信息
7. ../a.out &
将a.out任务放在后台执行
8. jobs:
查看一个终端下后台执行的所有任务
9. fg 编号:
将后台任务放到前台执行
3. 进程的创建:
32bits操作系统:
一个进程在运行时,操作系统会为该进程分配 0-4G 虚拟内存空间,分为文本段、数据段、系统数据段
文本段:
也称为文本区,存放代码和指令
数据段:
也称为数据区,可以细分为:
1. 字符串常量区
2. 为初始化全局变量/静态变量
3. 已初始化全局变量/静态变量
系统数据段:
包含堆区和栈区
4. 进程中虚拟地址和物理地址的关系
1. 0 - 4G虚拟内存空间只有一个
2. 实际物理地址中每个进程空间独立
3. 通过MMU内存映射单元,单一个进程执行时,将物理地址中的数据加载到虚拟地址中运行
5. 进程的调度:
1. 常见的调度算法:
1. 先来先执行、后来后执行
2. 高优先级调度算法
3. 时间片轮转调度算法
4. 多级队列后反馈调度算法
5. 负载均衡调度算法
时间片:
1. CPU在一个任务中的运行时间称为一个时间片
2. 宏观并行,微观串行
3. 进程的状态:
R 运行态、就绪态
S 睡眠态/可唤醒等待态
D 不可唤醒等待态
T 暂停态
Z 僵尸态
X 结束态
6. 进程相关函数接口:
1. 进程的创建
1. fork:
pid_t fork(void);
功能:创建一个子进程,新创建的进程称为原来进程的子进程,原来的进程称为新进程的父进程
参数:
void 缺省
返回值:
成功子进程返回0
父进程返回子进程的PID
失败返回-1
getpid:
pid_t getpid(void);
功能:获得调用进程的PID
getppid:
pid_t getppid(void);
功能:获得调用进程的PPID
练习:
创建一个父进程的2个子进程,子进程中打印自己的PID和父进程的PID,父进程中打印自己的PID和两个子进程的PID
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>int main(void)
{pid_t pid1;pid_t pid2;pid1 = fork();if(pid1 == -1){perror("fail to fork");return -1;}if(pid1 == 0){printf("chird process1: pid:%d, ppid:%d\n", getpid(), getppid());}else if(pid1 > 0){pid2 = fork();if(pid2 == -1){perror("fail to fork");return -1;}if(pid2 == 0){printf("child process2: pid:%d, ppid:%d\n", getpid(), getppid());}else if(pid2 > 0){printf("parent process: pid%d, child pid1:%d, child pid2:%d\n", getpid(), pid1, pid2);}}while(1){}return 0;
}
2. exit/_exit:
1. exit:
void exit(int status);
功能:
让进程结束
参数:
status:进程结束的状态
返回值:
缺省
exit在主函数中使用和return效果一致
exit会刷新缓存区
2. _exit:
void _exit(int status);
功能:
让进程直接结束
参数:
status:进程结束的状态
返回值:
缺省
7. 进程的消亡:
1. 僵尸进程:
进程代码执行结束,空间没有被回收,称为僵尸进程
2. 如何避免产生僵尸进程?
1. 让父进程先结束
2. 让父进程回收子进程空间
3. 孤儿进程:
进程的父进程先结束,此时该进程称为孤儿进程,被系统进程收养,进程再结束时,会被系统进进程空间
8. wait:
pid_t wait(int *wstatus);
功能:回收子进程空间
参数:
wstatus:存放子进程结束状态空间的首地址
返回值:
成功返回回收到的子进程PID
失败返回-1
1. wait函数具有阻塞功能
2. wait函数具有同步功能
WIFEXITED(wstatus) //进程是否正常退出 WEXITSTATUS(wstatus) //进程结束状态值WIFSIGNALED(wstatus) //进程是否被信号杀死WTERMSIG(wstatus) //获得杀死进程的信号编号
作业:
1.创建一个进程的9个子进程,子进程中打印自己的PID和父进程的PID,父进程中打印自己的PID和9个子进程的PID
#include "head.h"int main(void)
{pid_t pid[9] = {0};int i = 0;int stat = 0;for(i = 0; i < 9; i++){if(i == 0){pid[i] = fork();if(pid[i] == -1){perror("fail to fork");return -1;}}if(pid[i] == 0){printf("child pid[%d]:%d, ppid:%d\n", i, getpid(), getppid());exit(10);}else if(pid[i] > 0){pid[i+1] = fork();if(pid[i+1] == -1){perror("fail to fork");return -1;}wait(&stat);}if(i == 8 && pid[i+1] > 0){printf("parent pid: %d, ", getpid());for(int j = 0; j < 9; j++){if(pid[j] != 0)printf("child pid[%d]:%d ", j, pid[j]);if(j == 3){printf("\n");}}printf("\n");printf("\n");}}return 0;
}