Я пишу TCP-сервер на C в качестве упражнения для задания, которое, как я знаю, я получу в следующем году. Я реализовал ядро, которое использует один поток для обработки всех подключений, для этого он использует средство epoll. Ядро предоставляет остальной части программы API, очень похожий на предложения C# для асинхронной сети; все это отлично работает, и после некоторой странности epoll - мне внезапно пришлось использовать дублирование файловых дескрипторов, чтобы поддерживать его работоспособность, но, к счастью, я понял, почему - мне удалось избавиться от ошибок и утечек. Однако я не уверен, как остановить сервер. В настоящее время я написал подпрограммы очистки, которые очищают основные структуры данных, но они никогда не вызываются. Основной цикл epoll_wait никогда не заканчивается. Как остановить этот цикл?
Я подумал о следующем:
Я использую глобальный флаг, защищенный мьютексом, который проверяется основным потоком каждый раз перед вызовом
epoll_wait(). Когда флаг становится истинным, основная нить прерывает свой цикл и очищает все. Это работает, когда я использую основной поток для установки флага, например, когда он выходит из основного контекста через обратный вызов (например, обратный вызов, который вызывается при установлении нового соединения с прослушивающим сокетом; ядро ничего не знает о реализация этих обратных вызовов, и в этих обратных вызовах я мог бы установить стоп-флаг. В этом случае мьютекс даже не был бы необходим.) Однако это не всегда работает, когда мне нужен внешний поток (поток диспетчеризации событий графического интерфейса, возможно, • Если я хочу написать графический интерфейс для мониторинга сервера во время его работы, это может пригодиться) для установки этого флага. Конечно, основной поток остановит сервер, как только произойдет повторная проверка флага, но проблема в том, что он не будет часто проверять этот флаг, если сервер простаивает (например, когда нет клиентов и нет новых подключений). Тогдаepoll_wait()просто останется заблокированным, и мне придется убить сервер -- с помощью Ctrl-C или чего-то подобного. Это не то, чего я хочу.Чтобы решить эту проблему, я подумал о создании канала и добавлении этого канала fd в контекст epoll сервера при его запуске, чтобы он реагировал и возвращался из
epoll_wait()всякий раз, когда какой-либо поток записывает некоторые (нерелевантные) данные в этот канал. Это может позволить какому-то потоку заставить ядро проверить свой флаг и выйти. Но это похоже на грязное решение. Есть ли лучшая альтернатива? Если нет, будет ли работать это решение для каналов?
Заранее спасибо, как обычно, любые замечания (если конструктивные) приветствуются!