通过/ proc / mounts监视挂载点更改

根据proc手册,可以通过打开“/ proc / mounts”并在select()调用中添加文件描述符来读取fd_set来监视linux系统中的挂载点更改。

以下代码在Ubuntu 9.04上运行,而不是在Ubuntu 10.04(2.6.32 linux内核)下运行:

 int mfd = open("/proc/mounts", O_RDONLY, 0); fd_set rfds; struct timeval tv; int rv; FD_ZERO(&rfds); FD_SET(mfd, &rfds); tv.tv_sec = 5; tv.tv_usec = 0; int changes = 0; while ((rv = select(mfd+1, &rfds, NULL, NULL, &tv)) >= 0) { if (FD_ISSET(mfd, &rfds)) { fprintf(stdout, "Mount points changed. %d.\n", changes++); } FD_ZERO(&rfds); FD_SET(mfd, &rfds); tv.tv_sec = 5; tv.tv_usec = 0; if (changes > 10) { exit(EXIT_FAILURE); } } 

可编辑的片段。

文件描述符在一台机器上总是可读的,因此它在select调用中保持popup状态。 即使坐骑没有变化。

我在这里错过了什么?

提前感谢任何帮助!

男人5过程:

/ proc / [pid] / mounts(自Linux 2.4.19开始)

这是当前挂载在进程的挂载名称空间中的所有文件系统的列表。 这个文件的格式logging在fstab(5)中。 从内核版本2.6.15开始,这个文件是可轮询的:在打开文件读取之后,这个文件(即,文件系统mount或者unmount)的改变导致select(2)将文件描述符标记为可读,并且轮询2)和epoll_wait(2)将文件标记为有错误的情况。

在linux内核中有一个错误修正描述了这个行为:

SUSv3表示“普通文件应始终轮询TRUE读取和写入”。 请参阅http://www.opengroup.org/onlinepubs/009695399/functions/poll.html

所以,你必须使用POLLPRI |进行轮询 POLLERR标志。 像这样的东西:

int mfd = open("/proc/mounts", O_RDONLY, 0); struct pollfd pfd; int rv; int changes = 0; pfd.fd = mfd; pfd.events = POLLERR | POLLPRI; pfd.revents = 0; while ((rv = poll(&pfd, 1, 5)) >= 0) { if (pfd.revents & POLLERR) { fprintf(stdout, "Mount points changed. %d.\n", changes++); } pfd.revents = 0; if (changes > 10) { exit(EXIT_FAILURE); } }
int mfd = open("/proc/mounts", O_RDONLY, 0); struct pollfd pfd; int rv; int changes = 0; pfd.fd = mfd; pfd.events = POLLERR | POLLPRI; pfd.revents = 0; while ((rv = poll(&pfd, 1, 5)) >= 0) { if (pfd.revents & POLLERR) { fprintf(stdout, "Mount points changed. %d.\n", changes++); } pfd.revents = 0; if (changes > 10) { exit(EXIT_FAILURE); } } 

您指出的文档不正确。 要使用select()等待挂载更改, /proc/mounts/proc/pid/mounts文件描述符应设置为除ff之外的而不是readfds 。 只要交换你的程序中的第二个和第四个参数。 与常规文件相关联的文件描述符是POSIX要求始终可读的。

如果你这样做

 ls -l /proc/mounts 

你会看到时间不断变化,这意味着即使没有太多变化,安装数据也会不断更新。 所以看起来像监视坐骑的当前方法是不可行的。

为了补充发布的主要示例,下面是使用GLibGIO库的另一个示例,通过监视/proc/self/mountinfo来侦听挂载更改:

 /* Compile with: * gcc -g -O0 `pkg-config --cflags --libs gio-2.0` -o test test.c */ #include <glib.h> #include <gio/gio.h> static gboolean proc_mounts_changed (GIOChannel *channel, GIOCondition cond, gpointer user_data) { if (cond & G_IO_ERR) { g_message ("MOUNTS CHANGED!"); } return TRUE; } int main (int argc, char *argv[]) { GIOChannel *proc_mounts_channel; GSource *proc_mounts_watch_source; GError *error = NULL; GMainLoop *loop; proc_mounts_channel = g_io_channel_new_file ("/proc/self/mountinfo", "r", &error); if (proc_mounts_channel == NULL) { g_warning ("Error creating IO channel for %s: %s (%s, %d)", "/proc/self/mountinfo", error->message, g_quark_to_string (error->domain), error->code); g_error_free (error); return error->code; } proc_mounts_watch_source = g_io_create_watch (proc_mounts_channel, G_IO_ERR); g_source_set_callback (proc_mounts_watch_source, (GSourceFunc) proc_mounts_changed, NULL, NULL); g_source_attach (proc_mounts_watch_source, g_main_context_get_thread_default ()); g_source_unref (proc_mounts_watch_source); g_io_channel_unref (proc_mounts_channel); loop = g_main_loop_new (NULL, FALSE); /* Run the main loop, program can be ended with CTRL+C */ g_main_loop_run (loop); g_main_loop_unref (loop); return 0; }