Я думаю, что мои лучшие варианты используют dup()
и / или dup2()
, но в соответствии
на их справочную страницу, dup()
создает копию файла, переданного в
функция, но ссылающаяся на то же описание открытого файла,
Да.
значение
что эти два могут быть использованы взаимозаменяемо,
Может быть. Это зависит от того, что вы подразумеваете под "взаимозаменяемо".
и dup2()
закрывает новый fd
который заменяет старый FD.
dup2()
закрывает дескриптор файла target , если он открыт, перед дублированием дескриптора источника на него. Возможно, это то, что вы имели в виду, но мне трудно читать ваше описание таким образом.
Итак, мои предположения о том, что произойдет, (извините за мой дерьмовый псевдо
код)
int fd1, fd2, fd3;
fd1 = socket(x); // what the app is aware of
fd2 = socket(y); // first to connect
fd3 = dup(fd1); // fd1 and fd3 indentify the same description
Пока хорошо.
dup2(fd2, fd1); // The description identified by fd2 is now identified by fd1, the description previously identified by fd1 (and fd3) is closed
Нет, комментарий неверный. Файловый дескриптор fd1
сначала закрывается, а затем делается дубликатом fd2
. Базовое описание открытого файла, на которое первоначально ссылался fd1
, не закрыто, потому что с процессом связан другой дескриптор открытого файла, fd3
.
dup2(fd3, fd2); // The description identified by fd3 (copy of fd1, closed in the line above) is identified by fd2 (which can be closed and reassigned to fd3) since now the thescription that was being identified by fd2 is being identified by fd1.
Что выглядит нормально, за исключением того, что первый dup2()
закрывается
fd1,
Да, это так.
, который закрывает также fd3
Нет, это не так.
, поскольку они идентифицируют один и тот же файл
описание.
Ненужные. Закрытие - это функция дескрипторов файлов, а не непосредственное описание базовых открытых файлов. На самом деле, было бы лучше не использовать здесь слово «идентификация», поскольку это предполагает, что файловые дескрипторы являются своего рода идентификатором или псевдонимом для описания открытого файла. Они не. Файловые дескрипторы идентифицируют записи в таблице ассоциаций с открытыми описаниями файлов, но сами по себе не являются открытыми описаниями файлов.
Короче говоря, ваша последовательность вызовов dup()
, dup2()
и dup2()
должна производить именно тот обмен, который вы хотите, при условии, что все они будут успешными. Однако они оставляют дополнительный открытый файловый дескриптор, который может привести к утечке файлового дескриптора при многих обстоятельствах. Поэтому не забудьте закончить с
close(fd3);
Конечно, все, что предполагает, что это значение из fd1
, которое является особенным для приложения, а не переменная , содержащая его . Файловые дескрипторы - это просто числа. В объектах, которые их содержат, нет ничего особенного, поэтому если это переменная fd1
, которую необходимо использовать приложению, независимо от его конкретного значения, то все, что вам нужно сделать, - это выполнить обычный обмен целых чисел:
fd3 = fd1;
fd1 = fd2;
fd2 = fd3;
Относительно редактирования , вы пишете,
Когда приложение вызывает api_connect()
, оно переходит к функции a
указатель на int (вместе со всеми необходимыми адресами и
протоколы и т. д.). api_connect () вызовет socket (), bind () и
connect (), важной частью является то, что он напишет возвращаемое значение
socket () в памяти разбирается через указатель.
Возвращает ли api_connect()
значение дескриптора файла, записывая его через указатель или передавая его как или в возвращаемом значении функции, не имеет значения. Дело в том, что значение имеет , а не объект, если таковой имеется, который его содержит.
Это то, что я
означает "сокет знает только об одном fd". Приложение будет
затем позвоните FD_SET(fd1, write_set)
, позвоните api_select()
и затем проверьте
если fd доступен для записи с помощью вызова FD_ISSET(fd1, write_set)
.
Ну, это звучит проблематично в свете остальной части вашего описания.
[При некоторых условиях]
api_select()
создает новое соединение на другом интерфейсе
(вызывая все необходимые функции socket (), bind () и connect ()). это
соединение идентифицируется новым fd -fd2- приложение незнать, и который отслеживается в API.
Теперь, если приложение вызывает api_select()
с FD_SET(fd1, write_set)
и API понимает, что это второе соединение, которое завершено,
таким образом, делая fd2 доступным для записи, я хочу, чтобы приложение использовало fd2.
проблема в том, что приложение будет вызывать только FD_ISSET(fd1,
write_set)
и write(fd1)
после этого, поэтому мне нужно заменить fd2
с fd1.
Обратите внимание, что даже если вы выполните обмен файловыми дескрипторами, как описано в первой части этого ответа, это не повлияет на членство FD в любом fd_set
, так как такое членство логическое , не физический. Вам придется управлять членством fd_set
вручную, если вызывающий абонент использует это.
Мне неясно, предназначен ли api_select()
для предоставления услуг для более чем одного (указанного вызывающим абонентом) файлового дескриптора одновременно, как это может сделать select()
, но я полагаю, что для этого требуется бухгалтерия это было бы чудовищно. С другой стороны, если на самом деле функция одновременно обрабатывает только один FD, предоставляемый вызывающим абонентом, то имитация интерфейса select()
будет ... нечетной.
В этом случае я настоятельно призываю вас разработать более подходящий интерфейс. Помимо прочего, такой интерфейс должен обсуждать вопрос об обмене FD. Вместо этого он может напрямую сообщить вызывающей стороне, какой FD, если таковой имеется, готов к использованию, либо возвращая его, либо записывая его через указатель на переменную, указанную вызывающей стороной.
Кроме того, в случае, если вы, так или иначе, переключаетесь на альтернативный FD, не забывайте об управлении старым, чтобы не пропустить дескриптор файла. Каждый процесс имеет довольно ограниченное количество доступных, поэтому утечка файлового дескриптора может быть гораздо более сложной, чем утечка памяти. В случае, если вы действительно переключаетесь, вы уверены, что вам действительно нужно поменяться, в отличие от простого dup2()
добавления нового FD на старый, а затем закрытия нового?