Мониторинг изменений точки монтирования через / proc / mounts - PullRequest
10 голосов
/ 21 февраля 2011

В соответствии с руководством по proc, можно отслеживать изменения точки монтирования в системе linux, открыв "/ proc / mounts" и добавив дескриптор файла для чтения 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.Даже нет никаких изменений в креплениях.

Я что-то здесь упускаю?

Заранее благодарен за любую помощь!

man 5 proc:

/ proc / [pid] / mounts (начиная с Linux 2.4.19)

Это список всех файловых систем, которые в настоящее время смонтированы в пространстве имен монтирования процесса.Формат этого файла задокументирован в fstab (5).Начиная с версии ядра 2.6.15, этот файл доступен для опроса: после открытия файла для чтения изменение этого файла (т. Е. Монтирование или размонтирование файловой системы) приводит к тому, что select (2) помечает дескриптор файла как читаемый, и poll (2) и epoll_wait (2) помечают файл как имеющий условие ошибки.

Ответы [ 4 ]

13 голосов
/ 22 февраля 2011

В ядре linux было исправление , описывающее такое поведение:

SUSv3 говорит: «Обычные файлы всегда должны запрашивать ИСТИНА для чтения и писать ". см. 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);
          }
     }

4 голосов
/ 22 февраля 2011

Документация, на которую вы указали, неверна. Чтобы ожидать изменения монтирования с использованием select(), дескриптор файла /proc/mounts или /proc/pid/mounts должен быть установлен в , за исключением fds , а не readfds . Просто поменяйте 2-й и 4-й аргументы в вашей программе. POSIX требует, чтобы файловые дескрипторы, связанные с обычными файлами, всегда были читаемыми.

1 голос
/ 17 сентября 2017

В дополнение к основному примеру, опубликованному по вопросу, вот еще один пример использования библиотек 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;
}
0 голосов
/ 21 февраля 2011

Если вы сделаете

ls -l /proc/mounts

Вы увидите, что время постоянно меняется, что означает, что данные монтирования постоянно обновляются, даже если мало что изменилось.Похоже, что текущий метод мониторинга монтирования не работает.

...