进程管理是操作系统重点、难点问题,也是贯穿Linux学习的知识点。那么什么是进程呢?
1.为什么引入进程的概念?
- 从理论角度看,是对正在运行的程序过程的抽象;
- 从实际角度看,是一种数据结构,旨在清晰的刻画动态系统的内在规律,可以有效管理和调度进入计算机系统主存储器运行的程序。
2.进程的基本概念
- 用户角度:进程就是一段程序的执行过程
- 进程实际上就是一个程序的运行中的描述,这个描述称为PCB(进程控制块),Linux下PCB就是一个task_struct结构体
task_struct结构体
task_struct是Linux内核中的一种数据结构,里面包含着进程的信息,其内容分类都有:
- 标识符:描述进程的唯一标识符,用来区别其他的进程。
- 状态:描述进程的状态,进程有挂起、运行、阻塞等状。态,退出代码,退出信号等。
- 优先级:有多个进程同时进行运行时就存在先后执行顺序的问题,决定获取的CPU资源。
- 程序计数器:用于保存在CPU上即将执行的下一步指令的地址,CPU要执行任何指令,都需要将指令加载到寄存器中。
- 内存指针:包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针。
- 上下文数据:保存CPU上正在处理的数据。
- I/O状态信息:包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
- 记账信息:可能包括处理器时间总和,使用的时钟数总和,时间限制,记帐号等。
关于task_struct结构体更多的详细介绍可以看看大佬的这篇介绍
3.查看进程的方法
- ps -ef:查看所有的进程信息
- ps aux:查看进程的详细信息
- top(查看进程的信息)
- 查看你所要的进程信息: ps -ef | 名字
4.如何创建一个进程-初识fork
创建进程:pid_t fork(void); 通过复制调用(父进程)创建了一个新的进程(子进程)。进程就是pcb,创建一个进程就是创建了一个pcb,复制了调用fork的这个进程pcb的信息,运行的位置也相同。
fork函数
fork函数的返回值比较特殊:
对于父进程:返回子进程的pid
对于子进程:返回0
创建子进程失败:返回-1
父子进程代码共享,数据各自开辟空间,私有一份(写时拷贝)
关于进程创建一部分在学习后面进程控制会继续深入了解学习。
5.进程的状态
根据不同的方式角度对进程进行划分分为以下三种情况:
进程的三种状态
将进程划分为最基本的三种状态分别是:就绪、运行、阻塞状态。
就绪
:等待CPU执行的进程;
运行
:CPU正在执行进程中的指令;
阻塞
:正在执行的进程,由于等待某个事件发生而无法执行时,便放弃处理机而处于阻塞状态。引起进程阻塞的事件可有多种,例如,等待I/O完成、申请缓冲区不能满足、等待信件(信号)等。
其转换过程如下图:
进程的五种状态
为了满足PCB对数据的操作及操作的完整性要求,通常在系统中又为进程引入了两种常见的状态:创建状态
和终止状态
进程的七种状态
R(running) 运行态
:并不意味着程序一定在运行中,它表明进程要么在运行中要么在运行队列里。
S(sleeping) 睡眠状态
:可中断的休眠(浅度睡眠)
D(disk sleep) 不可被中断的休眠状态
:只能通过指定的方式—>唤醒(深度睡眠),这个状态的进程通常会等待I/O的结束
T(stopped) 停止状态
t(tracing stop) 追踪状态
X(dead) 死亡状态
:
Z(zombie) 僵死状态
:这个状态只是一个返回状态,不会在任务列表中看到这个状态,进程已经退出,但是资源没有得到释放。
6.僵尸进程
僵尸进程是处于僵死状态的进程,退出后资源没有完全释放的过程。
- 产生原因:子进程先于父进程退出,但父进程没有关注子进程的退出状态,导致子进程资源无法完全释放,成为僵尸进程。
- 解决方式:进程等待(等待子进程退出,获取子进程返回值,释放子进程资源,避免出现僵尸进程)->父进程一直等待子进程的退出。
- 产生危害:会导致资源泄露,一个用户创建的进程是有限的,僵尸进程过多会导致创建新的子进程失败;内核中的PCB也没有被回收。
7.孤儿进程
- 父进程提前退出,子进程就被成为孤儿进程;
- 孤儿进程被1号进程领养,init进程进行回收;
- 运行在后台,父进程成为1号init/systemd进程。
8.环境变量
定义:环境变量一般是指在操作系统中用老保存或者设置系统环境参数的变量,使得系统运行的环境的配置更加灵活。
命令操作
- 查看环境变量:
env
:查看所有环境变量;
echo
:直接打印;
set
:查看所有变量,不只是环境变量;
echo $name//name表示变量名称
- 设置环境变量:
export
:声明定义转换环境变量 - 删除环境变量:
unset
常见的环境变量
- PATH:存储程序默认的搜索路径;
- HOME:制定用户的主工作目录(及用户登录到系统中时,默认的目录);
- SHELL:当前shell,它的值通常是/bin/bash
PATH:运行一个程序时,如果没有指定路径只有程序名称,shell会在PATH环境变量保存路径中去找这个程序,将自己程序所在路径加入到PATH环境变量中,程序就可以直接运行了。
9.获取环境变量的方式
1.main函数的第三个参数
int main(int argc,char *argv[ ],char *env[ ])
2.通过environ
变量进行获取
extern char **environ
声明一个全局变量(里面没有具体的数据),environ指向环境变量表,没有包含在任何头文件中
3.getenv
通过系统调用进行获取
char *getenv(char *key)
通过环境变量名称获取环境变量的内容
设置环境变量
int putenv(char *string)//通过代码设置一个环境变量
int setenv(const char *name,const char *value,int overwrite)//通过代码设置一个环境变量