【问题标题】:parsing proc/pid/cmdline to get function parameters解析proc/pid/cmdline获取函数参数
【发布时间】:2021-08-24 17:54:21
【问题描述】:

我正在尝试通过使用 cmdline 中的数据来提取调用应用程序的参数。

如果我像这样启动应用程序实例:

我的应用程序 1 2

然后 cat myapp 的命令行,我会看到类似 myapp12 的内容。

我需要提取这些值,我使用这段代码来完成它


pid_t proc_id = getpid();

sprintf(buf,"/proc/%i/cmdline",proc_id);

FILE * pFile;
pFile = fopen (buf,"r");
if (pFile!=NULL)
{
    fread(buf,100,100,pFile);
    cout << "PID " << proc_id << endl;
    string str = buf;
    cout << buf << endl;
    size_t found=str.find_last_of("/\\");
    cout << " file: " << str.substr(found+1) << endl;

    fclose (pFile);
}

但我得到的只是应用名称,没有参数......


从答案复制的更新:

好吧,我现在的问题似乎是如何读取 cmdline 文件而不让它在第一个 NULL 字符处停止...

fopen(cmdline, "rb")

什么都不做,所以...

【问题讨论】:

  • 今天打了这个之后,我想说明我必须使用:fread(buf,1,100,pFile); (size=1, count=buffer length)。

标签: c++ linux procfs


【解决方案1】:

/usr/bin/strings /proc/1337/cmdline 通常为我做这项工作。

【讨论】:

    【解决方案2】:

    所有命令行参数(将通过 argv[] 数组出现)实际上是 /proc/XXX/cmdline 中的空分隔字符串。

    abatkin@penguin:~> hexdump -C /proc/28460/cmdline
    00000000  70 65 72 6c 00 2d 65 00  31 20 77 68 69 6c 65 20  |perl.-e.1 while |
    00000010  74 72 75 65 00                                    |true.|
    

    这解释了为什么当您 cat'ed cmdline 他们都“卡”在一起(cat 忽略了无效的 NULL 字符)以及为什么您的 cout 在第一个命令行参数(进程名称)之后停止) 因为它认为进程名称是一个以 null 结尾的字符串,并在那时停止寻找更多字符。

    处理命令行参数

    要处理命令行参数,您有几个选项。如果您只想将整个命令行作为一个巨大的字符串,请从 0 循环到 (numRead - 2)(其中 numRead 是读取的字符数)并将任何 NULL 字节 (curByte == 0) 替换为空格。然后确保将最后一个字符也设置为 NULL 字节(以防由于固定大小的缓冲区而被截断)。

    如果您想要一个包含所有参数的数组,则需要更有创意。一种选择是从 0 循环到 (numRead - 1) 并且可以找到您找到的所有 NULL 字节。然后分配该长度的char* 数组。然后通过命令行循环返回,将每个字符串的开头(即数组中的第一个字节,加上 NULL 字节后面的每个字节)设置为 char* 的数组的连续元素。

    只要知道,由于您读取的是固定大小的缓冲区,超出该缓冲区的任何内容都会被截断。所以请记住,无论您做什么,您可能都需要手动确保最后一个字符串的结尾以 NULL 结尾,否则大多数字符串处理函数将不知道字符串在哪里结束,并且会一直持续下去。

    【讨论】:

    • 我已经看到了 ;) read 或 fread 的问题是它们在第一个 NULL 处停止并且没有得到其余的参数......我该如何解决这个问题?干杯
    • readfread 不要停止,停止的是 cout(或者可能是缓冲区中的 string 构造,不确定)。检查您的fread 的返回值,您就会明白我的意思。
    • 亚当,感谢您的帮助。我得了程序员综合症,想破坏转义键;)。你的建议是正确的。再次感谢;)
    【解决方案3】:

    |path| 中提供了许多文件大小不正确(proc 文件等)。因此,文件是按顺序读取的,而不是一次性读取。

    std::string cmdline;
    char buf[1024];
    size_t len;
    FILE *fp = fopen("/proc/self/cmdline", "rb");
    if (fp) {                       
        while ((len = fread(buf, 1, sizeof(buf), fp)) > 0) {
            cmdline.append(buf, len); // note: `len` here is very important
        }
    }
    

    然后,您将获得整个命令行以及参数。但是,当您尝试打印它时,您只能获取应用程序名称或文件路径而没有参数的原因是您拥有的命令行用'\0' 分隔,类似于"./exefile_name\0-param1=p1\0-param2=p2"。所以你只能得到第一个'\0'前面的部分,因为机器假设字符串在那个地方结束。您还需要先用'\0' 对其进行标记,然后尝试打印或使用它。

    std::stringstream tokens(cmdline);
    std::string tmp;
    while (getline(tokens, tmp, '\0')){
        std::cout << tmp << std::endl;
    }
    fclose(fp);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-02
      • 2010-09-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多