2010-03-05 29 views
2

我想我的程序總是知道所有掛載點。快速谷歌後,我發現getmntent()和朋友可以告訴我什麼是掛載。我意識到我每次都可以做到這一點,因爲我需要知道掛載了什麼,但有什麼方法可以識別什麼時候掛載/卸載,因此我不必繼續閱讀文件?這是什麼dBus做?我怎麼注意什麼時候掛載

任何提示都會有幫助。我正在嘗試開始編程(2002年,我在大學時參加了一門C課程),並發現了一個我想在開源程序中實現的功能。

+1

這是一個Linux的問題嗎?更好地標記它...... – 2010-03-05 20:31:17

+0

啊,是的,我加了標籤。謝謝。 – Patrick 2010-03-05 20:44:35

+4

這就是她所說的? – newdayrising 2010-03-05 20:46:25

回答

1

基於提到的getmntent(),我猜測你正在處理Linux(其他Unices也包括它,但是現在它們已經不常見了......)。如果是這樣,man inotify應該讓你開始。

+0

這裏有一個'inotify'的解釋和示例代碼:http://www.ibm.com/developerworks/linux/library/l-ubuntu-inotify/index.html?ca=drs- – bta 2010-03-05 21:33:41

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系統的使用方法。祝你好運!

相關問題