Модераторы: feodorv
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> вопрос по epoll, зачем union epoll_data_t  
V
    Опции темы
shara
Дата 27.7.2011, 17:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 344
Регистрация: 29.6.2004
Где: печенье?

Репутация: нет
Всего: 2



Собно есть в Линухе такое семейство функций под общим названием epoll. Чтобы не растекаться мыслями по древу приведу исходный код из  man'a:

Код

/*************** DEFS *******************/
#define MAX_EVENTS 10

typedef union epoll_data {
  void        *ptr;
  int          fd;
  __uint32_t   u32;
  __uint64_t   u64;
} epoll_data_t;

struct epoll_event {
  __uint32_t   events;      /* Epoll events */
  epoll_data_t data;        /* User data variable */
};

/*************** CODE *******************/
struct epoll_event ev, events[MAX_EVENTS];
int listen_sock, conn_sock, nfds, epollfd;

/* Set up listening socket, 'listen_sock' 
    (socket(), bind(), listen()) 
*/

epollfd = epoll_create(10);
if (epollfd == -1) {
  perror("epoll_create");
  exit(EXIT_FAILURE);
}

ev.events = EPOLLIN;
ev.data.fd = listen_sock;

if (epoll_ctl(epollfd, EPOLL_CTL_ADD, listen_sock, &ev) == -1) {
  perror("epoll_ctl: listen_sock");
  exit(EXIT_FAILURE);
}

for (;;) {
  nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1);
  if (nfds == -1) {
    perror("epoll_pwait");
    exit(EXIT_FAILURE);
  }

  for (n = 0; n < nfds; ++n) {
    if (events[n].data.fd == listen_sock) {
      conn_sock = accept(listen_sock,
          (struct sockaddr *) &local, &addrlen);
      if (conn_sock == -1) {
        perror("accept");
        exit(EXIT_FAILURE);
      }
      setnonblocking(conn_sock);
      ev.events = EPOLLIN | EPOLLET;
      ev.data.fd = conn_sock;
      if (epoll_ctl(epollfd, EPOLL_CTL_ADD, conn_sock, &ev) == -1) {
        perror("epoll_ctl: conn_sock");
        exit(EXIT_FAILURE);
      }
    } else {
      do_use_fd(events[n].data.fd);
    }
  }
}



Вроде бы все чинно, лоично и понятно..

Но вот в упор не пойму зачем epoll_data_t был объявлен как union?
Ведь кроме файлового декскритора там особо ничего и не насохраняешь..
Если даже сохранить какойнить полезный указатель в тот-же void *ptr;  заботливо припасенный в юнионе, - то мы затрем дескриптор файла, а он ведь  тоже нужен. Посему нужно будет скопировать дескритор в другую перемнную...  НУ НЕ ПОНИМАЮ Я ЭТОГО!!  smile 

З.Ы. 
А круто было бы, если бы вместо union'a это был struct. Много полезной инфы можно было бы напихать туда - удобно, все  в одном месте. Хотя, сдается мне, что такой подход был бы череват перерасходом памяти..



--------------------
   с точки зрения аэродинамики шмель не может летать  
PM MAIL   Вверх
boostcoder
Дата 27.7.2011, 17:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(shara @  27.7.2011,  17:16 Найти цитируемый пост)
Если даже сохранить какойнить полезный указатель в тот-же void *ptr;  заботливо припасенный в юнионе, - то мы затрем дескриптор файла, а он ведь  тоже нужен.

потому что в реальном коде все ассоциированные с дексриптором данные хранят в структуре. а ее адрес и присваивают ptr`у  smile 
PM WWW   Вверх
shara
Дата 27.7.2011, 19:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 344
Регистрация: 29.6.2004
Где: печенье?

Репутация: нет
Всего: 2



выходит это так сделано для удобства системы? smile  а я блин ищу высшие смыслы  smile  smile  smile 


--------------------
   с точки зрения аэродинамики шмель не может летать  
PM MAIL   Вверх
boostcoder
Дата 27.7.2011, 20:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(shara @  27.7.2011,  19:45 Найти цитируемый пост)
выходит это так сделано для удобства системы?

для удобства использующего ее программиста ;)
PM WWW   Вверх
shara
Дата 27.7.2011, 20:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 344
Регистрация: 29.6.2004
Где: печенье?

Репутация: нет
Всего: 2



А можешь показать в чем заключается это удобство? а то я не совсем понимаю.. лично мне от этого юниона ни тепло ни холодно


--------------------
   с точки зрения аэродинамики шмель не может летать  
PM MAIL   Вверх
boostcoder
Дата 28.7.2011, 02:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



ну вот представь: у тебя есть набор подключившихся пользователей. ты мониторишь набор дескрипторов в ожидании событий от юзеров.
где ты будешь хранить информацию о сессии(состояние игры, транзакцию действий) пользователя? и как ты имея только дескриптор, поймешь, какого_пользователя_этот_дестриптор?
PM WWW   Вверх
shara
Дата 28.7.2011, 09:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 344
Регистрация: 29.6.2004
Где: печенье?

Репутация: нет
Всего: 2



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


typedef struct _session 
{
  void *in_buf;
  int in_buf_size;
  // other usefool data
  // ...
} session, *p_session;

p_session user_session_map[MAX_FD];
session user_session[MAX_FD];

int make_session_job (p_session ses);

/********************************************/

// init
for (i=0; i < MAX_FD) {
  user_session_map[i] = &user_session[i];
  // some other initialization
}

  // some other code
 
  nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1);
  for (n = 0; n < nfds; ++n) {
    //get session buffer form READY fd
    if (events[n].data.fd > MAX_FD) {
       error("Unexpected FD\n");
    }
    make_session_job (  user_session_map [events[n].data.fd] );
    //...
  }

опять же повторюсь, union может хранить в себе только ОДНО значение т.е. ИЛИ fd ИЛИ *ptr
но не как ни соответствие fd <-->*pt
для этиго вышеупомянутый epoll_data_t должен был бы быть объявлен как struct - тогда пожалуйста.

ну или я действительно чего-то не понимаю  smile 


--------------------
   с точки зрения аэродинамики шмель не может летать  
PM MAIL   Вверх
asmdzen
Дата 28.7.2011, 09:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



**


Профиль
Группа: Участник
Сообщений: 345
Регистрация: 28.11.2010

Репутация: нет
Всего: 5



Цитата(shara @  27.7.2011,  17:16 Найти цитируемый пост)
Если даже сохранить какойнить полезный указатель в тот-же void *ptr;  заботливо припасенный в юнионе, - то мы затрем дескриптор файла, а он ведь  тоже нужен. Посему нужно будет скопировать дескритор в другую перемнную...

ptr будет указывать на структуру в которую мы сперва скопируем этот fd, а потом уже поменяем значение ptr. т.е. если нужен только дескриптор файла, пожалуйста, если нужна целая структура, делайте как хотите и помещайте указатель на нее в ptr.
PM MAIL   Вверх
boostcoder
Дата 28.7.2011, 10:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(shara @  28.7.2011,  09:42 Найти цитируемый пост)
Создаем массив

Цитата(shara @  28.7.2011,  09:42 Найти цитируемый пост)
можно сделать так

всего один вопрос: зачем?
PM WWW   Вверх
shara
Дата 28.7.2011, 10:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 344
Регистрация: 29.6.2004
Где: печенье?

Репутация: нет
Всего: 2



Цитата(asmdzen @  28.7.2011,  08:56 Найти цитируемый пост)
ptr будет указывать на структуру в которую мы сперва скопируем этот fd,

Т.е. достаточно будет только раз этот *ptr туда прописать и он нам вернется из epoll_wait в юниионе.  Мы будем точно знать что на этой сесси произошло некое событие. 
Теперь понял  smile , действительное красивое решение. Спасибо.


boostcoder
Опытом не умудрен потому и склонен к изобретению лисапетов  smile 

З.Ы. ну не встречал я раньше таких приемов программирования


Это сообщение отредактировал(а) shara - 28.7.2011, 10:39


--------------------
   с точки зрения аэродинамики шмель не может летать  
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Сети | Следующая тема »


 




[ Время генерации скрипта: 0.0827 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.