多进程——孤儿进程或者僵尸进程解决方法

26 篇文章 0 订阅

多进程中,难免会出现父进程先于子进程退出或者子进程先于父进程退出,为此分为两种情况,若父进程先于子进程先退出,则子进程相当于孤儿进程;若子进程先于父进程先退出,则子进程相当于僵尸进程。
fork在 <unistd.h>文件中定义如下:
使用pid_t fork(void)函数创建子线程,若fork返回为-1,则调用失败;若fork返回为0,相当于是子线程;若fork大于0,则为父进程。
一、僵尸进程
例程

#include <stdio.h>
#include <stdlib.h>

#include <signal.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <errno.h>

int main()
{
    int fds[2];
    pipe(fds);
    pid_t pid;
    pid=fork();
    int i=0;
    if(0==pid)
    {
        for(i=0;i<20;i++)
        {
            sleep(1);
            printf("I'm child %d\n",i);
        }
    }
    else
    {
        for(i=0;i<30;i++)   //父进程调用时间大于子进程
        {
            sleep(1);
            printf("I'm farmer %d\n",i);
        }
    }

    if(pid==0)
    {
        printf("child exit!\n");
    }
    else
    {
        printf("farmer exit!\n");
    }
    return 0;
}

因子进程先于父进程退出,则出现,进程状态为Z+

machine~$:ps au|grep fork
1000      5282  0.0  0.0   4168   352 pts/3    S+   14:23   0:00 ./fork_test
1000      5283  0.0  0.0   4168    88 pts/3    S+   14:23   0:00 ./fork_test
1000      5287  0.0  0.0  13616   944 pts/4    S+   14:23   0:00 grep --color=auto fork
machine~$:ps au|grep fork
1000      5282  0.0  0.0   4168   352 pts/3    S+   14:23   0:00 ./fork_test
1000      5283  0.0  0.0      0     0 pts/3    Z+   14:23   0:00 [fork_test] <defunct>
1000      5289  0.0  0.0  13616   944 pts/4    S+   14:23   0:00 grep --color=auto fork
fengweilong@machine~$:

解决方法(使用信号量SIGCHLD):

	void fork_handler(int sig)
	{
    	printf("child PID is end!\n");
    	int state;
    	waitpid(-1,state,WNOHANG);
	}

	struct sigaction act;
    act.sa_handler = fork_handler;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    sigaction(SIGCHLD,&act,0);

二、孤儿进程

#include <stdio.h>
#include <stdlib.h>

#include <signal.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <errno.h>

int main()
{
    int fds[2];
    pipe(fds);
    pid_t pid;
    pid=fork();
    int i=0;
    if(0==pid)
    {
        for(i=0;i<30;i++)
        {
            sleep(1);
            printf("I'm child %d\n",i);
        }
    }
    else
    {
        for(i=0;i<20;i++)   //子进程调用时间大于父进程
        {
            sleep(1);
            printf("I'm farmer %d\n",i);
        }
    }

    if(pid==0)
    {
        printf("child exit!\n");
    }
    else
    {
        printf("farmer exit!\n");
    }
    return 0;
}

父进程退出时,通知子进程,利用进程间通讯,方式有信号、信号量、共享内存、消息队列、管道和套接字。其中使用的是管道。解决方法:

#include <stdio.h>
#include <stdlib.h>

#include <signal.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <errno.h>

void fork_handler(int sig)
{
    printf("child PID is end!\n");
    int state;
    waitpid(-1,state,WNOHANG);
}

void *read_error(void *arg)
{
    int fd = *(int *)arg;
    char buf[100];
    printf("parent PID is %d,current PID is %d\n",getppid(),getpid());
    while((-1 == read(fd,buf,sizeof(buf))) && EINTR == errno);//利用父进程退出后,管道退出,导致子进程再去读取时,导致退出循环,子进程返回
    printf("parent PID is %d,current PID is %d\n",getppid(),getpid());
    exit(-1);
}

int main()
{
    struct sigaction act;
    act.sa_handler = fork_handler;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    sigaction(SIGCHLD,&act,0);

    int fds[2];
    pipe(fds);
    pid_t pid;
    pid=fork();
    int i=0;
    if(0==pid)
    {
        close(fds[1]);
        pthread_t pthd;
        pthread_create(&pthd,NULL,read_error,(void *)&fds[0]);

        for(i=0;i<30;i++)
        {
            sleep(1);
            printf("I'm child %d\n",i);
        }
    }
    else
    {
        close(fds[0]);
        for(i=0;i<20;i++)
        {
            sleep(1);
            printf("I'm farmer %d\n",i);
        }

    }

    if(pid==0)
    {
        printf("child exit!\n");
    }
    else
    {
        printf("farmer exit!\n");
    }
    return 0;
}

实验结果父进程退出后,子进程也一起退出:

/FORK_PID$:./fork
parent PID is 5291,current PID is 5292
I'm child 0
I'm farmer 0
I'm child 1
I'm farmer 1
I'm child 2
I'm farmer 2
。。。。
I'm child 18
I'm farmer 18
I'm child 19
I'm farmer 19
farmer exit!
parent PID is 1,current PID is 5292
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值