g_io_channel и FIFO заставляют ЦП привязываться к 100% - PullRequest
0 голосов
/ 01 мая 2018

Я пытаюсь понять, почему мой процессор привязывается к 100%, когда я использую FIFO в сочетании с g_io_channel.

У меня есть проект на github , который демонстрирует проблему с наименьшей возможной настройкой; просто простой сервер, который открывает FIFO в / tmp, и клиент, который отправляет сообщение на сервер через этот FIFO.

Я нашел:

  1. При первом запуске сервер занимает около нуля CPU
  2. Как только клиент отправляет сообщение на сервер через FIFO, сообщение принимается и распечатывается сервером, а затем ЦП переходит на 100%.
  3. Вы можете продолжать отправлять сообщения через FIFO, и сервер будет их печатать, но этот ЦП останется на уровне 100%: - /

Я пробовал обычный гугл и переполнение стека, но пока не радуюсь поиску решения. Я надеюсь, что кто-то может помочь мне понять, что происходит. Я верю, что использую glib / GTK правильно, но я очень рад, что исправлюсь. Я ценю любую помощь, которую вы можете оказать. Спасибо!

1 Ответ

0 голосов
/ 02 мая 2018

Запустив сервер с помощью strace, я увидел, что он просто вызывал poll() в цикле при возврате события POLLHUP. Проблема, похоже, заключалась в том, что вы ожидаете, что сможете ждать неопределенно G_IO_IN событий, чтобы сообщить вам о поступлении данных, но не управляете G_IO_HUP, которые сообщают вам, что соединение было закрыто.

Я нашел этот комментарий в bluez code :

if (cond & (G_IO_ERR | G_IO_HUP)) {
        /*
         * Both ends needs to be open simultaneously before proceeding
         * any input or output operation. When the remote closes the
         * channel, hup signal is received on this end.
         */
        fifo_open();
        return FALSE;
}

Этот вопрос SO объясняет все это: Опрос () в именованном канале возвращается с POLLHUP постоянно и немедленно

И это то, что я видел с strace: когда клиентский процесс завершает работу (ваш или просто echo на вашем fifo), канал ввода-вывода получает уведомление о том, что другая сторона соединения повесила трубку. Ваш клиент в настоящее время отправляет сообщение и закрывает соединение. Так что либо вы хотите, чтобы соединение поддерживалось и не отключалось, либо вам нужно снова открыть серверную часть fifo и добавить новые часы, или, как говорит mark4o в вопросе SO, с которым я связан, вы открываете fifo с помощью read / права на запись на стороне сервера , чтобы у вас всегда был хотя бы один пишущий сервер на fifo (сервер), чтобы избежать зависания.

В качестве примера, код bluez, с которым я связался, закрывает канал и открывает новый при отключении. Также будьте осторожны с проблемами подсчета ссылок в вашем коде.

...