根据proc手册,可以通过打开“/ proc / mounts”监视linux系统中的挂载点更改,并在fd_set
调用中添加文件描述符以读取select()
。
以下代码适用于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调用中不断弹出。即使坐骑没有变化。
我在这里错过了什么吗?
提前感谢您的帮助!
/ proc / [pid] / mounts(自Linux 2.4.19起)
这是当前在进程的mount命名空间中安装的所有文件系统的列表。 fstab(5)中记录了该文件的格式。从内核版本2.6.15开始,此文件是可轮询的:打开文件进行读取后,此文件中的更改(即文件系统挂载或卸载)会导致select(2)将文件描述符标记为可读,并轮询( 2)和epoll_wait(2)将文件标记为有错误条件。
答案 0 :(得分:13)
Linux内核中有bugfix描述了这种行为:
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);
}
}
答案 1 :(得分:4)
您指向的文档不正确。要使用select()
等待挂载更改,/proc/mounts
或/proc/pid/mounts
文件描述符应设置为 exceptfds ,而不是 readfds 。只需在程序中交换第2和第4个参数即可。 POSIX要求与常规文件关联的文件描述符始终可读。
答案 2 :(得分:1)
为了补充发布的主要示例,这是使用GLib
和GIO
库的另一个示例,通过监控/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;
}
答案 3 :(得分:-1)
如果你这样做
ls -l /proc/mounts
您将看到时间不断变化,这意味着即使没有太多变化,装载数据也会不断更新。所以看起来监控挂载的当前方法是不可行的。