Linux进程控制
文章目录
- Linux进程控制
- Linux系统任务管理的方法
- PCB的原型
- Linux查看获取进程id的方式
- 现象解释
- Linux 进程的状态
- 首先学习查看进程状态的命令
- 常见的几种状态
- 僵尸进程的危害
- 孤儿进程:
- 进程优先级
- 概念:
- PRI and NI
- 查看进程优先级的命令
- 环境变量
- 概念
- 常见的环境变量
- 测试PATH
- 详解环境变量
- END
Linux系统任务管理的方法
在Linux中,所有执行的程序都会以进程的形式加载到内存中,进程=PCB+代码和数据,PCB里包含进程运行的各种信息
PCB的原型
Linux的内核PCB其实就是一个非常复杂的结构体,里边我们这节课只关注两个属性,pid(进程id)和ppid(父进程id)
Linux查看获取进程id的方式
pid_t pid=getpid(); //获取pid
pid_t ppid=getppid(); //获取ppid
fork(); //创建子进程
eg:
//示例代码
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{pid_t id=fork(); if(id==0){while(1){printf("i am a child process,my pid:%d ppid:%d\n",getpid(),getppid());sleep(1);}}else{ while(1){printf("i am a parent process,my pid:%d ppid:%d\n",getpid(),getppid());sleep(1);}}return 0;
}
这个C程序运行起来是这样的结果:
现象解释
当程序执行到fork函数以后,系统会创建一个子进程,子进程和父进程暂时共享fork函数后边的代码和数据,这时候会有一个颠覆大家常识的现象,就是fork函数是有返回值的,我们创建了一个子进程,fork会对子进程返回0值,对父进程返回子进程的pid。这时候一定会想,一个变量怎么会同时赋值两个不同的值呢?
那是因为每个进程都有相同范围的地址空间,地址空间和实际物理空间地址还有一层页表的转化,地址空间指向一个页表,页表指向实际物理空间,当创建子进程时候,父子进程的地址空间是一致的,当子进程需要对程序数据进行修改或者操作的时候,子进程的页表会自动指向一块新的空间,来存放或者修改变量值。这也称为写时拷贝。这也可以解释为什么一个变量可以存在多个不同的值了
eg:
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>int main()
{int a=10;pid_t id=fork();while(1){if(id)printf("parent process:a=%d\n",a);//parent processif(id==0){a=0;printf("child process:a=%d\n",a);//child process}sleep(1);}return 0;
}
运行结果:
Linux 进程的状态
首先学习查看进程状态的命令
ps aux / ps axj
运行结果为:
常见的几种状态
R 运行状态 并不意味着在运行,也有可能在运行队列中
S 睡眠状态 意味着进程中在等待时间完成
D 磁盘休眠状态 等待IO结束
T 停止状态 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。
X 死亡状态 这个状态只是一个返回状态,你不会在任务列表里看到这个状态。
Z 僵尸状态 进程已死亡,并未被任何进程读取,就会一直存在僵尸状态,此时也是存在资源占用的,存在内存泄漏的风险
僵尸进程的危害
进程的退出状态必须被维持下去,因为他要告诉关心它的进程(父进程),你交给我的任务,我办的怎么样了。可父进程如果一直不读取,那子进程就一直处于Z状态?是的!
维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在task_struct(PCB)中,换句话说,Z状态一直不退出,PCB一直都要维护?是的!
那一个父进程创建了很多子进程,就是不回收,是不是就会造成内存资源的浪费?是的!因为数据结构对象本身就要占用内存,想想C中定义一个结构体变量(对象),是要在内存的某个位置进行开辟空间!内存泄漏?是的!
孤儿进程:
父进程如果提前退出,那么子进程后退出,进入Z之后,那该如何处理呢?
父进程先退出,子进程就称之为“孤儿进程”
孤儿进程被1号init进程领养,当然要有init进程回收喽。
孤儿进程不会存在内存泄漏的问题,在父进程退出后,由一号进程收养,自然也包括回收。
进程优先级
概念:
1、cpu资源分配的先后顺序,就是指进程的优先权(priority)。
2、优先权高的进程有优先执行权利。配置进程优先权对多任务环境的linux很有用,可以改善系统性能。
3、还可以把进程运行到指定的CPU上,这样一来,把不重要的进程安排到某个CPU,可以大大改善系统整体性能。
在linux或者unix系统中,用ps –l命令则会类似输出以下几个内容:
UID : 代表执行者的身份
PID : 代表这个进程的代号
PPID :代表这个进程是由哪个进程发展衍生而来的,亦即父进程的代号
PRI :代表这个进程可被执行的优先级,其值越小越早被执行
NI :代表这个进程的nice值
PRI and NI
PRI也还是比较好理解的,即进程的优先级,或者通俗点说就是程序被CPU执行的先后顺序,此值越小进程的优先级别越高
那NI呢?就是我们所要说的nice值了,其表示进程可被执行的优先级的修正数值
PRI值越小越快被执行,那么加入nice值后,将会使得PRI变为:PRI(new)=PRI(old)+nice
这样,当nice值为负值的时候,那么该程序将会优先级值将变小,即其优先级会变高,则其越快被执行
所以,调整进程优先级,在Linux下,就是调整进程nice值
nice其取值范围是-20至19,一共40个级别。
查看进程优先级的命令
//top
//top后按->"r"->输入进程pid->键入修正nice值
环境变量
概念
环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数
如:我们在编写C/C++代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪里,但是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找。
环境变量通常具有某些特殊用途,还有在系统当中通常具有全局特性
常见的环境变量
PATH : 指定命令的搜索路径
HOME : 指定用户的主工作目录(即用户登陆到Linux系统中时,默认的目录)
SHELL : 当前Shell,它的值通常是/bin/bash。
查看环境变量的方式:
echo $NMME//NAME:你的环境变量名称
测试PATH
eg:
#include <stdio.h>
int main()
{printf("hello world!\n");return 0;
}
- 对比./hello执行和之间hello执行
- 为什么有些指令可以直接执行,不需要带路径,而我们的二进制程序需要带路径才能执行?
- 将我们的程序所在路径加入环境变量PATH当中, export PATH=$PATH:hello程序所在路径
- 对比测试
- 还有什么方法可以不用带路径,直接就可以运行呢?
解释说明
export 是导入环境变量的作用,但是只在内存层面的,每次重启会恢复原样,要永久修改还是需要修改配置文件的
详解环境变量
每个程序都会收到一张环境表(char env[]),环境表是一个字符指针数组,每个指针指向一个以’\0’结尾的环境字符串*
通过代码获取
#include <stdio.h>
int main(int argc, char *argv[], char *env[])
{int i = 0;for(; env[i]; i++){printf("%s\n", env[i]);}return 0;
}
环境变量特性:
环境变量通常是具有全局属性,可以被子进程继承下去