设置可执行程序的名称

2023-11-05

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;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

设置可执行程序的名称 的相关文章

  • 如何像C99一样使用make和编译?

    我正在尝试使用 Makefile 编译 Linux 内核模块 obj m main o all make C lib modules shell uname r build M PWD modules clean make C lib mo
  • 在 Bash 中使用“$RANDOM”生成随机字符串

    我正在尝试使用 Bash 变量 RANDOM创建一个由包含整数和字母数字的变量中的 8 个字符组成的随机字符串 例如 var abcd1234ABCD 我怎样才能做到这一点 使用参数扩展 chars 是可能的字符数 是模运算符 chars
  • 如何在Linux中获取带有图标的活动应用程序

    我想找到一种方法获取活动应用程序的列表及其名称和图标 实际上 我正在使用此命令来获取所有活动进程 wmctrl lp 示例输出 0x03800002 0 3293 user notebook XdndCollectionWindowImp
  • 64位版本的adb和fastboot?

    我在 Debian 7 3 x64 已完全修补 上发现了以下错误 我很确定这是因为adb即使在其 SDK 工具的 64 位发行版中也是 32 位 which adb opt android sdk platform tools adb op
  • copy_from_user() 错误:目标大小太小

    我正在为内核模块编写 ioctl 处理程序 我想从用户空间复制数据 当我编译禁用优化的代码时 O0 gflags 编译器返回以下错误 include linux thread info h 136 17 error call to bad
  • 当下一条(跳过)指令是变量定义时,Shellcode 中的 JMP 意外行为

    Purpose 我试图利用 x86 64 中的 RIP 模式 尽管程序集本身按预期执行 但 shellcode 却没有 问题 简而言之 我尝试过的是这样的 jmp l1 str1 db some string l1 other code l
  • Powershell从Linux客户端连接到Windows远程

    我正在尝试从我的 Linux 工作站远程连接到 Windows 计算机 我在 Arch Linux 工作站上安装了 powershell 目前正在尝试连接到主机 在主机上 Enable PSRemoting 然后允许所有主机Set Item
  • 是否有一种异步信号安全的方式来读取 Linux 上的目录列表?

    SUSv4 http pubs opengroup org onlinepubs 9699919799 functions V2 chap02 html tag 15 04 03 03未在其异步信号安全函数列表中列出 opendir rea
  • 您会为 Linux 推荐哪种甘特图/项目管理工具? [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我需要一个可在 Linux 中运行并具有甘特图的项目管理工具 它不一定是免费的 只是不贵 我不在乎它如何存储我提供的信息 只要我可以访问它即可 我一定
  • 使用 SED 将单词的第一个字母大写

    如何将单词的第一个字母替换为大写字母 例如 Trouble me Gold rush brides into Trouble Me Gold Rush Brides 这一行应该做到这一点 sed e s b u 1 g
  • 在ubuntu中使用gcc生成特定频率的声音?

    如何在 C C 中生成特定频率的声音 我运行 Ubuntu 10 04 并使用 gcc 有一个void sound int frequency Windows 版 TurboC 上的功能 gcc 有等效的吗 下面是利用 PortAudio
  • 为 Python 终端提供持久的历史记录

    有没有办法告诉交互式 Python shell 保留会话之间执行命令的历史记录 当会话运行时 在执行命令后 我可以向上箭头并访问所述命令 我只是想知道是否有某种方法可以保存一定数量的这些命令 直到下次使用 Python shell 时 这将
  • 如何为自定义应用程序选择静态端口号?

    我们有一个自定义应用程序 需要在其自己的端口号上处理请求 我们真的不在乎这个数字是多少 尽管我们在决定后会坚持使用该端口 如何选择最不可能与用户系统上运行的其他应用程序或服务发生冲突的数字 我们应该遵循什么规则或标准吗 澄清 一旦我们选择了
  • 在 Linux 上,当打开套接字时,Java 会发出反向 DNS 查找。为什么,我该如何阻止它?

    我们在 Linux 上遇到了一种非常奇怪的行为 Java DNS 查找 更新 Mac OS X 上也会发生 我错了 我们将Google公共DNS服务器8 8 8 8设置为JVM DNS服务器 然而 系统 etc resolv conf 服务
  • Tensorflow推荐的系统规格?

    我开始在我的 RHEL 6 5 机器上安装 Tensorflow 但事实证明 Tensorflow 需要 glibc gt 2 17 而 rhel 6 5 上默认的 glibc 是 2 12 我想知道是否有人可以帮助我了解张量流的最低 推荐
  • rusage 进程/线程的 Cpu 时间不可能

    我正在计算进程 线程正在使用的 cpu 时间之间的增量 以及某个函数的调用之间的增量 我得到了进程 cpu 时间不可能的值 有时下一次调用会返回较小的 cpu 时间 这是不可能的 这是我用来计算CPU时间的代码 u64 CpuTime ca
  • 如何将域名附加到我的服务器? [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我有一个小问题 查看了这里和其他论坛 但找不到解决方案 我的网站位于 my domain com 网站位于共享主机上 在我的域名注册中 我添加了当我为
  • __NR_gettid 和 SYS_gettid 之间的区别

    我只是在寻找在 Linux 中获取唯一线程 ID 的方法 我发现的方法是将两个参数中的任何一个作为参数进行系统调用 NR gettid OR SYS gettid 有人能解释一下它们之间有何不同吗 Nothing in
  • 无法通过 SSH 连接到 Google 计算引擎

    我在一个新项目中设置了一个新的 Google Compute Engine 实例 我启动实例并使用命令gcloud init连接到我的项目 然后我使用命令sudo gcloud compute ssh instance 1 它引导我完成 S
  • 是否可以在 python shebang 中包含命令行选项?

    我的 python 脚本顶部有规范的 shebang usr bin env python 但是 当我运行脚本时 我仍然经常希望将未缓冲的输出导出到日志文件 因此我最终调用 python u myscript py gt myscript

随机推荐