Monitoring mount point changes via /proc/mounts

爷,独闯天下 提交于 2019-11-30 08:59:08

There was a bugfix in linux kernel describing that behavior:

SUSv3 says "Regular files shall always poll TRUE for reading and writing". see http://www.opengroup.org/onlinepubs/009695399/functions/poll.html

So, you have to use poll with POLLPRI | POLLERR flags. Something like this:


     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);
          }
     }

The documentation that you pointed to is incorrect. To wait on mount changes using select(), the /proc/mounts or /proc/pid/mounts file descriptor should set be in exceptfds, not readfds. Just swap the 2nd and 4th arguments in your program. File descriptors associated with regular files are required by POSIX to always be readable.

To complement the main example posted on question, here's another example using GLib and GIO libraries, to listen to mount changes by monitoring /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;
}

If you do

ls -l /proc/mounts

You will see that time is keep on changing that means mount data is being constantly updated even though not much is changed. So looks like the current method of monitoring mounts is not workable.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!