创建进程,销毁僵尸进程

//创建进程
#include <stdio.h>
#include <unistd.h>

//父子进程共享同一段代码,但在不同的内存结构中
int gval=10;
int main(int argc,char *argv[])
{
	pid_t pid;
	int lval=20;
	gval++,lval+=5;
	
	pid=fork();		//调用fork函数床创建进程,父进程返回子进程的ID 子进程返回0
	if(pid==0)
		gval+=2,lval+=2;
	else
		gval-=2,lval-=2;
	
	if(pid==0)
		printf("Child Proc: [%d,%d] \n",gval,lval);
	else
		printf("Parent Proc: [%d,%d]\n",gval,lval);
	return 0;
}


//创建僵尸进程

#include <stdio.h>
#include <unistd.h>

int main(int argc,char *argv[])
{
	pid_t pid=fork();	
	
	if(pid==0)
	{
		puts("Hi,I am a child process");
	}
	else
	{
		printf("Child Process ID: %d \n",pid);
		sleep(30);
	}
	
	if(pid==0)
		puts("End child process");
	else
		puts("End parent process");
	return 0;
}


//销毁僵尸进程wait

#include <stdio.h>
#include <sys/wait.h>		//因为要调用wait()函数,销毁子进程要由父进程主动管理,wait函数可能会引起阻塞
#include <unistd.h>		//exit,return的返回值将传递给操作系统,而操作系统不会销毁子进程,直到把这些值传递给产生该子进程的父进程
#include <stdlib.h>		//所以产生僵尸进程的正是操作系统
				//如果父进程终止,处于僵尸状态的子进程将同时销毁
int main()
{
	int status;
	pid_t pid=fork();
	
	if(pid==0)
	{
		return 3;
	}
	else
	{
		printf("Child One PID: %d \n",pid);
		pid=fork();
		if(pid==0)
		{
			exit(7);
		}
		else
		{
			printf("Child Two PID: %d \n",pid);
			wait(&status);			//利用wait()函数销毁僵尸进程
			printf("status:%d \n",status);	//单独输出status并没什么意义,&status指向的单元还包含其他信息
			
			wait(&status);			//利用wait()函数销毁僵尸进程
			printf("status:%d \n",status);
/*			if(WIFEXITED(status))
				printf("Child one send: %d \n",WEXITSTATUS(status));
			
			wait(&status);
			if(WIFEXITED(status))
				printf("Child two send: %d \n",WEXITSTATUS(status));
*/
			sleep(30);
		}
	}
	return 0;
}


//销毁僵尸进程waitpid

#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>

int main()
{
	int status;
	pid_t pid=fork();
	
	if(pid==0)
	{
		sleep(15);
		return 24;
	}
	else
	{
		while(!waitpid(-1,&status,WNOHANG))		//-1可以等待任意子进程终止,WNOHANG即使没有终止的子进程也不会阻塞而是返回0并退出函数
		{										//成功时返回终止的子进程ID,失败返回-1
			sleep(3);
			puts("sleep 3sec.");
		}
		
		if(WIFEXITED(status))
			printf("Child send %d \n",WEXITSTATUS(status));
	}
	return 0;
}


### Linux僵尸进程的概念 在Linux操作系统中,僵尸进程是指那些已经完成执行(即退出)但其父进程尚未通过`wait()`系统调用来获取其状态信息的子进程。尽管这些进程实际上不再运行,但在系统的进程表中仍然保留着它们的状态信息,直到父进程回收为止[^1]。 #### 查找僵尸进程的方法 可以使用多种方法查找僵尸进程。一种常见的做法是借助`ps`命令来识别带有特殊标志“Z”的进程。具体操作如下: ```bash ps aux | grep Z ``` 上述命令会显示所有处于僵尸状态的进程列表。如果希望统计当前系统中存在的僵尸进程数量,则可进一步扩展为: ```bash ps aux | grep Z | wc -l ``` 另一种更为精确的方式涉及结合`ps`与正则表达式匹配技术定位特定类型的僵尸记录: ```bash ps -A -ostat,ppid,pid,cmd | grep -e '^[Zz]' ``` 此语句能够筛选出所有标记为大写或小写字母‘Z’开头的条目,并附带额外细节如父PID(PPID),自身PID(PID)以及对应的指令名称(CMD)[^4]。 #### 解决僵尸进程的办法 由于僵尸进程本身并不消耗CPU资源或者内存空间,因此通常不会直接影响到整个系统的性能表现;然而长期累积下来可能会耗尽可用的进程号池,从而引发其他潜在问题。所以及时清理是非常必要的。 要解决这个问题,首先要确认造成僵尸现象的根本原因是哪个应用程序产生的——这往往是因为该应用未能妥善处理子线程结束后的善后工作所致。一旦明确了源头之后,可以选择以下几种策略之一来进行干预: - **重启服务**: 对于某些简单场景下,重新启动关联的服务可能是最快速有效的手段。 - **强制销毁孤儿僵尸**: 如果确定某个具体的僵尸无法被正常回收而且也没有必要继续保存的话,可以直接尝试发送信号给它的实际拥有者也就是init进程让它接管并最终清除掉这个残留项。不过需要注意的是这种方法仅适用于少数特殊情况下的极端措施因为一般情况下我们更倾向于修复产生这些问题的应用逻辑而不是单纯依赖外部力量强行消除后果。 另外值得注意的一点在于,真正意义上的"杀死"一个僵尸是不可能实现的因为它根本就不存在活动迹象只是等待最后阶段的数据提取而已真正的目标应该是促使负责管理这部分数据结构的那个上级实体尽快履行职责完毕即可[^2]。 ```bash kill -9 <pid> ``` 这里 `<pid>` 是指代那个作为始作俑者的原始创建者而非直接针对那些标注出来的所谓'尸体'. 当然除了以上提到的手动排查方式之外还可以考虑自动化脚本定期扫描检测异常状况以便提前预防大规模爆发风险. ### 总结 综上所述,在面对Linux环境里的僵尸进程时,应当先学会如何准确无误地将其甄别出来然后再依据实际情况采取合理的应对方案。无论是优化现有软件设计减少此类事件发生频率也好或者是建立完善的监控体系第一时间响应处置也罢都是值得提倡的良好实践方向。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值