socol 发表于 2013-1-15 18:56:07

程序内通信:GIOChannel 与 Pipe

原文:
http://caterpillar.onlyfun.net/Gossip/GTKGossip/GIOChannelPipe.html
 
使用pipe又称为无名管道,它直接在内存中划分区域进行通信,其最大的局限就是必须在有父子关系的进程中进行通信。
另外,还有一种称之为有名管道FIFO,可以进行程序间通信。
 
#include<gtk/gtk.h>#include<errno.h>#include<unistd.h>void value_changed_callback(GtkSpinButton *spinButton, GIOChannel *channel);gboolean iochannel_read(GIOChannel *channel, GIOCondition condition, GtkLabel *label);void setup_parent(gint output[]);void setup_child(gint input[]);int main(int argc, char *argv[]) {    gint parent_to_child;    if(pipe(parent_to_child) == -1) { // 開啟Pipe      g_error("Error: %s\n", g_strerror(errno));      return 1;    }    // fork 子程序    switch(fork()) {      case -1:            g_error("錯誤: %s\n", g_strerror(errno));            break;      case 0: // 這是子程序            gtk_init(&argc, &argv);            setup_child(parent_to_child);            break;      default: // 這是父程序            gtk_init(&argc, &argv);            setup_parent(parent_to_child);    }    gtk_main();    return 0;}// GtkSpinButton的callbackvoid value_changed_callback(GtkSpinButton *spinButton, GIOChannel *channel) {    GIOStatus ret_value;    gint value;    GString *text;    gsize length;    value = gtk_spin_button_get_value_as_int(spinButton);    text = g_string_new("");    g_string_sprintf(text, "%d\n", value);    // 寫入資料至 GIOChannel    ret_value = g_io_channel_write_chars(channel, text->str, -1, &length, NULL);    if(ret_value == G_IO_STATUS_ERROR) {      g_error("錯誤: 無法寫入 GIOChannel !\n");    }    else {      g_io_channel_flush(channel, NULL);    }}gboolean iochannel_read(GIOChannel *channel,                         GIOCondition condition, GtkLabel *label) {    GIOStatus ret_value;    gchar *message;    gsize length;   if(condition & G_IO_HUP) {      g_error("錯誤: Pipe 已中斷!\n");    }    ret_value = g_io_channel_read_line(channel, &message, &length, NULL, NULL);    if(ret_value == G_IO_STATUS_ERROR) {      g_error("錯誤: 無法讀取!\n");    }    message = 0;    gtk_label_set_text(label, message);    return TRUE;}void setup_parent(gint output[]) {    GtkWidget *window;    GtkWidget *spinButton;    GIOChannel *channel_write;    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);    gtk_window_set_title(GTK_WINDOW(window), "Parent");    gtk_window_set_default_size(GTK_WINDOW(window), 250, 50);    spinButton = gtk_spin_button_new_with_range(0.0, 100.0, 1.0);    gtk_container_add(GTK_CONTAINER(window), spinButton);    g_signal_connect(GTK_OBJECT(window), "destroy",                     G_CALLBACK(gtk_main_quit), NULL);    // 關閉不用的 Pipe 輸出    close(output);    // 建立 GIOChannel    channel_write = g_io_channel_unix_new(output);    if(channel_write == NULL) {      g_error("錯誤: 無法建立 GIOChannels!\n");    }    g_signal_connect(G_OBJECT(spinButton), "value_changed",               G_CALLBACK(value_changed_callback), (gpointer) channel_write);    gtk_widget_show_all(window);}void setup_child(gint input[]) {    GtkWidget *window;    GtkWidget *label;    GIOChannel *channel_read;    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);    gtk_window_set_title(GTK_WINDOW(window), "Child");    gtk_window_set_default_size(GTK_WINDOW(window), 250, 50);    label = gtk_label_new("0");    gtk_container_add(GTK_CONTAINER(window), label);    g_signal_connect(GTK_OBJECT(window), "destroy",                     G_CALLBACK(gtk_main_quit), NULL);    // 關閉不必要的 Pipe 輸入    close(input);    channel_read = g_io_channel_unix_new(input);    if(channel_read == NULL) {      g_error("錯誤: 無法建立 GIOChannels!\n");    }   if(!g_io_add_watch(channel_read, G_IO_IN | G_IO_HUP,      (GIOFunc) iochannel_read, (gpointer) label)) {      g_error("錯誤: 無法對 GIOChannel 加入 watch!\n");    }    gtk_widget_show_all(window);} 
結果畫面如下所示:

http://caterpillar.onlyfun.net/Gossip/GTKGossip/images/GIOChannelPipe-1.jpg
页: [1]
查看完整版本: 程序内通信:GIOChannel 与 Pipe