【发布时间】:2020-04-17 20:54:07
【问题描述】:
背景和问题
出于某些原因,我需要分叉我的代码并在两个分叉上更新一个变量。该变量通过mmap 存储在内存中,因此所有进程都可以访问它。在一个子进程中,我增加了变量。如何告诉 GTK 应用程序从子进程刷新/更新/重绘?
MWE
/*
* Update GTK label from variable stored in mmap
*/
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <gtk/gtk.h>
static void activate (GtkApplication *app, gpointer localval) {
GtkWidget *window;
// Button Containers
GtkWidget *button_box_quit;
// Buttons
GtkWidget *exit_button;
// Text
GtkWidget *text_status;
// Define Window, dynamic size for screen.
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "test");
gtk_window_set_default_size(GTK_WINDOW(window), 400, 300);
// Define Button Boxes.
button_box_quit = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
// Define Exit Button, put it in a box, put box in window
exit_button = gtk_button_new_with_label ("Exit");
gtk_container_add(GTK_CONTAINER (button_box_quit), exit_button);
gtk_container_add(GTK_CONTAINER (window), button_box_quit);
// Connect signals to buttons
g_signal_connect_swapped (exit_button, "clicked", G_CALLBACK (gtk_widget_destroy), window);
// Define text status
char msg[32]={0};
// The "print" line
g_snprintf(msg, sizeof msg, "val: %d\n", *(int *)localval);
text_status = gtk_label_new(msg);
gtk_container_add(GTK_CONTAINER (button_box_quit), text_status);
//Activate!
g_snprintf(msg, sizeof msg, "val: %d\n", *(int *)localval);
gtk_label_set_text(GTK_LABEL(text_status), msg);
gtk_widget_show_all (window);
}
int main (int argc, char **argv) {
GtkApplication *app;
int status;
int *VAL = mmap(NULL, sizeof(int), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
int *ABORT = mmap(NULL, sizeof(int), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
int pid = fork();
if (pid == 0) {
while(!*ABORT) {
printf("%d\n", *VAL);
// Increments here should be reflected outside this PID.
*VAL = *VAL + 1;
usleep(1000000);
}
exit(0);
} else {
app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
// The passing line
g_signal_connect (app, "activate", G_CALLBACK (activate), VAL);
status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);
*ABORT = 1;
}
*ABORT = 1;
return status;
}
运行时会发生什么
当 MWE 运行时,终端会尽职尽责地在每次更新时打印该值。然而,GTK 窗口永远显示“val: 1”。我们可以通过在activate 进程中的gtk_widget_show_all 之前添加usleep(3000000) 来告诉GTK 进程可以访问存储在mmap 中的值。在此变体中,窗口将永远显示“val: 4”。
重申的问题
如何使 GTK 窗口上的输出与终端匹配?
【问题讨论】: