oracle listener为何要fork两次子进程产生serverprocess?

相关主题

1:listener为何要fork两次子进程
2:为何listener要fork两次子进程,这里面有我的观点,本文主要是把以前模拟日记分享出来

模拟进程说明

c代码非常简单,主要就是fork,execv,wait,exit及输出一些标识,有简单的c知识都能看懂
listener.c:模拟oracle listener
serverprocess.c:模拟oracle serverprocess

listener.c

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

int main (int argc, char *argv[])   
{   
    pid_t fpid,cpr; 
    int count=0;  
    char *argnew[]={"serverprocessd",NULL};

    fpid=fork();   
    if (fpid < 0)   
        printf("###Parent fork error!\n");   
    else if (fpid == 0) {  

        printf("      Child, pid=%d\n",getpid());
        sleep(5);
        printf("      Child sleeped5S,will fork serverprocess\n");
        cpr=fork();
        printf("      Child fork end!\n");
        if (cpr<0)
           printf("######Child fork error!\n");
        else if (cpr==0){
            while (1){
               printf("            Grandchild has been born,will change to serverprocess after 5S,pid=%d\n",getpid());
               sleep(5);
               if (execv("/home/test/serverprocessd",argnew)<0){
                  printf("###########Grandchild execv error!");
               }
               printf("            Grandchild changing successfully!,pid=%d\n",getpid());
               count++;
               if (count>14){
                  printf("            Grandchild serverprocess will exit after 5S\n");
                  sleep(5);
                  printf("------------Grandchild serverprocess exit,pid=%d\n",getpid());
                  exit(0);
               } 
            }
        }else{
            printf("      Child will sleep 5S,then exit\n");
            sleep(5);
            printf("------Child exit,pid=%d\n",getpid());
            exit(0);
        }      
    }else{  
        printf("   Parent,pid=%d\n",getpid());
        while (1)
        {
           sleep(15);
           printf("   Parent Sleeped15S,begin wait\n");
           wait(NULL);
           count++;
           printf("   Parent wait end,count=%d\n",count);
           if (count>3){
              printf("---Parent will exit,pid=%d\n",getpid());
              exit(0);
           }
        }      
    }    
    return 0;  
}

serverprocess.c

#include<stdio.h>
int main(void)
{
  while (1){
    sleep(3);
    printf("___^_^ I'am serverprocess,have worked 3S\n");
  }
  return 0;
}

进程运行及输出

root@IPS3DEV test]# ./listenerd
Parent,pid=14836
Child, pid=14837
Child sleeped5S,will fork serverprocess
Child fork end!
Child will sleep 5S,then exit
Child fork end!
Grandchild has been born,will change to serverprocess after 5S,pid=14840
------Child exit,pid=14837
___^_^ I’am serverprocess,have worked 3S
Parent Sleeped15S,begin wait
Parent wait end,count=1
___^_^ I’am serverprocess,have worked 3S
___^_^ I’am serverprocess,have worked 3S
___^_^ I’am serverprocess,have worked 3S
___^_^ I’am serverprocess,have worked 3S
___^_^ I’am serverprocess,have worked 3S
Parent Sleeped15S,begin wait
Parent wait end,count=2
___^_^ I’am serverprocess,have worked 3S
___^_^ I’am serverprocess,have worked 3S
___^_^ I’am serverprocess,have worked 3S
___^_^ I’am serverprocess,have worked 3S
___^_^ I’am serverprocess,have worked 3S
Parent Sleeped15S,begin wait
Parent wait end,count=3
___^_^ I’am serverprocess,have worked 3S
___^_^ I’am serverprocess,have worked 3S
___^_^ I’am serverprocess,have worked 3S
___^_^ I’am serverprocess,have worked 3S
___^_^ I’am serverprocess,have worked 3S
Parent Sleeped15S,begin wait
Parent wait end,count=4
—Parent will exit,pid=14836
[root@IPS3DEV test]# ___^_^ I’am serverprocess,have worked 3S
___^_^ I’am serverprocess,have worked 3S
___^_^ I’am serverprocess,have worked 3S
___^_^ I’am serverprocess,have worked 3S
___^_^ I’am serverprocess,have worked 3S

进程监控及说明

[root@IPS3DEV ~]# ps -ax|grep -e listenerd -e serverprocessd
14836 pts/0 S+ 0:00 ./listenerd #pid=14836,主进程,监听进程
14837 pts/0 S+ 0:00 ./listenerd #pid=14837,子进程1,由监听fork
[root@IPS3DEV ~]# ps -ax|grep -e listenerd -e serverprocessd
14836 pts/0 S+ 0:00 ./listenerd #pid=14836,主进程,监听进程
14837 pts/0 S+ 0:00 ./listenerd #pid=14837,子进程1,由监听fork
14840 pts/0 S+ 0:00 ./listenerd #pid=14840,子进程2,由子进程1 fork
[root@IPS3DEV ~]# ps -ax|grep -e listenerd -e serverprocessd
14836 pts/0 S+ 0:00 ./listenerd
14837 pts/0 Z+ 0:00 [listenerd] <defunct> #pid=14837,子进程1退出变成僵尸进程
14840 pts/0 S+ 0:00 serverprocessd #pid=14840,子进程2,由子进程1 fork,借尸还魂,调用exec变成serverprocess进程,注意pid号没变
[root@IPS3DEV ~]# ps -ax|grep -e listenerd -e serverprocessd
14836 pts/0 S+ 0:00 ./listenerd #pid=14836,主进程,监听进程,调用wait释放了子进程1的资源,子进程1消失了
14840 pts/0 S+ 0:00 serverprocessd

[root@IPS3DEV ~]# ps -ax|grep -e listenerd -e serverprocessd
14836 pts/0 S+ 0:00 ./listenerd
14840 pts/0 S+ 0:00 serverprocessd
[root@IPS3DEV ~]# ps -ax|grep -e listenerd -e serverprocessd
14840 pts/0 S 0:00 serverprocessd
同时间其它监控
[root@IPS3DEV ~]#
[root@IPS3DEV ~]# ps -ef|grep -e listenerd -e serverprocessd
root 14836 4936 0 10:55 pts/0 00:00:00 ./listenerd #4936的信息:root 4936 4934 0 09:04 pts/0 00:00:00 -bash
root 14837 14836 0 10:55 pts/0 00:00:00 ./listenerd #pid=14837,子进程1,由监听fork
root 14840 14837 0 10:55 pts/0 00:00:00 ./listenerd #pid=14840,子进程2,由子进程1 fork,注意父进程号14837
[root@IPS3DEV ~]# ps -ef|grep -e listenerd -e serverprocessd
root 14836 4936 0 10:55 pts/0 00:00:00 ./listenerd
root 14837 14836 0 10:55 pts/0 00:00:00 [listenerd] <defunct> #pid=14837,子进程1退出变成僵尸进程
root 14840 1 0 10:55 pts/0 00:00:00 serverprocessd #pid=14840,子进程2,由子进程1 fork,注意它的父进程由14837变成了1;1号进程就是/sbin/init
[root@IPS3DEV ~]# ps -ef|grep -e listenerd -e serverprocessd
root 14836 4936 0 10:55 pts/0 00:00:00 ./listenerd #pid=14836,主进程,监听进程,调用wait释放了子进程1的资源,子进程1消失了
root 14840 1 0 10:55 pts/0 00:00:00 serverprocessd

[root@IPS3DEV ~]# ps -ef|grep -e listenerd -e serverprocessd
root 14836 4936 0 10:55 pts/0 00:00:00 ./listenerd
root 14840 1 0 10:55 pts/0 00:00:00 serverprocessd
[root@IPS3DEV ~]# ps -ef|grep -e listenerd -e serverprocessd
root 14840 1 0 10:55 pts/0 00:00:00 serverprocessd

总结

为什么listener要fork两次?如下,假设:

1.listener只fork一个进程,这个进程调exec成为serverprocess
2.listener fork一个子进程1,子进程1再fork一个子进程2,子进程2调用exec成为serverprocess

1的局限性:listener进程fork子进程后如果不调wait,子进程终止后将成为僵尸进程,浪费系统资源;如果listener调用wait势必被阻塞,在子进程退出前,无法响应其它连接请求
2的优势:listener fork子进程1,子进程1 fork子进程2后立马退出,这时候子进程1变成僵尸进程,等listener调用Wait后正常退出,由于子进程1已经退出变僵尸进程listener进程调用Wait处理不会被阻塞,可以立即响应其它连接请求,子进程1退出变僵尸后,子进程2的父进程变成1,也可以自行终止被init回收不会变为僵尸进程浪费系统资源。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值