设置可执行程序的名称

argc:命令行参数的个数。

argv:是个数组,每个数组元素都是指向一个字符串的 char *,里边存储的内容是所有命令行参数。

argv 内存之后接着就是连续的环境变量参数信息内存,里边存储的内容是可执行程序执行时有关的所有环境变量参数信息,可以通过一个全局的 environchar **)访问,environ 内存和 argv 内存是紧紧挨着的。

在这里插入图片描述

修改可执行程序名称的实现思路:

  1. 重新分配一块内存,用来保存 environ 中的内容;
  2. 修改 argv[0] 所指向的内存。

在这里插入图片描述

在这里插入图片描述

ngx_setproctitle.cxx:

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

#include "ngx_global.h"

// 设置可执行程序的标题:分配内存并把环境变量拷贝到新内存中来
void ngx_init_setproctitle()
{
    int i;

    // 统计环境变量所占的空间大小,注意判断方法是environ[i]是否为空作为环境变量结束标记
    for (i = 0; environ[i]; i++)
    {
        g_environlen += strlen(environ[i]) + 1; // +1是因为末尾有\0,是占实际内存位置的,要算进来
    }
    
    gp_envmem = new char[g_environlen]; 
    memset(gp_envmem, 0, g_environlen); // 内存要清空,防止出现问题

    char* ptmp = gp_envmem;

    // 把原来的内存内容搬到新地方来
    for (i = 0; environ[i]; i++) 
    {
        size_t size = strlen(environ[i]) + 1 ; // 不要忘记+1,否则内存全乱套了,因为strlen是不包括字符串末尾的\0的
        strcpy(ptmp, environ[i]); // 把原环境变量内容拷贝到新内存中
        environ[i] = ptmp; // 然后还要让新环境变量指向这段新内存
        ptmp += size;
    }

    return;
}

// 设置可执行程序的标题:修改argv[0]所指向的内存
void ngx_setproctitle(const char* title)
{
    // 这里假设所有的命令行参数我们都不需要了,可以被随意覆盖
    // 这里假设新标题所占的空间大小不会超过原argv和environ的内存总和

    // 计算新标题的长度
    size_t ititlelen = strlen(title); 

    // 计算原始的argv那块内存的总长度(包括各种参数)
    size_t e_environlen = 0;
    for (int i = 0; g_os_argv[i]; i++)
    {
        e_environlen += strlen(g_os_argv[i]) + 1;
    }

    size_t esy = e_environlen + g_environlen; // 原argv和environ的内存总和

    if (esy <= ititlelen) // 注意字符串末尾多了个\0,所以这里的判断是<=,也就是说==都算存不下
    {
        return;
    }

    // 空间够保存新标题的,继续走下来

    // 设置后续的命令行参数为空,表示argv[]中只有一个元素了,这是个好习惯,防止后续argv被滥用,因为很多判断是用argv[]==NULL来做结束标记判断的
    g_os_argv[1] = NULL;

    // 把新标题弄进来,注意原来的命令行参数都会被覆盖掉,不要再使用这些命令行参数,而且g_os_argv[1]已经被设置为NULL了
    char* ptmp = g_os_argv[0]; // 让ptmp指向g_os_argv所指向的内存
    strcpy(ptmp, title);
    ptmp += ititlelen; // 跳过标题

    // 把剩余的原argv和environ所占的内存全部清0,否则在ps命令的cmd列可能会出现一些没有被覆盖的残余内容
    size_t cha = esy - ititlelen; // 内存总和减去标题字符串长度(不含字符串末尾的\0)剩余的大小就是要memset的
    memset(ptmp, 0, cha);

    return;
}

nginx.cxx:

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

#include "ngx_c_conf.h" // 和配置文件处理有关的类,名字带c_表示和类有关
#include "ngx_signal.h"
#include "ngx_func.h" // 各种函数声明

// 和设置标题有关的全局量
char** g_os_argv; // 原始命令行参数数组,在main中会被赋值
char* gp_envmem = NULL; // 指向手动分配的env环境变量的内存
int g_environlen = 0; // 环境变量所占内存大小

int main(int argc, char* const* argv)
{
    g_os_argv = (char **) argv;

    ngx_init_setproctitle(); // 把环境变量搬家
    
    // 我们在main中,先把配置读出来,供后续使用 
    CConfig* p_config = CConfig::GetInstance(); // 单例类
    
    if (p_config->Load("nginx.conf") == false) // 把配置文件内容载入到内存
    {
        printf("配置文件载入失败,退出!\n");
        exit(1);
    }

    // 前提是保证所有命令行参数我们都不用了
    ngx_setproctitle("nginx: master process");
    
    // 获取配置文件信息    
    int port = p_config->GetIntDefault("ListenPort", 0); // 0是缺省值
    printf("port=%d\n", port);
    
    const char* pDBInfo = p_config->GetString("DBInfo");
    if (pDBInfo != NULL)
    {
        printf("DBInfo=%s\n", pDBInfo);
    }

    for (;;)
    {
        sleep(1);
        printf("休息1秒\n");
    }

    // 对于因为设置可执行程序标题导致的环境变量分配的内存,我们应该释放
    if (gp_envmem)
    {
        delete[] gp_envmem;
        gp_envmem = NULL;
    }
    
    printf("程序退出,再见!\n");
    
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值