对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);

      ......
} 

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

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

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

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

你可能感兴趣的:(PostgreSQL)