zoukankan      html  css  js  c++  java
  • 对PostgreSQL 后台进程名称的再认知

    看 Postmaster 中如下的代码

     /* StartChildProcess -- start an auxiliary process for the postmaster                            
     *                            
     * xlop determines what kind of child will be started.    All child types                        
     * initially go to AuxiliaryProcessMain, which will handle common setup.                            
     *                            
     * Return value of StartChildProcess is subprocess' PID, or 0 if failed                            
     * to start subprocess.                            
     */                            
    static pid_t                            
    StartChildProcess(AuxProcType type)                            
    {                            
        pid_t    pid;                    
        char    *av[10];                    
        int    ac = 0;                    
        char    typebuf[32];                    
                                
        /*                        
         * Set up command-line arguments for subprocess                        
         */                        
        av[ac++] = "postgres";                        
                                
        #ifdef EXEC_BACKEND                        
            av[ac++] = "--forkboot";                    
            av[ac++] = NULL;            /* filled in by postmaster_forkexec */        
        #endif                        
                                
        snprintf(typebuf, sizeof(typebuf), "-x%d", type);                        
        av[ac++] = typebuf;                        
                                
        av[ac] = NULL;                        
        Assert(ac < lengthof(av));                        
                                
        #ifdef EXEC_BACKEND                        
            pid = postmaster_forkexec(ac, av);                    
                                
        #else    /* !EXEC_BACKEND */                    
                                
            pid = fork_process();                    
                                
            if (pid == 0)        /* child */            
            {                    
                IsUnderPostmaster = true;                /* we are a postmaster subprocess now */
                                
                /* Close the postmaster's sockets */                
                ClosePostmasterPorts(false);                
                                
                /* Lose the postmaster's on-exit routines and port connections */                
                on_exit_reset();                
                                
                /* Release postmaster's working memory context */                
                MemoryContextSwitchTo(TopMemoryContext);                
                MemoryContextDelete(PostmasterContext);                
                PostmasterContext = NULL;                
                                
                AuxiliaryProcessMain(ac, av);                
                ExitPostmaster(0);                
            }                    
        #endif   /* EXEC_BACKEND */                        
                                
        ……
        /*                        
         * in parent, successful fork                        
         */                        
        return pid;                        
    } 

    AuxiliaryProcessMain 是各个子进程的入口点。

    那么为何 ps -ef | grep post 可以看到各个子进程的不同的名字呢:

    这和 AuxiliaryProcessMain的实现有关, 其代码在  bootstrap.c 中,下面缩略一下,只考虑我关心的代码:

    /*                                    
     *     AuxiliaryProcessMain                                
     *                                    
     *     The main entry point for auxiliary processes, such as the bgwriter,                                
     *     walwriter, walreceiver, bootstrapper and the shared memory checker code.                                
     *                                    
     *     This code is here just because of historical reasons.                                
     */                                    
    void                                    
    AuxiliaryProcessMain(int argc, char *argv[])                                    
    {                                    
        ……                                
        /* If no -x argument, we are a CheckerProcess */                                
        MyAuxProcType = CheckerProcess;                                
                                        
        while ((flag = getopt(argc, argv, "B:c:d:D:Fr:x:-:")) != -1)                                
        {                                
            switch (flag)                            
            {                            
                ……                        
                case 'x':                        
                    MyAuxProcType = atoi(optarg);                    
                    break;                    
                ……                        
            }                            
        }                                
                                        
        ……                                
        /*                                
         * Identify myself via ps                                
         */                                
        if (IsUnderPostmaster)                                
        {                                
            const char *statmsg;                            
                                        
            switch (MyAuxProcType)                            
            {                            
                case StartupProcess:                        
                    statmsg = "startup process";                    
                    break;                    
                case BgWriterProcess:                        
                    statmsg = "writer process";                    
                    break;                    
                case CheckpointerProcess:                        
                    statmsg = "checkpointer process";                    
                    break;                    
                case WalWriterProcess:                        
                    statmsg = "wal writer process";                    
                    break;                    
                case WalReceiverProcess:                        
                    statmsg = "wal receiver process";                    
                    break;                    
                default:                        
                    statmsg = "??? process";                    
                    break;                    
            }                            
            init_ps_display(statmsg, "", "", "");                            
        }                                
                                        
        ……                                
        /*                                
         * XLOG operations                                
         */                                
        SetProcessingMode(NormalProcessing);                                
                                        
        switch (MyAuxProcType)                                
        {                                
            case CheckerProcess:                            
                /* don't set signals, they're useless here */                        
                CheckerModeMain();                        
                proc_exit(1);        /* should never return */                
                                        
            case BootstrapProcess:                            
                bootstrap_signals();                        
                BootStrapXLOG();                        
                BootstrapModeMain();                        
                proc_exit(1);        /* should never return */                
                                        
            case StartupProcess:                            
                /* don't set signals, startup process has its own agenda */                        
                StartupProcessMain();                        
                proc_exit(1);        /* should never return */                
                                        
            case BgWriterProcess:                            
                /* don't set signals, bgwriter has its own agenda */                        
                BackgroundWriterMain();                        
                proc_exit(1);        /* should never return */                
                                        
            case CheckpointerProcess:                            
                /* don't set signals, checkpointer has its own agenda */                        
                CheckpointerMain();                        
                proc_exit(1);        /* should never return */                
                                        
            case WalWriterProcess:                            
                /* don't set signals, walwriter has its own agenda */                        
                InitXLOGAccess();                        
                WalWriterMain();                        
                proc_exit(1);        /* should never return */                
                                        
            case WalReceiverProcess:                            
                /* don't set signals, walreceiver has its own agenda */                        
                WalReceiverMain();                        
                proc_exit(1);        /* should never return */                
                                        
            default:                            
                elog(PANIC, "unrecognized process type: %d", (int) MyAuxProcType);                        
                proc_exit(1);                        
        }                                
    }                                    

    可以看到,会根据调用的时候,所传递的flag,来设定各子进程的 显示名称:

    主要是这一段:

    switch (MyAuxProcType)
    {
      case StartupProcess:
        statmsg = "startup process";
        break;
      case BgWriterProcess:
        statmsg = "writer process";
        break;
      case CheckpointerProcess:
        statmsg = "checkpointer process";
        break;
      case WalWriterProcess:
        statmsg = "wal writer process";
        break;
      case WalReceiverProcess:
        statmsg = "wal receiver process";
        break;
      default:
        statmsg = "??? process";
        break;
    }  
    init_ps_display(statmsg, "", "", "");

    其中 ,init_ps_display 起到了关键的作用。但是具体在合适才导致 ps 时可以看到各个不同的名称,还有待进一步的观察。

    可以先作一个实验来看:

    在bootstrap 的 init_ps_dispalya(statmsg,"","",""); 完毕后,加一句:

       //added by gaojian , sleep 3 minutes
       fprintf(stderr,"sleeping...\n");
       sleep(180);

    让它停顿三秒种,此时用ps 命令看, 然后,三秒过后,再用ps 命令看,看到的结果如下:

    启动 Postgres ,看到 sleeeping...信息后,立即执行如下命令:

    [root@localhost ~]# ps -ef|grep post
    root 2928 2906 0 13:42 pts/1 00:00:00 grep post
    [root@localhost ~]# ps -ef|grep post
    root 2953 2932 0 13:42 pts/2 00:00:00 su - postgres
    postgres 2954 2953 0 13:42 pts/2 00:00:00 -bash
    postgres 2989 2954 0 13:42 pts/2 00:00:00 /usr/local/pgsql/bin/postgres -D /usr/local/pgsql/data
    postgres 2990 2989 0 13:42 pts/2 00:00:00 postgres: startup process
    root 2992 2906 0 13:42 pts/1 00:00:00 grep post

    可以看到有一个叫 postgres: startup process 的子进程出现。后面这个进程不见了。这是很有趣的。

    然后等过了几秒钟,再用ps 命令来看:

    [root@localhost ~]# ps -ef|grep post
    root 2953 2932 0 13:42 pts/2 00:00:00 su - postgres
    postgres 2954 2953 0 13:42 pts/2 00:00:00 -bash
    postgres 2989 2954 0 13:42 pts/2 00:00:00 /usr/local/pgsql/bin/postgres -D /usr/local/pgsql/data
    postgres 3000 2989 0 13:45 ? 00:00:00 postgres: checkpointer process
    postgres 3001 2989 0 13:45 ? 00:00:00 postgres: writer process
    postgres 3002 2989 0 13:45 ? 00:00:00 postgres: wal writer process
    postgres 3003 2989 0 13:45 ? 00:00:00 postgres: autovacuum launcher process
    postgres 3004 2989 0 13:45 ? 00:00:00 postgres: stats collector process
    root 3018 2906 0 13:53 pts/1 00:00:00 grep post

    --------------------------------------------------------------------------------------------------

    对此暂时先放一放。我想,更重要的是如下这样的代码:

    switch (MyAuxProcType)
    {
      ......

      case BgWriterProcess:
      /* don't set signals, bgwriter has its own agenda */
      BackgroundWriterMain();
      proc_exit(1);

          ......
    } 

    可以打个比方: 一个父亲有几个儿子,有一天他问几个儿子,你们长大想做什么呢?

    老大说,我想当将军,保家卫国。老二说,我想当医生,救死扶伤。 老三说,我想当教师,桃李满天下。

    于是父亲说,好啊,他给每个儿子作了一定帽子,写着 将军、医生、教师。在人们的嘲笑声中,三个儿子一个去了部队,一个去了医学院,一个去了师范学院。走上了各自不同的道路,后来真的成就了各自的梦想。

    这就是不同的子进程拥有不同的名称的类比了。

  • 相关阅读:
    Windows Phone 7(WP7)开发 自订磁贴(深度链接)
    Windows Phone 7(WP7)开发 在ViewModel中使用NavigationService
    Windows Phone 7(WP7)开发 显示长文本(高度大于2000px)
    类属性生成器(小程序)
    Windows Phone 7(WP7)开发 ListBox的分页加载
    Windows Phone 7(WP7)开发工具 查看独立存储空间中数据库内容
    Windows Phone 7(WP7)开发 获取网络状态
    发布一个XNA写的小雷电源码
    用python来个百度关键词刷排名脚本
    win7下 VirtualBox虚拟机开机后台自启动
  • 原文地址:https://www.cnblogs.com/gaojian/p/2737068.html
Copyright © 2011-2022 走看看