LINUX.ORG.RU

recvmsg vs netlink

 , ,


0

2
char buffer[100];
iov.iov_base = buffer;
iov.iov_len  = sizeof ( buffer );

ssize_t length;
bool done = false;
while ( true ) {
    length = recvmsg ( socket_fd, &messages, 0 );
    if ( length == -1 ) {
        return false;
    } else if ( length == 0 ) {
        break;
    }

    struct nlmsghdr * message;
    for ( message = ( struct nlmsghdr * ) buffer; NLMSG_OK ( message, length ); message = NLMSG_NEXT ( message, length ) ) {
        switch ( message->nlmsg_type ) {
        case NLMSG_DONE:
            printf ( "%s\n", "done" );
            done = true;
            break;
        default:
            printf ( "code %d\n", message->nlmsg_type );
            break;
        }
    }
    if ( done ) {
        break;
    }
}

используя метод научного тыка находим:

  • 20 <= размер буфера < 68 - прочитан done
  • 68 <= размер буфера < 148 - прочитано одно сообщение и done
  • 148 <= размер буфера < inf - прочитано два сообщения и done

вот это прикол. зачем он отбрасывает нужные сообщения. почему оно не кидает ошибку EMSGSIZE. идем в ман:

Если сообщение слишком длинное и не поместилось в предоставленный буфер, лишние байты могут быть отброшены, в зависимости от типа сокета, на котором принимаются сообщения.

для netlink доступно 2 варианта создания сокетов:

socket ( AF_NETLINK, SOCK_RAW,   NETLINK_ROUTE )
socket ( AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE )
и в обоих случаях сообщения отбрасываются.

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

Огромные фиксированные буферы - не хочу. Читать обычным read-ом?

★★

Ответ на: комментарий от true_admin

получить информацию о сетевых интерфейсах, адресах, маршрутах и тд. причем каждую информацию получать в реальном времени. например, если чел выдернул сетевой кабель - пропал интерфейс, адрес, маршрут и тд их друзья. при этом приложение должно получить сообщение RTM_DELLINK, RTM_DELADDR и тд. при этом нужно принять соответствующие меры. при восстановлении - восстановить работу.

punya ★★ ()
Последнее исправление: punya (всего исправлений: 3)
Ответ на: комментарий от punya

Ммм, а какие ещё есть варианты? Ядро шлёт сообщение, буфер уже заполнен... Или ты хотел чтобы буфер динамически расширялся? Так он же в юзерспейсе, ядро не может вызвать realloc.

Единственное, хотелось бы знать сколько сообщений дропнулось.

true_admin ★★★★★ ()
Ответ на: комментарий от true_admin

так точно. фиксированный читаю и в свой расширяющийся ложу. я так впринципе и могу сделать с помощью обычного read =) странно что люди советуют использовать recvmsg. было бы норм, если можно было контролировать количество дропнутых =(

punya ★★ ()
Ответ на: комментарий от punya

с помощью обычного read

а read будет из ядерного буффера читать? Сорри, не знаком с netlink.

true_admin ★★★★★ ()
Ответ на: комментарий от true_admin

да. потестирую сегодня вечером будут ли дропаться сообщения при маленьких буферах. надеюсь что нет =)

punya ★★ ()
Ответ на: комментарий от punya

Хм, тут тогда возникает другая проблема - а ты уверен что понимаешь как в ядре управляется этот буфер?

Моё имхо из моего опыта это сделать буфер размером.. ну, допустим, чтобы приложение могло продержаться 10 секунд под пиковым напором этих самых сообщений. Я так же таким приложениям задираю приоритет (а может вообще rt сделать?) и вызываю mlockall(CURRENT|FUTURE) (и ставлю ограничение по rss чтобы оперативу не отожрало в случае багов внуртри). Внутри приложения стараюсь избегать блокирующих намертво операций (=дисковые операции).

true_admin ★★★★★ ()

Можно сначала запросить размер пакета:

next_packet_size = recv(fd, NULL, 0, MSG_PEEK | MSG_TRUNC);
Я делал именно так и вроде всё работало.

Deleted ()
Ответ на: комментарий от vasily_pupkin

прочел nl_recv и желание юзать эту либу пропало.

  • локальный статик. ненужен, неоправдан и потоконебезопасен. пару таких багов лежат пофикшенные на трекере. нафиг мне такие приключения
  • goto
  • зашибись логика. всегда делать ретрай по EINTR

вобщем пусть идут лесом со своим «кодом». библиотека максимум на «позырить»

punya ★★ ()
Последнее исправление: punya (всего исправлений: 3)
Ответ на: комментарий от punya

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

vasily_pupkin ★★★★★ ()
Ответ на: комментарий от punya

всегда делать ретрай по EINTR

вот такие вот сигналы в юниксах :(

true_admin ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.