2

プログラムが常にすべてのマウントポイントを認識できるようにします。簡単なグーグルの後、 getmntent() と友人がマウントされているものを教えてくれることがわかりました。マウントされたものを知る必要があるたびにこれを実行できることはわかっていますが、ファイルを読み続ける必要がないように、何かがマウント/アンマウントされたことを認識する方法はありますか? これはdBusが行うことですか?

どんなヒントも役に立ちます。私はプログラミングを始めようとしています (2002 年に大学生のときに C のコースを受講しました)。オープン ソース プログラムに実装したい機能を見つけました。

4

2 に答える 2

3

Linux 用にコーディングしている場合 (またはそれでも GNOME ライブラリを使用している場合)、GNOME の GIO はこれに適した API を提供します。これは、GTK と GIO を使用する C で書いた単純なドライブ モニターです。

#include <gio/gio.h>
#include <gtk/gtk.h>
#include <string.h>

typedef struct {
    GtkWidget *window;
    GtkWidget *vbox;
    GtkWidget *scrolled_window;
    GtkWidget *view;
    GtkWidget *button;

    GtkListStore *store;
    GVolumeMonitor *monitor;
} Context[1];

enum {
    COL_DRIVE,
    COL_ICON,
    COL_NAME,
    NUM_COLS
};

static int find_drive(GtkTreeModel *model, GDrive *drive, GtkTreeIter *iter)
{
    gboolean valid;

    valid = gtk_tree_model_get_iter_first(model, iter);
    while (valid) {
        GDrive *cur;
        gtk_tree_model_get(model, iter, COL_DRIVE, &cur, -1);

        if (cur == drive)
            return 1;

        valid = gtk_tree_model_iter_next(model, iter);
    }

    return 0;
}

static void set_drive_iter(Context ctx, GDrive *drive, GtkTreeIter *iter)
{
    GIcon *icon = g_drive_get_icon(drive);
    gchar *name = g_drive_get_name(drive);

    gtk_list_store_set(ctx->store, iter,
        COL_DRIVE, drive,
        COL_ICON, icon,
        COL_NAME, name,
        -1);

    g_free(name);
}

static void add_drive(Context ctx, GDrive *drive)
{
    GtkTreeIter iter;
    gtk_list_store_append(ctx->store, &iter);
    set_drive_iter(ctx, drive, &iter);
}

static void refresh_drive_list(Context ctx)
{
    GList *drives, *l;
    drives = g_volume_monitor_get_connected_drives(ctx->monitor);

    gtk_list_store_clear(ctx->store);

    for (l = drives; l; l = l->next)
        add_drive(ctx, l->data);
}

static void update_drive(Context ctx, GDrive *drive)
{
    GtkTreeModel *model = GTK_TREE_MODEL(ctx->store);
    GtkTreeIter iter;

    if (find_drive(model, drive, &iter))
        set_drive_iter(ctx, drive, &iter);
    else
        refresh_drive_list(ctx); //Shouldn't happen
}

static void remove_drive(Context ctx, GDrive *drive)
{
    GtkTreeModel *model = GTK_TREE_MODEL(ctx->store);
    GtkTreeIter iter;

    if (find_drive(model, drive, &iter))
        gtk_list_store_remove(ctx->store, &iter);
    else
        refresh_drive_list(ctx); //Shouldn't happen
}

static void init_drive_list(Context ctx)
{
    ctx->store = gtk_list_store_new(3, G_TYPE_POINTER, G_TYPE_ICON, G_TYPE_STRING);
    refresh_drive_list(ctx);
}

static void init_drive_view(Context ctx)
{
    GtkTreeViewColumn *column;
    GtkCellRenderer *renderer;

    ctx->view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(ctx->store));
    g_object_set(ctx->view,
        "headers-visible", FALSE,
        NULL);

    renderer = gtk_cell_renderer_pixbuf_new();
    g_object_set(renderer, "stock-size", GTK_ICON_SIZE_DIALOG, NULL);
    column = gtk_tree_view_column_new_with_attributes("Icon", renderer, "gicon", COL_ICON, NULL);
    gtk_tree_view_column_set_resizable(column, TRUE);
    gtk_tree_view_append_column(GTK_TREE_VIEW(ctx->view), column);

    renderer = gtk_cell_renderer_text_new();
    column = gtk_tree_view_column_new_with_attributes("Name", renderer, "text", COL_NAME, NULL);
    gtk_tree_view_column_set_resizable(column, TRUE);
    gtk_tree_view_append_column(GTK_TREE_VIEW(ctx->view), column);
}

static void print_drive_info(GDrive *drive)
{
    GIcon *icon;
    gchar *name, *icon_string;

    name = g_drive_get_name(drive);
    icon = g_drive_get_icon(drive);
    icon_string = g_icon_to_string(icon);
    g_object_unref(icon);

    g_print("\tname: %s\n\ticon: %s\n",
        name ? name : "(null)",
        icon_string ? icon_string : "(null)");

    g_free(name);
    g_free(icon_string);
}

static void on_drive_changed(GVolumeMonitor *volume_monitor, GDrive *drive, Context ctx)
{
    g_print("Drive changed:\n");
    print_drive_info(drive);
    update_drive(ctx, drive);
}

static void on_drive_connected(GVolumeMonitor *volume_monitor, GDrive *drive, Context ctx)
{
    g_print("Drive connected:\n");
    print_drive_info(drive);
    add_drive(ctx, drive);
}

static void on_drive_disconnected(GVolumeMonitor *volume_monitor, GDrive *drive, Context ctx)
{
    g_print("Drive disconnected:\n");
    print_drive_info(drive);
    remove_drive(ctx, drive);
}

static void on_refresh_clicked(GtkButton *button, Context ctx)
{
    refresh_drive_list(ctx);
}

int main(int argc, char *argv[])
{
    Context ctx;
    memset(ctx, 0, sizeof(ctx));
    gtk_init(&argc, &argv);

    ctx->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    g_signal_connect(ctx->window, "destroy", G_CALLBACK(gtk_main_quit), NULL);

    ctx->vbox = gtk_vbox_new(FALSE, 0);
    gtk_widget_show(ctx->vbox);
    gtk_container_add(GTK_CONTAINER(ctx->window), ctx->vbox);

    ctx->scrolled_window = gtk_scrolled_window_new(NULL, NULL);
    gtk_scrolled_window_set_policy(
        GTK_SCROLLED_WINDOW(ctx->scrolled_window),
        GTK_POLICY_AUTOMATIC,
        GTK_POLICY_AUTOMATIC);
    gtk_box_pack_start(GTK_BOX(ctx->vbox), ctx->scrolled_window, TRUE, TRUE, 0);
    gtk_widget_show(ctx->scrolled_window);

    ctx->monitor = g_volume_monitor_get();
    g_signal_connect(ctx->monitor, "drive-changed", G_CALLBACK(on_drive_changed), ctx);
    g_signal_connect(ctx->monitor, "drive-connected", G_CALLBACK(on_drive_connected), ctx);
    g_signal_connect(ctx->monitor, "drive-disconnected", G_CALLBACK(on_drive_disconnected), ctx);

    init_drive_list(ctx);
    init_drive_view(ctx);
    gtk_widget_show(ctx->view);
    gtk_container_add(GTK_CONTAINER(ctx->scrolled_window), ctx->view);

    ctx->button = gtk_button_new_from_stock(GTK_STOCK_REFRESH);
    g_signal_connect(ctx->button, "clicked", G_CALLBACK(on_refresh_clicked), ctx);
    gtk_widget_show(ctx->button);
    gtk_box_pack_start(GTK_BOX(ctx->vbox), ctx->button, FALSE, FALSE, 0);

    gtk_window_set_default_size(GTK_WINDOW(ctx->window), 500, 500);
    gtk_widget_show(ctx->window);

    gtk_main();
    return 0;
}

でコンパイルしgcc $(pkg-config --cflags --libs gtk+-2.0) volumes.c -o volumesます。実行してテストし、ペンドライブを接続します。その場で更新する必要があります。適切なアイコンも表示されます。

これは、マウントではなくドライブを監視することに注意してください。GVolumeMonitor はマウントも監視できます (devhelp の「mount-added」と「mount-removed」を参照)。これを使用するには、GObject システムについて少し学ぶ必要があります。幸運を!

于 2010-03-05T20:43:21.243 に答える
1

の言及に基づいてgetmntent()、私はあなたが Linux を扱っていると推測します (他の Unice にも Linux が含まれていますが、最近ではあまり一般的ではありません...)。その場合は、man inotify開始する必要があります。

于 2010-03-05T20:38:50.753 に答える