【问题标题】:C extracting info from file in /procC从/ proc中的文件中提取信息
【发布时间】:2018-02-14 02:37:52
【问题描述】:

我正在尝试从 C 中的 /proc/pid/cmdline 获取包含 PID 可执行文件的路径。手册页指出:

"命令行参数出现 在此文件中作为一组由空字节分隔的字符串 ('\0'),在最后一个字符串之后有一个空字节。”

我的想法(伪代码):

int main(int argc, char** argv){
    // Assume file_path has been initialized
    char executable_path[1000];
    FILE* file = fopen(file_path, "r");
    if(f != NULL){

        fscanf("%s", executable_path);
    }
    return 0;
}

因为我只想要这个文件中的第一个字符串(因为那是包含可执行文件的路径)并且我确定第一个字符串后面有一个 '\0',所以 fscanf 是正确的函数吗?它会检测到第一个'\0',然后将整个字符串存储到可执行文件路径数组中的第一个'\0'吗? (注意:我不需要提取任何其他字符串)。

谢谢!

【问题讨论】:

  • 你的问题包含代码你试过了吗?结果如何?我的预感(我没有检查文档)是 scanf 不会在 %s 的 \0 上终止。如果我没记错的话,它只会在空白处终止。
  • 您可以轻松地将this answer 中的get_argv() 函数(读取为/proc/self/cmdline)改为读取/proc/PID/cmdline。但是,如果您只对可执行文件感兴趣,请在 /proc/PID/exe 上使用 readlink()
  • @NominalAnimal 我不允许使用 readlink() 或任何系统调用。如果路径后面有参数,我将如何只获取路径?
  • @Bill: readlink() 不是系统调用,它是标准的 POSIX.1 C 函数,用于获取符号链接指向的路径。

标签: c file scanf pid


【解决方案1】:

不要为此使用fscanf,如果命令名称中有空格,则不会 获取全名。

您可以使用fgets,它会在'\0' 处停止读取。我现在有一个 以 pid 10979 运行的进程:

FILE *fp = fopen("/proc/10979/cmdline", "r");

char line[1024];
fgets(line, sizeof line, fp);

puts(line);

fclose(fp);

打印出来:

/usr/bin/gvim

【讨论】:

  • 我把你的路径和一些参数放在我为测试而创建的命令行文件中:“/usr/bin/gvim arg1 arg2 arg3”。但是,代码会打印整个字符串,而不是打印“/usr/bin/gvim”。
  • @Bill 它将仅显示执行的内容...因此,如果您执行为 gvim 提供完整路径,它将显示完整路径...在有问题的 proc 上发布目录列表具有指导意义用于查看除 cmdline 以外的其他属性的终端...根据 ls -la /proc/10979 ... 在这里您将看到 ls -la /proc/10979/exe ... 除非有获取完整路径的快捷方式到 cmd 我会说你可以通过首先获取 pid 的 PATH 然后发现 cmd 位置来解决它......更新检查这个 readlink -f /proc/15870/exe 它给你完整的路径
  • @ScottStensland fread 也会检测到第一个空终止符吗?
  • @Bill 可能是的,我还没有测试过。但是你可以测试一下。 --- 我把你的路径和一些参数放在我创建的用于测试的 cmdline 文件中你把它放在哪里了?请注意,这仅适用于 /proc/<pid>/cmdline 使用 '\0' 作为分隔符。
【解决方案2】:
  1. /proc/PID/cmdline 包含用于执行程序的命令行(除非由程序本身修改)。它不包含可执行文件的路径;它只包含用于执行它的路径。

    例如,如果你执行foo bar baz,它的/proc/PID/cmdline将包含foo\0bar\0baz\0

    您可以使用例如getdelim()'\0' 作为分隔符来读取可执行文件的路径。
     

  2. 要获取可执行文件的实际路径,请检查/proc/PID/exe 符号链接。它总是指向可执行文件。

    要读取符号链接,可以使用 C 库提供的 POSIX.1 readlink() 函数。

    我有一个示例实现in this answer

    在 Linux 中,存在一个内核“错误”:如果可执行文件在文件系统层次结构中非常深,则对 /proc/PID/exe 伪符号链接的 readlink() 调用会失败并出现 ENAMETOOLONG 错误。
     

  3. 可执行文件的路径也可以从/proc/PID/stat中提取。

    可执行文件的名称在该伪文件中的第一个 ( 和最后一个 ) 之间。

    您可以使用getline() 读取整行(实际上是整个伪文件,因为它只在末尾包含一个换行符),strchr() 可以找到其中的第一个 (strrchr() 可以找到最后)
     

如果您想尝试有趣/讨厌的可执行文件名称,只需运行例如

ln -s /bin/cat $'foo)\nbar\n('
$'./foo)\nbar\n(' /proc/self/stat
rm $'foo)\nbar\n('

在 Bash 中,检查 /proc/self/stat 的内容。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-19
    • 2015-09-08
    • 2017-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-05
    相关资源
    最近更新 更多