Понимание системы опроса Glib для файловых дескрипторов - PullRequest
0 голосов
/ 14 апреля 2020

Я пытаюсь понять систему опроса glib. Как я понимаю, опрос - это метод отслеживания файловых дескрипторов событий. Функция os_host_main_loop_wait выполняется в al oop. Вы можете видеть, что он вызывает glib_pollfds_fill, qemu_poll_ns и glib_pollfds_poll. Я пытаюсь понять, что делает l oop, вызывая каждую из этих функций.

static GArray *gpollfds;

static void glib_pollfds_fill(int64_t *cur_timeout)
{
    GMainContext *context = g_main_context_default();
    int timeout = 0;
    int64_t timeout_ns;
    int n;

    g_main_context_prepare(context, &max_priority);

    glib_pollfds_idx = gpollfds->len;
    n = glib_n_poll_fds;
    do {
        GPollFD *pfds;
        glib_n_poll_fds = n;
        g_array_set_size(gpollfds, glib_pollfds_idx + glib_n_poll_fds);
        //Gets current index's address on gpollfds array
        pfds = &g_array_index(gpollfds, GPollFD, glib_pollfds_idx);
        //Fills gpollfds's each element (pfds) with the file descriptor to be polled
        n = g_main_context_query(context, max_priority, &timeout, pfds,
                                 glib_n_poll_fds);
        //g_main_context_query returns the number of records actually stored in fds , or, 
        //if more than n_fds records need to be stored, the number of records that need to be stored.
    } while (n != glib_n_poll_fds);

    if (timeout < 0) {
        timeout_ns = -1;
    } else {
        timeout_ns = (int64_t)timeout * (int64_t)SCALE_MS;
    }

    *cur_timeout = qemu_soonest_timeout(timeout_ns, *cur_timeout);
}
static void glib_pollfds_poll(void)
{
    GMainContext *context = g_main_context_default();
    GPollFD *pfds = &g_array_index(gpollfds, GPollFD, glib_pollfds_idx);

    if (g_main_context_check(context, max_priority, pfds, glib_n_poll_fds)) {
        g_main_context_dispatch(context);
    }
}
static int os_host_main_loop_wait(int64_t timeout)
{
    GMainContext *context = g_main_context_default();
    int ret;

    g_main_context_acquire(context);

    glib_pollfds_fill(&timeout);

    qemu_mutex_unlock_iothread();
    replay_mutex_unlock();

    ret = qemu_poll_ns((GPollFD *)gpollfds->data, gpollfds->len, timeout); //RESOLVES TO: g_poll(fds, nfds, qemu_timeout_ns_to_ms(timeout));

    replay_mutex_lock();
    qemu_mutex_lock_iothread();

    glib_pollfds_poll(); 

    g_main_context_release(context);

    return ret;
}

Так что, как я понимаю, g_poll опрашивает массив файловых дескрипторов с тайм-аутом. Что это означает? Это означает, что он ожидает тайм-аут. Если что-то происходит (например, в fd есть данные для чтения), я не знаю, что это делает.

Затем glib_pollfds_poll вызывает g_main_context_check, а затем g_main_context_dispatch.

Согласно документации glib, g_main_context_check делает следующее:

Передает результаты опроса обратно на главный l oop.

Что это значит?

Затем g_main_context_dispatch

отправляет все источники

, что я также не знаю, что это значит.

Весь источник можно основать здесь: https://github.com/qemu/qemu/blob/14e5526b51910efd62cd31cd95b49baca975c83f/util/main-loop.c

...