僵尸进程
概念
僵尸进程(Zombie Process)是指一个已经终止执行的子进程,但其父进程尚未调用 wait()
或 waitpid()
函数来获取子进程的退出状态。
-
Linux 中,僵尸进程会保留一些资源,如进程 ID、进程表项和一些系统资源,但不再执行任何代码。
-
僵尸进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。
创建僵尸进程,并检测
下面的代码将创建僵尸进程,并可以通过指令来查询其'Z'
状态:
- 在代码中,当父进程创建子进程后,父进程会通过
sleep(10)
函数暂停 10 秒钟等待子进程结束。在这个等待期间,子进程会立即退出并成为一个僵尸进程。
int main()
{
pid_t pid = fork();
if(pid < 0)
{
std::cerr << "fork error" << std::endl; // 创建失败
exit(1);
}
else if(pid == 0) // 子进程
{
// 获取并打印 子进程的pid
std::cout << "子进程:" << getpid() << "正在运行" << std::endl;
exit(0);
}
else // 父进程
{
std::cout << "父进程:" << getpid() << "等待子进程结束" << std::endl;
sleep(10); // 父进程暂停10s,等待子进程结束
std::cout << "父进程:" << getpid() << "结束" << std::endl;
}
return 0;
}
当成功运行程序后,我们通过下面的指令检测僵尸进程:
# 列出所有处于僵尸状态的进程的相关信息,包括进程号、父进程号、状态和命令行
ps -A -o pid,ppid,state,command | grep 'Z'
执行结果:
危害
僵尸进程本身并不会对系统造成直接的危害,因为它们不再执行任何代码。然而,如果系统中存在大量的僵尸进程,可能会导致以下问题:
-
资源浪费:僵尸进程会占用一些系统资源,如进程 ID、进程表项和一些系统内存。 虽然这些资源通常很小,但如果大量的僵尸进程积累,可能会导致资源浪费,降低系统的性能。
-
进程数量限制:操作系统对进程数量有一定的限制,具体取决于系统的配置和资源。如果系统中存在大量的僵尸进程,可能会消耗进程 ID 的数量限制,导致无法创建新的进程。
-
资源浪费:虽然僵尸进程本身不会直接影响系统稳定性,但如果父进程没有正确处理子进程的退出状态,可能会导致父进程无法正常工作或异常终止,从而影响系统的稳定性。
-
安全风险:如果恶意程序利用僵尸进程的存在来进行攻击,可能会导致安全风险。例如,恶意程序可以通过创建大量的僵尸进程来耗尽系统资源,或者利用僵尸进程来隐藏自己的存在。
为了避免僵尸进程的危害,父进程应该正确处理子进程的退出状态。这可以通过调用
wait()
或waitpid()
函数来实现。当父进程调用这些函数时,它会等待子进程的退出,并获取其退出状态。通过及时处理子进程的退出状态,可以释放僵尸进程所占用的资源,保持系统的稳定性和性能。
孤儿进程
概念
孤儿进程(Orphan Process)是指父进程先于子进程结束,导致子进程的父进程变为系统进程(PID=1,称为一号进程)(通常是 init 进程或 systemd 进程),从而成为孤儿进程。
创建孤儿进程,并检测
下面的代码创建了孤儿进程,并可以通过指令来获取其信息:
int main()
{
pid_t pid = fork();
if (pid == -1)
{
// 创建子进程失败
std::cerr << "failed to fork" << std::endl;
return 1;
}
else if (pid == 0) // 子进程
{
// 子进程任务内容
sleep(2); // 进程等待时间
std::cout << "Child process: My PID is " << getpid() << std::endl;
std::cout << "Child process: My parent's PID is " << getppid() << std::endl;
while (1)
{
// 打印子进程进程号信息。
printf("The child process is running ! childpid=%d fatherpid=%d \n", getpid(), getppid());
sleep(2);
}
}
else // 父进程
{
std::cout << "Parent process: My PID is " << getpid() << std::endl;
return 0; // 父进程立即退出,子进程变孤儿进程
}
return 0;
}
当我们成功运行程序后,执行命令检测孤儿进程
危害
-
占用系统资源:孤儿进程虽然没有父进程,但仍然在系统中运行并占用系统资源,如内存、CPU 时间等,会影响系统的性能和稳定性。
-
导致资源泄露:孤儿进程如果没有被及时回收,可能会导致资源泄露,如文件描述符、网络连接等,这些资源无法被其他进程使用,浪费了系统资源。
-
降低系统安全性:孤儿进程可能会成为黑客攻击的入口,黑客可以利用孤儿进程来执行恶意代码,窃取敏感信息或者破坏系统安全。
-
影响系统稳定性:孤儿进程如果不及时回收,可能会导致系统崩溃或死锁等问题,从而影响系统的稳定性。
及时处理孤儿进程是维护系统稳定性和安全性的重要措施之一。一般来说,可以通过编写程序来检测和处理孤儿进程,或者通过设置信号处理函数等方式来避免孤儿进程的产生。