Постарайтесь не снова использовать того же fd числа в приложении сокета мультипотока

По-моему, я не полагаю, что это - задание компилятора для фиксации то, что, честно, плохо кодирует. Вы, вполне явно, сказали компилятору о желании того первого выполняемого цикла. Это совпадает с:

x = 0
sleep 6 // Let's assume this is defined somewhere.
print x

я не хотел бы компилятор, удаляющий мой sleep оператор просто, потому что это ничего не сделало. Можно утверждать, что оператор сна является явным запросом на задержку, тогда как пример не. Но тогда Вы будете позволять компилятору принимать очень высокоуровневые решения относительно того, что должен сделать Ваш код, и я полагаю что быть плохой вещью.

Код и компилятор, который обрабатывает его, являются инструментами, и необходимо быть системным программистом, если Вы хотите использовать их эффективно. Сколько 12-дюймовые цепные пилы откажутся пробовать сокращенный 30-дюймовое дерево? Сколько разверток автоматически переключится для стука режима, если они обнаружат бетонную стену?

Ни один, который я подозреваю, и это вызвано тем, что стоимость разработки этого в продукт была бы ужасающей для запуска. Но что еще более важно, Вы не должны использовать развертки или цепные пилы, если Вы не знаете то, что Вы делаете. Например: если Вы не знаете то, что вознаграждение (очень простой способ к новичку снять их руку), избегать цепных пил, пока Вы не делаете.

я, все для разрешения компиляторов к предлагает улучшения, но я обеспечил бы контроль сам. Это не должно быть до компилятора, чтобы решить в одностороннем порядке, что цикл является ненужным.

, Например, я сделал циклы синхронизации во встроенных системах, где тактовая частота ЦП известна точно, но никакое надежное устройство синхронизации не доступно. В этом случае можно вычислить точно, сколько времени данный цикл будет брать и использовать это для управления, как часто вещи происходят. Это не работало бы, если бы компилятор (или ассемблер в этом случае) решил, что мой цикл был бесполезен и оптимизировал его из существования.

Однако позвольте мне оставить Вас со старой историей компилятора ФОРТРАНА VAX, который подвергался сравнительному тесту для производительности, и было найдено, что это было многие порядки величины быстрее, чем его самый близкий конкурент.

оказывается, что компилятор заметил, что результат циклов сравнительного теста не использовался больше нигде и оптимизировал циклы в забвение.

5
задан Arkaitz Jimenez 1 October 2009 в 14:32
поделиться

6 ответов

Ok, found the answer.

The best way here is to call accept() and get the lowest fd available, duplicate it with a number known by you like dup2(6,1000) and close(6), you have now control of the fd range you use.

Next accept will come again with 6 or similar, and we'll dup2(6,999); and keep decreasing like that and reseting it if it gets too low.

Since the accepting is done always in the same thread and dup2 and close aren't expensive compared to accept which is always done there it's perfect for my needs.

3
ответ дан 14 December 2019 в 04:43
поделиться

Как вы управляете сокетами? Похоже, у вас есть несколько потоков, любой из которых может:

  1. принять входящее соединение
  2. закрыть существующее соединение
  3. создать новое исходящее соединение

Похоже, вам нужен способ чтобы обеспечить доступ к различным розеткам, плавающим вокруг. Рассматривали ли вы возможность связать каждый сокет с мьютексом, который предотвращает закрытие сокета, пока он все еще используется, или, возможно, поместить каждый дескриптор сокета в структуру с атомарным счетчиком ссылок, который не позволит другим потокам закрыть его, пока все потоки не будут использовать его?

2
ответ дан 14 December 2019 в 04:43
поделиться

сокет представляет собой 5-кортеж {local-addr, local-port, remote-addr, remote-port, proto}, поэтому, если вы можете использовать эти свойства вместо fd для маршрутизации событий / обработчиков, вы можете избежать столкновения fd.

другой вариант - сериализовать все операции close () / accept () (приоритеты?), чтобы они не могли смешиваться

1
ответ дан 14 December 2019 в 04:43
поделиться

Отличный вопрос! Я даже не понимал, что такая проблема может возникнуть.

Единственный ответ, который я могу придумать, это то, что вы не должны использовать close (), чтобы сигнализировать, что сокет завершен. Одно из решений - использовать shutdown () для разрыва соединения. Затем вы можете безопасно close () сокет, используя подсчет ссылок.

1
ответ дан 14 December 2019 в 04:43
поделиться

Я бы все равно был осторожен при использовании dup2 () для хорошо известного значения fd. Помните, что dup2 () выполнит закрытие цели перед дублированием; это могло бы конфликтовать с каким-то несвязанным потоком, выполняющим несвязанный ввод-вывод, если вы начнете открывать 1000 файлов.

На вашем месте, учитывая ограничения, на которых вы настаиваете, я бы использовал dup () (не dup2 ()) внутри мьютекса. (Возможно, мьютексы per-fd, если вас это беспокоит.)

1
ответ дан 14 December 2019 в 04:43
поделиться

Ведите подсчет отложенных операций (чтение / запись и т. Д.) Для каждого сокета, а также наличие отложенного запроса на закрытие сокета. Если раньше вы вызывали close, сначала проверьте, есть ли какие-либо ожидающие операции. Если есть, вызовите shutdown вместо этого, а затем вызовите close только тогда, когда число ожидающих операций достигнет 0.

0
ответ дан 14 December 2019 в 04:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: