使用GIOChannel的空管

时间:2013-05-22 10:50:15

标签: c gtk fork pipe

我是GTK的新手,我正在为连接到服务器的程序开发GUI。我使用fork将逻辑(命令行客户端)与GUI分开。逻辑和GUI使用管道进行通信。

有时GUI会从管道中读取几条空信息,我不明白为什么。

我尝试制作SSCCE,但我无法在简化示例中复制该问题。无论如何,这大致是该计划的运作方式:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <gtk/gtk.h>

int gui_pipe[2], logic_pipe[2];

gboolean deliver_signal(GIOChannel *source, GIOCondition cond, gpointer d) {
    gchar readbuffer[100];
    char ack[] = "ack";
    read(gui_pipe[0], readbuffer, 100);
    g_print("I received: %s\n",readbuffer);
    write(logic_pipe[1], ack, strlen(ack));
    return(TRUE);
}

main(int argc, char *argv[]) {
    GtkBuilder *builder;
    GtkWidget *window;
    GIOChannel *g_signal_in;
    if(pipe(gui_pipe)==-1) {
        perror("pipe call");
        exit(1);
    }
    if(pipe(logic_pipe)==-1) {
        perror("pipe call");
        exit(1);
    }
    switch(fork()) {
        case -1:
            perror("fork call");
            exit(2);
        case 0: /* Child (GUI) */
            close(gui_pipe[1]);
            close(logic_pipe[0]);
            gtk_init(&argc, &argv);
            builder = gtk_builder_new();
            gtk_builder_add_from_file(builder, "mygui.glade", NULL);
            window = GTK_WIDGET(gtk_builder_get_object(builder, "window1"));
            g_signal_in = g_io_channel_unix_new(gui_pipe[0]);
            g_io_add_watch(g_signal_in, G_IO_IN, deliver_signal, NULL);
            gtk_widget_show(window);  
            gtk_main();
        default: /* Parent (Logic) */
            close(gui_pipe[0]);
            close(logic_pipe[1]);
            char msg[] = "Hello!";
            char readbuffer[100];
            int i;
            for(i=0;i<5;i++) {
                printf("LOGIC: I'm sending %s\n",msg);
                write(gui_pipe[1], msg, strlen(msg));
                read(logic_pipe[0], readbuffer, 100);
                printf("LOGIC: I received: %s\n", readbuffer);
            }
            exit(0);
    }

}

此版本不读取空管道,但原始程序会执行此操作(总是7次!)。 我发现的唯一解决方案是:

do {
    read(gui_pipe[0], readbuffer, 100);
} while(strcmp("",readbuffer)==0);

我还尝试使用g_io_channel_read_chars()代替read(),但它也不起作用。

有什么建议吗?谢谢!

1 个答案:

答案 0 :(得分:0)

当您显示的代码也已知可行时,很难回答。

你至少应该检查一下你的回调中的condition参数,也许是因为有问题的程序会导致non-read conditions报告?