Logo Море(!) аналитической информации!
IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware
Архив форумов ЦИТФорума
Море(!) вопросов - Море(!) ответов
 
 FAQFAQ   ПоискПоиск   ПользователиПользователи   ГруппыГруппы   РегистрацияРегистрация 
 ПрофильПрофиль   Войти и проверить личные сообщенияВойти и проверить личные сообщения   ВходВход 
Как правильно задавать вопросы

Перекидывание структур из ядра в пространство пользователя.

 
Перейти:  
Этот форум закрыт, вы не можете писать новые сообщения и редактировать старые.   Эта тема закрыта, вы не можете писать ответы и редактировать сообщения.    Список форумов Архив форумов ЦИТФорума -> Программирование
Предыдущая тема :: Следующая тема  
Автор Сообщение
Aragaer



Зарегистрирован: 28.03.2005
Сообщения: 164

СообщениеДобавлено: Пн Апр 11 2005 15:56    Заголовок сообщения: Перекидывание структур из ядра в пространство пользователя. Ответить с цитатой

В Linux.
Пытаюсь написать модуль, который будет выхватывать IP-пакеты, идущие через определенный интерфейс. Соответственно внутри модуля можно работать со структурой sk_buff. Требуется выкинуть ее наружу, чтобы уже другой программой что-то с этим sk_buff'ом делать.
Первая очевидная идея - использовать обычные средства ipc, в частности разделяемую память. Модули не умеют использовать все эти вещи. К сожалению.
Вторая идея - создать устройство, через который выкидывать информацию, а программой соответственно читать. Как выяснилось, символьные устройства для этого непригодны (передать sk_buff как последовательность байтов просто так не получится).
Вопрос: как можно сделать что-то вроде разделяемой памяти, доступной из ядра и из пространства пользователя? Была идея по поводу блочных устройств, но хотелось бы попроще как-нибудь.

Еще один вариант - попробовать превратить sk_buff в последовательный набор байт (то есть по сути обратно в ip-пакет), а потом его разбирать. Насколько реально такое?
_________________
Open your eyes.
And Awaken.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
Ersh



Зарегистрирован: 20.01.2004
Сообщения: 107

СообщениеДобавлено: Пн Апр 11 2005 19:09    Заголовок сообщения: Ответить с цитатой

может ты что-то не так делаешь, но модули тоже умеют работать с шаред мемори...
_________________
Анархия - мать порядка!!!!!!!!!
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
benoni



Зарегистрирован: 12.04.2005
Сообщения: 1

СообщениеДобавлено: Вт Апр 12 2005 15:59    Заголовок сообщения: Ответить с цитатой

Используй ф.с /proc, помоему она для этого и предназначена.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
Aragaer



Зарегистрирован: 28.03.2005
Сообщения: 164

СообщениеДобавлено: Вт Апр 12 2005 21:05    Заголовок сообщения: Ответить с цитатой

Получилось с символьным устройством.
Проблема в том, чтобы в пространстве пользователя работать со структурой типа sk_buff - компилятор ругается, что incomplete type, а если подключить linux\skbuff.h, то вылетает огромное количество ошибок в тех библиотеках, которые skbuff.h за собой тянет.
Пересылать структуру iphdr наружу уже получается.
_________________
Open your eyes.
And Awaken.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
pzz



Зарегистрирован: 13.04.2005
Сообщения: 4

СообщениеДобавлено: Ср Апр 13 2005 16:25    Заголовок сообщения: 2 Aragaer: skb и character devices Ответить с цитатой

Нет ничего сложного в том, чтобы использовать skb'шки совместно с character device'ами. Надо только передавать не структуру sk_buff, а ее содержимое.

Буфера, предназначенные для отправки из ядра в user space должны где-то складываться (в ядре, т.е. в драйвере/модуле) в очередь, т.к. появляются они, скорее всего, независимо от желания user space их читать. Чтение должно брать первый буфер из очереди, и копировать его в пользовательский буфер. Если буфер слишком маленький, есть два варианта: либо обрезать данные, либо возвращать ошибку (-EMSGSIZE), чтобы намекнуть user space'у, что неплохо бы предложить буфер побольше. Если чтение произошло без ошибок, буфер удаляется из очереди. Если же при попытке чтения выясняется, что очередь пуста, операция чтения блокируется (т.е., понадобится научиться работать с очередями ожидания, что не сложно).

О чем стоит подумать, это о том, что делать, если SKB'шки для чтения накапливаются, но их никто не читает (например, программа зависла, или ее просто нет). Иначе существует опасность собрать в очереди для чтения всю память ядра, после чего системе, очевидно, придет кирдык Smile

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

Особой разницы, делать это через /dev или через /proc нету. Это во многом вопрос вкуса. Отмечу одну особенность /dev'а: если devfs не используется, то имя в /dev придется добавить вручную, что не всегда удобно.

Еще одна возможность, раз уж данные внутри ядра представлены SKB'шками, это создать socket, работающий между ядром и userspace. Посмотри в сторону, например, rtnetlink, как это делается.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Отправить e-mail
Aragaer



Зарегистрирован: 28.03.2005
Сообщения: 164

СообщениеДобавлено: Ср Апр 13 2005 18:19    Заголовок сообщения: Ответить с цитатой

Пришел к выводу, что передавать всю skb'шку мне смысла нет. Даже и весь IP-заголовок не нужен, только saddr. /dev удобнее тем, что в него можно писать, с /proc это (насколько я понял из LKMPG) сложнее.

Но я никак не могу понять, как можно из ядра делать системные вызовы. Те же семафоры мне например понадобились. Понятно, что нужно подключить какую-то библиотеку. Но какую именно?
_________________
Open your eyes.
And Awaken.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
pzz



Зарегистрирован: 13.04.2005
Сообщения: 4

СообщениеДобавлено: Ср Апр 13 2005 22:09    Заголовок сообщения: Ответить с цитатой

В ядре свои семафоры:

struct semaphore sem;

init_MUTEX( &sem );
down( &sem );
up( &sem );

Но вообще, надо бы тебе книжку какую-нибудь найти и почитать.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Отправить e-mail
Aragaer



Зарегистрирован: 28.03.2005
Сообщения: 164

СообщениеДобавлено: Ср Апр 13 2005 22:29    Заголовок сообщения: Ответить с цитатой

Книжки в гугле искал. Тщательно. Так и не нашел ничего про системные вызовы. То есть нашел про unistd.h, но почему-то не хочет работать.
Еще есть вариант с таблицей системных вызовов. Но в ядре 2.6 это дело спрятано.

Семафорить мне нужно наружу.
То есть снаружи (в пространстве пользователя) некий процесс ожидает смены семафора. Как только это произойдет - читает из нашего символьного устройства.

Хотя, по идее раз мы находимся в режиме ядра, то можно вручную семафоры переключать. В крайнем случае.
А хочется сделать вызов типа sys_semget и не волноваться, что порушу таблицу семафоров.
_________________
Open your eyes.
And Awaken.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
Ersh



Зарегистрирован: 20.01.2004
Сообщения: 107

СообщениеДобавлено: Чт Апр 14 2005 15:29    Заголовок сообщения: Ответить с цитатой

Советую замечательную книжу: "Программирование в Unix" Автор Робачевский.
_________________
Анархия - мать порядка!!!!!!!!!
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
pzz



Зарегистрирован: 13.04.2005
Сообщения: 4

СообщениеДобавлено: Вс Апр 17 2005 23:48    Заголовок сообщения: Ответить с цитатой

Не надо ничего семафорить наружу Smile

User space может что-либо вычитать из твоего драйвера только позвав драйверный read. Вот там и синхронизируйся. Будет неплохо также, если твой драйвер будет поддерживать poll/select.

Почитай для начала что-нибудь из этого:

http://www.google.com/search?q=kernel+hacking+guide&sourceid=mozilla&start=0&start=0&ie=utf-8&oe=utf-8
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Отправить e-mail
Aragaer



Зарегистрирован: 28.03.2005
Сообщения: 164

СообщениеДобавлено: Пн Апр 18 2005 19:24    Заголовок сообщения: Ответить с цитатой

Да-да, уже все написал. Сделал блокируемой операцию чтения и все заработало.

Единственное что, так это странный глюк с ERESTARTSYS. А именно: в драйвере
Код:
if (cur == -1) {   // Нечего передать наружу
   if (filp->f_flags & O_NONBLOCK)
      return -EAGAIN;
   interruptible_sleep_on(&read_wq);
   return -ERESTARTSYS;
}

А в "клиенте"
Код:
res = read(fh, &saddr, 4)
if(res < 0)
   perror("Read error");

Проскакивало сообщение "Read error: unknown error 512", то есть тот самый ERESTARTSYS, который вообще-то вне ядра вообще не должен быть виден.
_________________
Open your eyes.
And Awaken.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
pzz



Зарегистрирован: 13.04.2005
Сообщения: 4

СообщениеДобавлено: Вт Апр 19 2005 20:00    Заголовок сообщения: Ответить с цитатой

Зачем тебе возвращать ERESTARTSYS? Почему бы тебе не сделать цикл прямо в драйвере?
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Отправить e-mail
Aragaer



Зарегистрирован: 28.03.2005
Сообщения: 164

СообщениеДобавлено: Ср Апр 20 2005 14:11    Заголовок сообщения: Ответить с цитатой

Потому что это более логично.
Дело в том, что в процессе ожидания пользователь может закрыть внешнее приложение. Это тоже прервет ожидание, но это еще не значит, что надо что-то передавать. Такое обрабатывается следующим образом:
Код:
interruptible_sleep_on(&read_wq);
if (cur == -1)   //Все еще нечего передать - значит мы вышли по прерыванию
   return 0;

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

Можно, конечно, ввести просто еще одну переменную, которая будет превращаться в единицу при каждом приходе пакета и в ноль при каждом чтении. Ее можно будет использовать, чтобы узнать, было прерывание или нет. Но ведь есть же специально предназначенный механизм - перезапустить еще раз системный вызов.
_________________
Open your eyes.
And Awaken.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
Показать сообщения:   
Этот форум закрыт, вы не можете писать новые сообщения и редактировать старые.   Эта тема закрыта, вы не можете писать ответы и редактировать сообщения.    Список форумов Архив форумов ЦИТФорума -> Программирование Часовой пояс: GMT + 3
Страница 1 из 1

 
Перейти:  
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах


Powered by phpBB © 2001, 2002 phpBB Group
Русская поддержка phpBB

 

IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

Информация для рекламодателей PR-акции, размещение рекламы — adv@citforum.ru,
тел. +7 495 6608306, ICQ 232284597
Пресс-релизы — pr@citforum.ru
Послать комментарий
Информация для авторов
This Web server launched on February 24, 1997
Copyright © 1997-2000 CIT, © 2001-2006 CIT Forum
Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Подробнее...