我希望我的程序总是知道所有的挂载点。在快速谷歌之后,我发现 getmntent() 和朋友可以告诉我安装了什么。我意识到每次我需要知道安装了什么时我都可以这样做,但是有什么方法可以识别什么时候安装/卸载,这样我就不必继续阅读文件了?这是dBus的作用吗?
任何提示都会有所帮助。我正在尝试开始编程(我在 2002 年上大学时参加了 C 课程。)并找到了我想在开源程序中实现的功能。
如果您正在为 Linux 编写代码(或者仍在使用 GNOME 库),GNOME 的 GIO 提供了一个很好的 API。这是我用 C 语言编写的一个使用 GTK 和 GIO 的简单驱动监视器:
#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 系统才能使用它。祝你好运!
基于对 的提及getmntent()
,我猜你正在处理 Linux(其他 Unices 也包括它,但它们现在不太常见......)。如果是这种情况,man inotify
应该让你开始。