|
看 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...信息后,立即执行如下命令:
[iyunv@localhost ~]# ps -ef|grep post
root 2928 2906 0 13:42 pts/1 00:00:00 grep post
[iyunv@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 命令来看:
[iyunv@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);
......
}
可以打个比方: 一个父亲有几个儿子,有一天他问几个儿子,你们长大想做什么呢?
老大说,我想当将军,保家卫国。老二说,我想当医生,救死扶伤。 老三说,我想当教师,桃李满天下。
于是父亲说,好啊,他给每个儿子作了一定帽子,写着 将军、医生、教师。在人们的嘲笑声中,三个儿子一个去了部队,一个去了医学院,一个去了师范学院。走上了各自不同的道路,后来真的成就了各自的梦想。
这就是不同的子进程拥有不同的名称的类比了。 |
|
|