glib g 主循环回调无故调用多次
glib g main loop callback called more than one time without reason
我想要一个进程 g_main_loop 调用文件描述符中传入字符的回调。
所以我尝试在我的板上使用上面的代码手动创建 /home/dev
文件。
除了启动此代码外,不做任何事情,回调将继续调用。
我不明白为什么。我希望只有在 /home/dev
文件中写入时才会调用回调。是 f_open
文件选项问题吗?还是我没有做正确的事情,文件描述符将数据视为已读?
#include <stdio.h>
#include <glib.h>
#include <glib/gstdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
gboolean cb_1 (GIOChannel *source, GIOCondition condition, gpointer data);
int main(void)
{
GMainLoop* mainloop;
int fd;
GIOChannel* channel;
mainloop = g_main_loop_new(NULL, TRUE);
fd=g_open("/home/dev", O_RDONLY, O_NONBLOCK);
channel=g_io_channel_unix_new(fd);
g_io_add_watch(channel, G_IO_IN, cb_1, NULL);
g_main_loop_run(mainloop);
g_main_loop_unref(mainloop);
}
gboolean cb_1 (GIOChannel *source, GIOCondition condition, gpointer data)
{
gchar** line=NULL;
GIOStatus status;
GError* error;
printf("cb\n");
status=g_io_channel_read_line(source, line, NULL, NULL, &error);
if(G_IO_STATUS_NORMAL == status)
{
printf("callback : data : %s\n", *line);
g_free(*line);
}
return TRUE;
}
打开文件并创建频道将在文件可供读取时触发您的回调。
在Linux中,你需要inotify watchers来实现你想要的。下面是帮助您理解它的代码片段。在回调方法中,您需要阅读 struct inotify_event 以了解调用回调的事件。阅读 inotify 手册页以获取有关您可以使用的可能掩码的完整详细信息。您可能还需要像 IN_CREATE | 这样的标志。 IN_DELETE.
#include <stdio.h>
#include <stdlib.h>
#include <glib.h>
#include <sys/inotify.h>
GMainLoop *mainloop;
static gboolean inotify_data(GIOChannel * channel, GIOCondition cond, gpointer user_data)
{
printf("event on GIOChannel\n");
char buffer[256];
gsize bytes_read;
GIOStatus status = g_io_channel_read_chars(channel, buffer, sizeof(buffer) - 1, &bytes_read, NULL);
/* buffer can have multiple inotify_event structs which contains
* details of what event, which file triggered this callback.
*/
return TRUE;
}
int main(void)
{
int fd, wd;
GIOChannel *channel;
mainloop = g_main_loop_new(NULL, FALSE);
fd = inotify_init();
if (fd < 0) {
exit(EXIT_FAILURE);
}
wd = inotify_add_watch(fd, "/home/test", IN_OPEN | IN_MODIFY);
channel = g_io_channel_unix_new(fd);
if (!channel) {
close(fd);
exit(EXIT_FAILURE);
}
g_io_channel_set_close_on_unref(channel, TRUE);
g_io_channel_set_encoding(channel, NULL, NULL);
g_io_channel_set_buffered(channel, FALSE);
g_io_add_watch(channel, G_IO_IN | G_IO_HUP | G_IO_NVAL | G_IO_ERR, inotify_data, NULL);
g_main_loop_run(mainloop);
return 0;
}
我想要一个进程 g_main_loop 调用文件描述符中传入字符的回调。
所以我尝试在我的板上使用上面的代码手动创建 /home/dev
文件。
除了启动此代码外,不做任何事情,回调将继续调用。
我不明白为什么。我希望只有在 /home/dev
文件中写入时才会调用回调。是 f_open
文件选项问题吗?还是我没有做正确的事情,文件描述符将数据视为已读?
#include <stdio.h>
#include <glib.h>
#include <glib/gstdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
gboolean cb_1 (GIOChannel *source, GIOCondition condition, gpointer data);
int main(void)
{
GMainLoop* mainloop;
int fd;
GIOChannel* channel;
mainloop = g_main_loop_new(NULL, TRUE);
fd=g_open("/home/dev", O_RDONLY, O_NONBLOCK);
channel=g_io_channel_unix_new(fd);
g_io_add_watch(channel, G_IO_IN, cb_1, NULL);
g_main_loop_run(mainloop);
g_main_loop_unref(mainloop);
}
gboolean cb_1 (GIOChannel *source, GIOCondition condition, gpointer data)
{
gchar** line=NULL;
GIOStatus status;
GError* error;
printf("cb\n");
status=g_io_channel_read_line(source, line, NULL, NULL, &error);
if(G_IO_STATUS_NORMAL == status)
{
printf("callback : data : %s\n", *line);
g_free(*line);
}
return TRUE;
}
打开文件并创建频道将在文件可供读取时触发您的回调。
在Linux中,你需要inotify watchers来实现你想要的。下面是帮助您理解它的代码片段。在回调方法中,您需要阅读 struct inotify_event 以了解调用回调的事件。阅读 inotify 手册页以获取有关您可以使用的可能掩码的完整详细信息。您可能还需要像 IN_CREATE | 这样的标志。 IN_DELETE.
#include <stdio.h>
#include <stdlib.h>
#include <glib.h>
#include <sys/inotify.h>
GMainLoop *mainloop;
static gboolean inotify_data(GIOChannel * channel, GIOCondition cond, gpointer user_data)
{
printf("event on GIOChannel\n");
char buffer[256];
gsize bytes_read;
GIOStatus status = g_io_channel_read_chars(channel, buffer, sizeof(buffer) - 1, &bytes_read, NULL);
/* buffer can have multiple inotify_event structs which contains
* details of what event, which file triggered this callback.
*/
return TRUE;
}
int main(void)
{
int fd, wd;
GIOChannel *channel;
mainloop = g_main_loop_new(NULL, FALSE);
fd = inotify_init();
if (fd < 0) {
exit(EXIT_FAILURE);
}
wd = inotify_add_watch(fd, "/home/test", IN_OPEN | IN_MODIFY);
channel = g_io_channel_unix_new(fd);
if (!channel) {
close(fd);
exit(EXIT_FAILURE);
}
g_io_channel_set_close_on_unref(channel, TRUE);
g_io_channel_set_encoding(channel, NULL, NULL);
g_io_channel_set_buffered(channel, FALSE);
g_io_add_watch(channel, G_IO_IN | G_IO_HUP | G_IO_NVAL | G_IO_ERR, inotify_data, NULL);
g_main_loop_run(mainloop);
return 0;
}