【问题标题】:Why does it return a null pointer when I try to visit the status file of a task?为什么当我尝试访问任务的状态文件时它返回一个空指针?
【发布时间】:2021-03-15 15:15:11
【问题描述】:

我正在使用 C 语言进行编程以获取 Ubuntu(Ubuntu 20.04 和 gcc 9.3.0)上的进程和任务的一些信息。
我用下面的代码扫描了一个已知pid的进程的任务目录:

char root_path[20] = "/proc/";
strcat(root_path, name_list[i]->d_name);
strcat(root_path, "/task");
tnum = scandir(root_path, &task_list, filter, alphasort);

其中name_list[i]->d_name 是进程的pid,形式为char*。 然后我使用 task_list 中的结果来访问这些任务的状态:

char path1[20] = "/proc/";
strcat(path1, task_list[j]->d_name);
strcat(path1, "/status");
FILE *fp = fopen(path1, "r");

这只是简单的代码。我遇到的问题是,虽然大多数任务都可以正常访问,但存在一些任务 id 使 fopen 返回一个空指针 fp。我使用 assert 语句来检测它。但是当我使用cat /proc/tid/status检查文件时,它就在那里并且可以正常访问。
当我把目录改成/proc/pid/task/tid/status后,问题依旧存在。
我想知道为什么我不能访问某个任务文件,它与其他状态文件似乎没有区别。返回空指针的任务的tid是固定的,直到我再次编译源代码。

【问题讨论】:

  • 如果fopen 返回NULL,使用perror 打印一条错误消息,说明为什么调用失败。
  • 您可以将strcat(); strcat();替换为snprintf();
  • 您可能需要检查errno 值来查找错误原因。您可以通过if (fp == NULL) printf("Error: %s\n", strerror(errno)); 进行操作。确保 #include <string.h> 代表 strerror<errno.h> 代表 errno 变量(它实际上是一个宏)。
  • “我使用 assert 语句来检测。”请注意,assert 应该用于调试,而不是用于错误检测。
  • @IanAbbott:当你不知道为什么甚至在哪里时,它肯定比“分段错误”要好。

标签: c ubuntu process operating-system


【解决方案1】:

char path1[20] 太短。使用这些字符串,对于最坏情况大小的 PID,您至少需要 char path1[24]。由于运行堆栈数组的末尾,您的程序未定义。

一旦它不是未定义的,如果它一直发生,请致电perror(path1) 以打印出您尝试访问的路径和错误消息。

提示:sizeof("string") 可用于数组声明,因此您可以编写 char path1[sizeof("/proc/" + 10 + sizeof("/status")] 并让编译器为您计算。

【讨论】:

  • pids 在 linux 上最多为 5 位数字,因此这些名称最长可能是 19 个字符(包括终止的 NUL)。
  • @ChrisDodd:我不太确定。 stackoverflow.com/a/6294196/14768 表示今天可以设置为 7 位;因此已经需要 21 个。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-20
  • 2020-05-05
  • 2021-01-05
相关资源
最近更新 更多