1.孤儿进程
- 没有父进程的进程,父进程退出后,子进程就是孤儿进程,被1号(init)进程收养。运行在后端,脱离终端控制。
- 孤儿进程无法用ctrl + c退出,但是可以被kill -9 杀死
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, const char *argv[])
{
pid_t cpid = fork();
if(0 == cpid)
{
while(1)
{
printf("this is child : %d %d\n", getppid(), getpid());
sleep(1);
}
}
return 0;
}
2.僵尸进程
- 子进程退出,父进程没有退出,且子进程的资源没有被回收,此时子进程就是僵尸进程。
- 僵尸进程无法被再次杀死(kill -9)
- 危害:
- 占用进程号,占用物理空间,占用内存空间,占用进程控制块等等....
- 僵尸进程必须回收:
- 退出父进程,子进程的资源将由内核自动回收,
- 父进程执行wait / waitpid函数回收,缺点:阻塞函数,父进程无法做自己的任务。非阻塞形式,有可能收不到
- wait / waitpid函数结合信号的方式回收:子进程退出后,通知父进程,父进程暂停当前任务,先执行收尸。
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, const char *argv[])
{
pid_t cpid = fork();
if(cpid > 0)
{
while(1)
{
printf("this is parent : %d %d\n", getpid(), cpid);
sleep(1);
}
}
return 0;
}
回收僵尸进程
//当子进程退出后,父进程收到17号信号
//进入下面的信号处理函数中,执行waitpid函数回收僵尸进程。
void callBack_zombie(int sig)
{
pid_t wpid = 0;
while(1)
{
//若成功回收到僵尸进程,则再回收一次
//直到没有僵尸进程,结束循环
//=0,有子进程,但是没有僵尸进程
//=-1,没有子进程,也没有僵尸进程
wpid = waitpid(-1, NULL, WNOHANG);
if(wpid <= 0)
break;
printf("[%d] wpid = %d\n", count++, wpid);
}
return ;
}
void callBack_zombie1(int sig)
{
while(waitpid(-1, NULL, WNOHANG)>0);
return;
}
3.守护进程(幽灵进程)
- 守护进程脱离终端控制且运行在后端的进程。
- 守护进程在执行过程中不会将信息显示在任何终端上,防止影响前端指令执行。且不会被任何终端产生的数据信息打断。
- 如果要周期性执行某个任务或者等待处理某些事情的时候一般使用守护进程。大多数服务器都是由守护进程实现的。
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> int main(int argc, const char *argv[]) { pid_t cpid = fork(); if(0 == cpid) { //创建新的会话组 pid_t sid = setsid(); printf("sid=%d\n", sid); //修改运行目录为不可卸载的文件目录 chdir("/"); //重设文件权限掩码 umask(0); //关闭文件描述符 for(int i=0; i<getdtablesize(); i++) close(i); while(1) { //功能代码 sleep(1); } } return 0; }