select

63 views
Skip to first unread message

Руслан Кутдусов

unread,
Dec 6, 2011, 4:38:49 AM12/6/11
to usu_netprog
У меня возник вопрос по select-у. Надо переделать астролога, так чтобы
он был с неблок. сокетами и с select-ом, на данный момент астролог
построен на автомате, так вот надо ли сохранить этот автомат или
откатится к предыдущей версии?

Alexander E. Patrakov

unread,
Dec 6, 2011, 5:09:02 AM12/6/11
to usu_n...@googlegroups.com
Руслан Кутдусов <ruslan.ku...@gmail.com> пишет:

Автомат надо сохранить. select без автомата не имеет смысла.

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

--
Александр Патраков

Руслан Кутдусов

unread,
Dec 6, 2011, 5:11:35 AM12/6/11
to usu_netprog
Спасибо, еще вопрос вот в select

int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *utimeout);

про readfds все понятно, если по некоторому сокету пришли данные, то с
помощью FD_ISSET узнаем какой именно тот эсокет и обрабатываем,
не ясно про writefds, как select понимает что от нас ждут данных?

Alexander E. Patrakov

unread,
Dec 6, 2011, 5:27:57 AM12/6/11
to usu_n...@googlegroups.com
Руслан Кутдусов <ruslan.ku...@gmail.com> пишет:

> Спасибо, еще вопрос вот в select
>
> int select(int nfds, fd_set *readfds, fd_set *writefds,
> fd_set *exceptfds, struct timeval *utimeout);
>
> про readfds все понятно, если по некоторому сокету пришли данные, то с

> помощью FD_ISSET узнаем какой именно тот сокет и обрабатываем,


> не ясно про writefds, как select понимает что от нас ждут данных?

Он это не понимает. Он только понимает, что в ядре есть незаполненный
буфер и, следовательно, что send() не зависнет. Т.е. мы в writefds
складываем все дескрипторы, куда хотим что-либо записать, а на выходе
из них останутся только те, запись в которые не завесит процесс.

--
Александр Патраков

Руслан Кутдусов

unread,
Dec 6, 2011, 5:30:20 AM12/6/11
to usu_netprog
все, спасибо, сейчас все прояснилось)

Руслан Кутдусов

unread,
Dec 6, 2011, 6:28:05 AM12/6/11
to usu_netprog
все, спасибо, сейчас все прояснилось)

Pavel White

unread,
Dec 8, 2011, 10:26:12 AM12/8/11
to usu_n...@googlegroups.com
При использовании селекта, допустим я форкнул новый процесс, будет ли считаться серверный сокет за первый открытый дескриптор или первыйм будет тот, который вернул аксепт?

Марк Коренберг

unread,
Dec 8, 2011, 12:03:17 PM12/8/11
to usu_n...@googlegroups.com
8 декабря 2011 г. 21:26 пользователь Pavel White
<white.mat...@gmail.com> написал:

> При использовании селекта, допустим я форкнул новый процесс, будет ли
> считаться серверный сокет за первый открытый дескриптор или первыйм будет
> тот, который вернул аксепт?

Не совсем ясен вопрос, но могу отметить следующее:
1. При fork() все файловые дескрипторы остаются и никак не меняются по номеру.
2. Обычно, первые три дескриптора (0, 1 и 2) заняты под stdin, stdout и stderr.
3. Нельзя делать никаких предположений относительно того, какой номер
дескриптора вернётся после вызова accept(). Необходимо писать
программы так, будто этот номер непредсказуем.
4. на самом деле, accept() вернет наименьший по номеру дескриптор из
возможных вариантов.

Если я не ответил на вопрос, то лучше его повторить, но переформулировав.


--
Segmentation fault

Alexander E. Patrakov

unread,
Dec 9, 2011, 12:25:14 AM12/9/11
to usu_n...@googlegroups.com
В Thu, 8 Dec 2011 07:26:12 -0800 (PST)
Pavel White <white.mat...@gmail.com> пишет:

> При использовании селекта, допустим я форкнул новый процесс, будет ли
> считаться серверный сокет за первый открытый дескриптор или первыйм
> будет тот, который вернул аксепт?

Марк ответил правильно, но хочу добавить, что при использовании select()
в рамках материала, который пройден на лекциях, отличных от
последней, fork() вместе с select() не вызывается. Поэтому я не совсем
понял, в связи с чем был задан вопрос.

Напомню, что мы проходили:

prefork, process-per-client: вызывается fork(), используются
блокирующие сокеты, не вызывается select(), не используется автоматное
программирование (то, что было на 6-й лекции - это искусственное
упражнение, не имеющее отношения к реальным программам).

select: все соединения обслуживаются с помощью неблокирующих сокетов в
одном процессе, fork() не вызывается, используется автоматное
программирование, select() используется, чтобы выяснить, какой автомат
продвигать. В fd_set'ы на каждом шаге добавляются слушающий сокет (если
он готов для чтения, делаем accept() и добавляем нового клиента в массив
состояний) и все файловые дескрипторы от клиентов (при готовности
продвигаются соответствующие автоматы).

poll, epoll: это улучшенные варианты select(), используются
совершенно аналогично.

Гибридная модель prefork + select (вкратце упоминалась на последнем
занятии): создается слушающий сокет, N раз вызывается fork (как в модели
prefork). В каждом из дочерних процессов реализуется модель с select.
При этом файловый дескриптор от слушающего сокета - единственный общий
дескриптор, являющийся сокетом. Он имеет один и тот же номер, а именно
тот, который вернул socket().

--
Александр Патраков

Reply all
Reply to author
Forward
0 new messages