对PostgreSQL 后台进程名称的再认知

本文涉及的产品
云原生数据库 PolarDB MySQL 版,通用型 2核8GB 50GB
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
简介:

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

      ......
} 

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

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

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

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







本文转自健哥的数据花园博客园博客,原文链接:http://www.cnblogs.com/gaojian/archive/2012/10/24/2737068.html,如需转载请自行联系原作者

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍如何基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
Unix Shell Linux
Linux 终端和进程的关系,以及在终端前后台切换进程
Linux 终端和进程的关系,以及在终端前后台切换进程
350 1
|
Linux Shell
Linux 进程的前台/后台切换
当你用shell启动一个程序时,往往他是在前台工作的。程序会一直占用终端命令行,例如你在前台解压的时候必须等着,期间干不了别的事(除非另开一个终端)。 例如经常用连接到远程服务器执行脚本的时候,如果本地网络中断后,这个时候前台进程就结束了,比较的懊恼,必须重新执行。
381 6
|
iOS开发
iOS 逆向编程(十三)PS命令获取进程PID与名称(Process Status)
iOS 逆向编程(十三)PS命令获取进程PID与名称(Process Status)
396 0
|
3月前
|
监控 编译器 Python
如何利用Python杀进程并保持驻留后台检测
本教程介绍如何使用Python编写进程监控与杀进程脚本,结合psutil库实现后台驻留、定时检测并强制终止指定进程。内容涵盖基础杀进程、多进程处理、自动退出机制、管理员权限启动及图形界面设计,并提供将脚本打包为exe的方法,适用于需持续清理顽固进程的场景。
|
7月前
|
Linux Shell
Linux 进程前台后台切换与作业控制
进程前台/后台切换及作业控制简介: 在 Shell 中,启动的程序默认为前台进程,会占用终端直到执行完毕。例如,执行 `./shella.sh` 时,终端会被占用。为避免不便,可将命令放到后台运行,如 `./shella.sh &`,此时终端命令行立即返回,可继续输入其他命令。 常用作业控制命令: - `fg %1`:将后台作业切换到前台。 - `Ctrl + Z`:暂停前台作业并放到后台。 - `bg %1`:让暂停的后台作业继续执行。 - `kill %1`:终止后台作业。 优先级调整:
418 5
|
安全 API C#
C# 如何让程序后台进程不被Windows任务管理器强制结束
C# 如何让程序后台进程不被Windows任务管理器强制结束
449 0
|
Android开发 开发者 Kotlin
Android 多进程情况下判断应用是否处于前台或者后台
本文介绍在多进程环境下判断Android应用前后台状态的方法。通过`ActivityManager`和服务信息`RunningAppProcessInfo`可有效检测应用状态,优化资源使用。提供Kotlin代码示例,帮助开发者轻松集成。
865 8
|
存储 缓存 NoSQL
Redis性能优化问题之优化 Redis fork 耗时严重的问题,如何解决
Redis性能优化问题之优化 Redis fork 耗时严重的问题,如何解决
|
应用服务中间件 nginx
cmd 杀掉 nginx后台进程 命令杀掉nginx后台 nginx 常用命令
cmd 杀掉 nginx后台进程 命令杀掉nginx后台 nginx 常用命令
1639 0
|
监控 网络协议 关系型数据库
如何在Linux中查看正在运行的进程以及过滤特定端口和进程名称
如何在Linux中查看正在运行的进程以及过滤特定端口和进程名称
985 0

热门文章

最新文章

推荐镜像

更多