第二次读取 Proc-FS 文件时使用 lseek() 是否安全

发布于 2024-10-13 19:15:45 字数 846 浏览 9 评论 0原文

  1. 使用 lseek(fd,0) 然后使用 read(fd,buf) 来读取 /proc/stat 文件而不是重新打开它是否安全下次获取该文件的更新内容?
  2. 打开此文件后 mmap() 调用到底会做什么(见下文)?

我遇到的问题是 top 报告的 CPU 使用率太低(软件中断为 10% 与 100%)。 strace 工具指示 top 不会重新打开此文件,而是查找开头并再次读取它。不知何故,下次从此文件中读取的内容与我单独为 /proc/stat 文件运行 cat 时得到的内容不匹配。

另外,如果我同时在循环中运行 top 和 cat /proc/stat ,那么 top 开始报告正确的 CPU 使用情况。

我发现的另一个区别是 top 在打开 /proc/stat 文件后立即使用 mmap() 调用,而 cat< /code> 不这样做。我不确定这是否也与我的问题有关(因为此处的 filesdes=-1):

mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f7b37649000

我正在使用带有 2.6.32-27-server 映像的 Ubuntu 10.04.1 桌面版。 CPU是Intel Q6600。

  1. Is it safe to use lseek(fd,0) and then read(fd,buf) for /proc/stat file instead of reopening it to get updated contents of this file next time?
  2. And what does the mmap() call after opening this file really do (see below)?

The problem I am encountering is that top reports way too low CPU usage (10% vs 100% for software interrupts). The strace tool indicates that top does not reopen this file but instead lseeks to beginning and reads it once again. And somehow the contents which are read from this file next time does not match with what I would get when I run cat for /proc/stat file alone.

Also If I run top and cat /proc/stat in a loop at the same time then top starts to report correct CPU-Usage.

One more difference I spot is that top uses mmap() call right after opening the /proc/stat file, while cat does not do that. I am not sure if this also could be related with my problem (because filesdes=-1 here):

mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f7b37649000

I am using Ubuntu 10.04.1 Desktop edition with 2.6.32-27-server image. The CPU is Intel Q6600.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

浮光之海 2024-10-20 19:15:45

你问的问题非常有趣......我开始检查我的机器,但我没有看到 cat /proc/stat 和执行顶部之间的差异。不管怎样,我在工作,并没有完全“自由”地进行测试。

您描述的“刷新”打开的文件以读取新数据的方式是正确的......在 [f|l]seek() 调用到文件末尾然后调用文件开头的情况下,将更新 EOF 和新数据将读取数据。

我不认为 mmap() 调用会导致您提到的问题,它可以使读取速度更快,但没有别的(我不是 100% 确定)。

我建议你用 C 语言制作一个小应用程序,打开 /proc/stat,阅读它,查找它并再次阅读它以查看它是如何更新的,如果你要做一些压力测试也可能很有用。

现在,回答您真正的问题:

  1. 是的,据我所知,这是肯定的,因为您将“等待”文件上的新数据,这应该比一直打开和关闭文件更好。

  2. 它将文件映射到进程地址空间,这里有一些信息和示例:

http://www.gnu.org/s/libc/manual/html_node/Memory_002dmapped-I_002fO.html< /a>
http://www.linuxquestions.org/questions/programming-9/mmap-tutorial-cc-511265/

It's very interesting what you ask... I start checking in my machine but I don't see differences between cat /proc/stat and execute top. Anyway, I'm at work and I'm not totally 'free' to make tests.

The way you describe to 'refresh' the opened file to read new data is correct... in case of a [f|l]seek() call to the end and then to the beginning of the file will update the EOF and new data will be read.

I don't think that the mmap() call will cause the problem you mentioned, it could make the read faster, but nothing else (I'm not 100% sure).

I would suggest you to make a small app in C that open /proc/stat, read it, seek it and read it again to see how it's updated, also if you have some stress test to do could be useful.

Now, answering your real questions:

  1. Yes, AFAIK it's sure because you will be 'waiting' for new data on the file and it should be better than open and close the file all the time.

  2. It maps a file to the process address space, here are some info and examples:

http://www.gnu.org/s/libc/manual/html_node/Memory_002dmapped-I_002fO.html
http://www.linuxquestions.org/questions/programming-9/mmap-tutorial-c-c-511265/

雾里花 2024-10-20 19:15:45

正如此问题的答案中所解释的,不可能从/proc<内存映射文件/em> 虚拟文件系统。您会从 mmap() 收到 EIO 错误。
避免系统性打开/读取/关闭的最佳方法是简单地打开文件一次,然后再次查找开头来读取其内容。返回更新的数据。
下面是一个每秒读取 /proc/meminfo 的示例程序:

#include <sys/types.h>
#include <errno.h>
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#define MEMINFO_FNAME "/proc/meminfo"

int read_file(int fd)
{
  int rc;
  char buffer[512];
  off_t off;

  off = lseek(fd, 0, SEEK_SET);
  if (off == (off_t)-1) {
    fprintf(stderr, "lseek(%s): '%m' (%d)\n", MEMINFO_FNAME, errno);
    return -1;
  }

  do {

    rc = read(fd, buffer, sizeof(buffer));
    if (rc > 0) {
      buffer[rc] = '\0';
      printf("%s", buffer);
    }
    
  } while(rc > 0);

  return rc;
}

int main(void)
{
  int fd;
  int rc;

  // Open the file
  fd = open(MEMINFO_FNAME, O_RDONLY);
  if (fd < 0) {
    fprintf(stderr, "open(%s): '%m' (%d)\n", MEMINFO_FNAME, errno);
    return 1;
  }

  do {
    printf("==========\n");
    rc = read_file(fd);
    sleep(1);
  } while(rc == 0);

  close(fd);

  return 0;
}

每次读取文件后执行显示不同的值:

$ gcc meminfo.c -o meminfo
$ ./meminfo
==========
MemTotal:       131927796 kB
MemFree:         9305304 kB
MemAvailable:   125498348 kB
Buffers:        53300112 kB
[...]
==========
MemTotal:       131927796 kB
MemFree:         9323984 kB
MemAvailable:   125517048 kB
Buffers:        53300112 kB
[...]
==========
MemTotal:       131927796 kB
MemFree:         9324236 kB
MemAvailable:   125517300 kB
Buffers:        53300120 kB
[...]

NB:取决于文件的平均大小,如果受到监视,则可以调整读取缓冲区的大小以仅调用一次read()

As explained in the answers to this question, it is not possible to memory map a file from the /proc virtual file system. You would get an EIO error from mmap().
The optimal way to avoid a systematic open/read/close, is to simply open the file once and seek to the beginning to read its content again. Updated data are returned.
Here is an example program reading /proc/meminfo every second:

#include <sys/types.h>
#include <errno.h>
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#define MEMINFO_FNAME "/proc/meminfo"

int read_file(int fd)
{
  int rc;
  char buffer[512];
  off_t off;

  off = lseek(fd, 0, SEEK_SET);
  if (off == (off_t)-1) {
    fprintf(stderr, "lseek(%s): '%m' (%d)\n", MEMINFO_FNAME, errno);
    return -1;
  }

  do {

    rc = read(fd, buffer, sizeof(buffer));
    if (rc > 0) {
      buffer[rc] = '\0';
      printf("%s", buffer);
    }
    
  } while(rc > 0);

  return rc;
}

int main(void)
{
  int fd;
  int rc;

  // Open the file
  fd = open(MEMINFO_FNAME, O_RDONLY);
  if (fd < 0) {
    fprintf(stderr, "open(%s): '%m' (%d)\n", MEMINFO_FNAME, errno);
    return 1;
  }

  do {
    printf("==========\n");
    rc = read_file(fd);
    sleep(1);
  } while(rc == 0);

  close(fd);

  return 0;
}

The execution shows varying values after each reads in the file:

$ gcc meminfo.c -o meminfo
$ ./meminfo
==========
MemTotal:       131927796 kB
MemFree:         9305304 kB
MemAvailable:   125498348 kB
Buffers:        53300112 kB
[...]
==========
MemTotal:       131927796 kB
MemFree:         9323984 kB
MemAvailable:   125517048 kB
Buffers:        53300112 kB
[...]
==========
MemTotal:       131927796 kB
MemFree:         9324236 kB
MemAvailable:   125517300 kB
Buffers:        53300120 kB
[...]

N.B.: Depending on the average size of the file which is monitored, the size of the read buffer can be adapted to have only one call to read().

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文