4

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

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

我的应用程序 1 2

然后 cat myapp 的 cmdline 我会看到类似 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")

不做任何其他事情所以...

4

3 回答 3

8

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

于 2011-03-16T13:44:42.913 回答
7

所有命令行参数(将作为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编辑cmdline它们时它们都“卡”在一起(cat忽略无效的 NULL 字符)以及为什么您cout在第一个命令行参数(进程名称)之后停止,因为它认为进程名称是一个以 null 结尾的字符串并且那时停止寻找更多角色。

处理命令行参数

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

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

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

于 2009-09-10T17:35:42.833 回答
0

|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);
于 2021-08-24T09:54:21.173 回答