我正在尝试使用cmdline中的数据提取调用应用程序的参数。
如果我启动这样的应用程序实例:
myapp 1 2
然后捕捉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")
没有做任何其他事情......
答案 0 :(得分:9)
/usr/bin/strings /proc/1337/cmdline
通常为我做这份工作。
答案 1 :(得分: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
'ed cmdline
时,他们全都“卡在一起”(cat
忽略了无效的NULL字符)以及为什么cout
在(numRead - 2)
之后停止了第一个命令行参数(进程名称),因为它认为进程名称是以空字符结尾的字符串,并且在此时停止查找更多字符。
处理命令行参数
要处理命令行参数,您有几个选项。如果您只想将整个命令行作为一个巨大的字符串,则从0循环到numRead
(其中(curByte == 0)
是读取的字符数)并用空格替换任何NULL字节(numRead - 1)
。然后确保将最后一个字符设置为NULL字节(如果由于固定大小的缓冲区而导致事物被截断)。
如果你想要一个包含所有参数的数组,你需要更有创意。一种选择是从0循环到char*
,并且可以找到所有的NULL字节。然后分配一个长度为char*
的数组。然后循环返回命令行,将每个字符串的开头(即数组中的第一个字节,加上NULL字节后的每个字节)设置为{{1}}数组的连续元素。
只要知道,因为您读取固定大小的缓冲区,超出该缓冲区的任何内容都将被截断。所以请记住,无论你做什么,你可能需要手动确保最后一个字符串的结尾最终被NULL终止,否则大多数字符串处理函数将不知道字符串结束的位置,并将继续永远。