僵尸进程
1.原理:
子进程先于父进程退出,父进程来不及回收子进程的资源,导致子进程变成僵尸进程,而子进程所对应的task_struct还在内核当中,双向链表管理着。对于子进程而言,程序是已经退出了,并不能执行任何用户的代码了;子进程的状态会变为Z状态;”刀枪不入“
2.产生僵尸进程之后,僵尸进程对应的状态是Z,并且使用kill命令或者强杀命令 kill -9 ,都结束不了僵尸进程
3.僵尸进程的危害:
产生僵尸进程后,僵尸进程是不能被强杀杀死的,意味着在操作系统内核双向链表还维护着僵尸进程的task_struct。内核维护这样的结构体是要耗费内存的,程序员还结束不了僵尸进程,所以操作系统内存泄露了。
4.如何预防僵尸进程的产生:
- 子进程不要先于父进程退出 (不可取)
- 进程等待(后面介绍) (可取,优雅的预防)
- 可以将父进程kill掉,然后僵尸进程就变成了孤儿进程,进而僵尸进程被1号进程领养,1号进程回收僵尸进程的资源。 (杀敌一千,自损八百,不可取)
来段代码测试一下
//测试代码
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
printf("hello\n");
pid_t ret = fork();
if(ret < 0)
{
perror("fork error");
return 0;
}
else if(ret == 0)
{
//child
printf("i am child, pid=%d, ppid=%d\n", getpid(), getppid());
sleep(5);
}
else
{
//father
while(1)
{
printf("i am father, pid=%d, ppid=%d\n", getpid(), getppid());
sleep(1);
}
}
return 0;
}
在另一个终端输入ps aux | head -1; ps aux | grep testZ | grep -v grep
进行监控,5秒后进程进入僵尸状态
可验证kill -9也无法强杀僵尸进程
可以将父进程kill掉,再查看僵尸进程状态,可见其已被操作系统回收
孤儿进程
- 1.原理:
父进程先于子进程退出,子进程会被1号进程所领养,1好进程被称为init进程。1号进程会在子进程退出的时候回收子进程的退出信息,防止子进程变为僵尸进程。
- 2.现象
//测试代码
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
printf("hello\n");
pid_t ret = fork();
if(ret < 0)
{
perror("fork error");
return 0;
}
else if(ret == 0)
{
//child
printf("i am child, pid=%d, ppid=%d\n", getpid(), getppid());
sleep(10);
}
else
{
//father
printf("i am father, pid=%d, ppid=%d\n", getpid(), getppid());
sleep(5);
}
return 0;
}
在终端监控下,可以看到子进程的ppid变为1
- 3.注意:孤儿进程不是一种进程状态!而是一种进程种类的名称
环境变量
1.概念:环境变量是用来定义系统运行环境的一些参数的
问题:为什么ls程序可以在任意目录下运行,而我们编译出来的代码,只能在当前编译目录下运行?
2.常见环境变量
HOME:保存用户家目录的环境变量
SHELL:保存当前使用的命令行解释器
PATH:保存可执行程序路径的环境变量
LD_LIBRARY_PATH:程序运行时依赖的库文件的搜索路径的环境变量
3.查看环境变量:echo $环境变量名称
4.新增环境变量的值
用export去更改或增加环境变量的值
万能公式:export [环境变量名称] = $[环境变量名称] : [新增加环境变量的值]
eg: export PATH = $PATH:/home/test
注意:在命令行当中使用export是临时生效的做法,只在当前终端内有效,当前终端关闭后,重新打开就没有之前设置的值了。
永久生效:将环境变量的值写到下面的文件中
- 普通用户:
~/.bashrc 或者~/.bash_profile
- 系统环境变量设置:(普通用户的环境变量不要往系统里添加)
/etc/bashrc
添加完成后使用source命令重新加载文件
source:告诉操作系统内核重新加载某一文件
用法:source 环境变量文件
和环境变量相关的命令
- echo: 显示某个环境变量值
- export: 设置一个新的环境变量
- env: 显示所有环境变量
- unset: 清除环境变量
- set: 显示本地定义的shell变量和环境变量
来看个例子进行测试
//测试代码
#include <stdio.h>
int main()
{
printf("hello world\n");
return 0;
}
执行程序可看到如下结果