The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

форумы  помощь  поиск  регистрация  майллист  ВХОД  слежка  RSS
"загрузка/выгрузка драйверов во фре"
Вариант для распечатки  
Пред. тема | След. тема 
Форумы Программирование под UNIX (Public)
Изначальное сообщение [Проследить за развитием треда]

"загрузка/выгрузка драйверов во фре"  
Сообщение от pvl email(ok) on 08-Дек-06, 12:13 
Доброго дня уважаемым. Помогите разобратся с 2-мя вопросами по сабжу если хавцы имеются.

1. есть драйвер т.н. чарактер девайса.. теость он отображается на /dev может быть открыт/закрыт/../т.д. из юзерспайса. ну.. все стандартно. и вот с шарингом его открытия/закрытия непонятка.
если в явном виде в юзерспайсе указать

ptr = open("/dev/mru", O_EXLOCK);
или
ptr = open("/dev/mru", O_SHLOCK);

то при попытке открытия драйвера вылетает
errno 45 /* Operation not supported */

и система сразу закрывает драйвер, хотя я в логах вижу что моя функция открытия возвращает 0

если шаровые флаги не трогать.. ну типа ptr = open("/dev/mru", 0);
открываемся с шаровой модой (что вобщем-то не плохо.. тока по ТЗ вариант эксклюзивного открытия обязателен)

2. тот же драйвер, но уже открытый с шаровой модой. драйвер рулит некой интерфейсной железкой и каждому юзер-клиенту выделяется кусоче полосы пропускания. реализацию множества клиентов делал по типу interface cloner framework. т.е. на каждого клиента создается своя структура данных. идентифицируется клиент по pid'у вызвавшего процесса. при появлении нового клиента для него выделяется память под все нужды и указатель вносится в лист. при записи/чтении/контроле из листа выбераются его параметры (опять таки по pid'у)и производится обработка. при отвале клиента, соответственно, из листа он удаляется, ресурсы очищаются.
но и тут какой то глюк вкрался.. примерно так выражен:
если законектились, скажем, 10-ток клиентов и один из них (не последний законекченый) в юзерспайсе аварийно вылетает (скажем по нулевому поинтеру или по ctrl^c снимается) то в драйвер не поступает сигнал закрытия дескриптора. поступает сигнал только для последнего клиента. со всеми вытекающими.
у себя все пересмотрел.. вроде нормально все должно быть.

допоможите грабли найти..
заранее спасибо.

ЗЫ
ос - FreeBSD 6.1 releng

ЗЗЫ
ух.. много текста наваял но это для полноты картины


Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

 Оглавление

Сообщения по теме [Сортировка по времени, UBB]


1. "загрузка/выгрузка драйверов во фре"  
Сообщение от Forth (??) on 08-Дек-06, 12:17 
Судя по всему должен драйвер обрабатывать ситуацию с эксклюзивными блокировками. Можно попробовать после open сделать flock эксклюзивно, может сработает.

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

2. "загрузка/выгрузка драйверов во фре"  
Сообщение от pvl email(ok) on 08-Дек-06, 12:41 
>после open сделать flock эксклюзивно, может сработает.

тада встречный вопрос - как из кернела сделать flock если нету его в кернеле..  гы

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

3. "загрузка/выгрузка драйверов во фре"  
Сообщение от Forth (??) on 08-Дек-06, 12:55 
>>после open сделать flock эксклюзивно, может сработает.
>
>тада встречный вопрос - как из кернела сделать flock если нету его
>в кернеле..  гы
А ядро здесь при чем? Написали же сами, что из юзерспейс делаете open, делайте следом flock. Не получится - значит надо в ядре что-то делать, чтобы работали блокировки эксклюзивные при открытии девайса.

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

4. "загрузка/выгрузка драйверов во фре"  
Сообщение от pvl email(ok) on 08-Дек-06, 13:02 
> делайте следом flock.
дык.. грю же - open в юзерспайсе возвращает -1 и сразу закрывает драйвер
> Не получится - значит надо в ядре что-то делать, чтобы работали блокировки эксклюзивные
> при открытии девайса.
гы..
знать бы что еще делать

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

5. "загрузка/выгрузка драйверов во фре"  
Сообщение от Forth (??) on 08-Дек-06, 13:08 
>> делайте следом flock.
>дык.. грю же - open в юзерспайсе возвращает -1 и сразу закрывает
>драйвер
Ну без шаровых флагов - открывается? Потом можно попробовать сделать flock. В целях эксперимента.
>> Не получится - значит надо в ядре что-то делать, чтобы работали блокировки эксклюзивные
>> при открытии девайса.
>гы..
>знать бы что еще делать
Копать драйверное api ядра:)


Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

6. "загрузка/выгрузка драйверов во фре"  
Сообщение от BigHo on 08-Дек-06, 14:37 
>1. есть драйвер т.н. чарактер девайса.. теость он отображается на /dev может
>быть открыт/закрыт/../т.д. из юзерспайса. ну.. все стандартно. и вот с шарингом
>его открытия/закрытия непонятка.
>если в явном виде в юзерспайсе указать
>
>ptr = open("/dev/mru", O_EXLOCK);
>или
>ptr = open("/dev/mru", O_SHLOCK);
>
>то при попытке открытия драйвера вылетает
>errno 45 /* Operation not supported */

ответ на твой вопрос скрывает файл miscfs/specfs/spec_vnops.c. Если кратко, то для файловых дескрипторов, не являющихся обычными файлами, операция блокировки FLOCK недоступна. Это ограничение не должно портить жизнт рядовому программисту, т.к. эту функцию можно заменить соответствующими ioctl вызовами (см. d_ioctl для struct cdevsw).

>и система сразу закрывает драйвер, хотя я в логах вижу что моя
>функция открытия возвращает 0

это нормально.

>если шаровые флаги не трогать.. ну типа ptr = open("/dev/mru", 0);
>открываемся с шаровой модой (что вобщем-то не плохо.. тока по ТЗ вариант
>эксклюзивного открытия обязателен)

потребуется одно из двух: либо корректировка ТЗ или всей ОС :)

>2. тот же драйвер, но уже открытый с шаровой модой. драйвер рулит
>некой интерфейсной железкой и каждому юзер-клиенту выделяется кусоче полосы пропускания. реализацию
>множества клиентов делал по типу interface cloner framework. т.е. на каждого
>клиента создается своя структура данных. идентифицируется клиент по pid'у вызвавшего процесса.

сколько умных слов.. Даже переспрашивать неловко.. :) Единственно, понял про привязку к pid. Остальное - смутные предположения.

>при появлении нового клиента для него выделяется память под все нужды
>и указатель вносится в лист. при записи/чтении/контроле из листа выбераются его
>параметры (опять таки по pid'у)и производится обработка. при отвале клиента, соответственно,
>из листа он удаляется, ресурсы очищаются.

Пожайлуста, опиши этот процесс по подробней.

>но и тут какой то глюк вкрался.. примерно так выражен:
>если законектились, скажем, 10-ток клиентов и один из них (не последний законекченый)
>в юзерспайсе аварийно вылетает (скажем по нулевому поинтеру или по ctrl^c
>снимается) то в драйвер не поступает сигнал закрытия дескриптора. поступает сигнал
>только для последнего клиента. со всеми вытекающими.
>у себя все пересмотрел.. вроде нормально все должно быть.

Хммм. eventhandler в совместно с dev_clone в модуле как-нибудь используются ?

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

7. "загрузка/выгрузка драйверов во фре"  
Сообщение от pvl email(ok) on 08-Дек-06, 15:21 
о..
начинается шото дельное..

>ответ на твой вопрос скрывает файл miscfs/specfs/spec_vnops.c.
не нашел в дереве исходников RELENG61 такого файла..
искал тама  http://fxr.watson.org/fxr/find?v=RELENG61&string=

> Если кратко, то для файловых дескрипторов, не являющихся обычными файлами, операция
> блокировки FLOCK недоступна.
я уже понял.. посмотрел код flock'а там принудительно вываливают errno 45 если дескриптор не указывает на "чесный" файл

>>если шаровые флаги не трогать.. ну типа ptr = open("/dev/mru", 0);
>>открываемся с шаровой модой (что вобщем-то не плохо.. тока по ТЗ вариант
>>эксклюзивного открытия обязателен)
>
>потребуется одно из двух: либо корректировка ТЗ или всей ОС :)
значит какой клиент первым успеет ioctl(set acces mode) сделать - так и будет

ффф..
с первым разобрался
пасиб!!

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

9. "загрузка/выгрузка драйверов во фре"  
Сообщение от BigHo on 08-Дек-06, 16:32 
>о..
>начинается шото дельное..
>
>>ответ на твой вопрос скрывает файл miscfs/specfs/spec_vnops.c.
>не нашел в дереве исходников RELENG61 такого файла..
>искал тама  http://fxr.watson.org/fxr/find?v=RELENG61&string=

я искал в freebsd4. Там макрасами код не так сильно запутан. Реализация cdevsw у них почти одинаковая.

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

8. "загрузка/выгрузка драйверов во фре"  
Сообщение от pvl email(ok) on 08-Дек-06, 15:55 
>>при появлении нового клиента для него выделяется память под все нужды
>>и указатель вносится в лист. при записи/чтении/контроле из листа выбераются его
>>параметры (опять таки по pid'у)и производится обработка. при отвале клиента, соответственно,
>>из листа он удаляется, ресурсы очищаются.
>
>Пожайлуста, опиши этот процесс по подробней.

подробнее..
подробнее - HDLC контроллер на 256 каналов есть у инфинеона.
стоит задача поднять его драйвер таким образом чтобы HDLC каналы интегрировались в сетевой стек BSD (это уже сделано аля L3 - IP ower HDLC) и какая-то часть каналов могла использоватся для неструктурированых данных.

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

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

когда загружается модуль доступа из юзермода вобщем то никаких действий не происходит..
создается мутекс там.. память выделяется под структуры и под будущий лист клиентов..
и создается ОДИН!!! cdev. один - потому что неизвесно сколько пользователей может быть и в каком порядке они будут появлятся/изщезать.
можно было бы наделать клонов(для сетевых интерфейсов так и делаю).. но клоны нада будет еще из юзерспайса менеджерить.. создавать их, удалять.. а не факт что клиент будет рутовыми правами обладать.

када юзер в клиентской программе делает open - создается структура с его параметрами(пока только access mode), она регистрируется у манагера. B вносится в лист активных клиентов
типа так

extern struct mru_softc *sc;

int mru_open(struct cdev *dev, int flag, int mode, struct thread *td)
{
  struct proc       *procp = td->td_proc;
  struct usrcl      *cl    = NULL;
.
.
  MALLOC(cl, struct usrcl*, sizeof(*cl), M_TKR_MRU_SC, M_WAITOK | M_ZERO);
  if(cl == NULL) {
   ...
  }
  cl->id = procp->p_pid;
.
.
  if((err = tkr_modregister(cl->id, "name", (void*)(cl))))
    return err;

  sc->clcnt++;
  LIST_INSERT_HEAD(sc->cldb, cl, cl_next);  // insert to client list
.
.
}
ну тока эт не все канечна.. мутексом там все закрыто критическое.
а при clos'е
int mru_close(struct cdev *dev, int flag, int otyp, struct thread *td)
{
  struct proc       *procp = td->td_proc;
  struct usrcl      *cl    = NULL;
  int                err   = 0;

  LIST_FOREACH(cl, sc->cldb, cl_next) {        // only one client per process
    if( cl->id == procp->p_pid ) {       // supported
      break;
    }
  }
  if(cl == NULL)   return EIO;
.
.
  err = tkr_modrelease(cl->id);
.
.
  LIST_REMOVE(cl, cl_next); // remove from clone list
.
.
  FREE( cl,     M_TKR_MRU_SC );
.
.
  sc->clcnt--;
  return 0;
}
тоесть действия до боли обратные.

>
>>но и тут какой то глюк вкрался.. примерно так выражен:
>>если законектились, скажем, 10-ток клиентов и один из них (не последний законекченый)
>>в юзерспайсе аварийно вылетает (скажем по нулевому поинтеру или по ctrl^c
>>снимается) то в драйвер не поступает сигнал закрытия дескриптора. поступает сигнал
>>только для последнего клиента. со всеми вытекающими.
>>у себя все пересмотрел.. вроде нормально все должно быть.
>
>Хммм. eventhandler в совместно с dev_clone в модуле как-нибудь используются ?

eventhandler только тот который стандартные LOAD/UNLOAD/DOWN обрабатыват.. клонеров - нет не считаю правильным (в данном кейсе)


Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

10. "загрузка/выгрузка драйверов во фре"  
Сообщение от BigHo on 08-Дек-06, 17:24 
>весь драйвер - слоистый (непосредственно контрол железки - мультиплексор - интерфейсный модуль,
>модуль доступа юзерей[с ним собссно щас и парюсь]), а так как
>BSD не жалует такие фичи (ну или я не нашел ничего
>билт-ин как слои реализовывать) то сделал еще свой манагер всех загруженых
>модулей.

Модуль доступа юзверей - как понимаю, интерфейс (API) для управления из пользовательского режима.

>смысл примерно такой:
>при старте системы манагер стартует первым и потом каждый загружающийся модуль (из
>входящих в мой драйвер) регистрируется у него (отдает структуру с указателями
>на свои io/ctl функции и параметры ) взамен получает указатель на
>соответствующие функции манагера.
>т.е. весь трафик в ядре идет через манагер.. может это и медленнее
>зато более структурно и легче ресурсы шарить.

На стадии установки параметров скорость работы не принципиальна - это да. И ориентация на модульность - это хорошо.

>когда загружается модуль доступа из юзермода вобщем то никаких действий не происходит..
>
>создается мутекс там.. память выделяется под структуры и под будущий лист клиентов..
>
>и создается ОДИН!!! cdev. один - потому что неизвесно сколько пользователей может

Извини, но это зря. Иначе d_open и d_close будут с ума сходить, то переоткрывая уже используемые рессурсы, то перезакрывая не принадлежащий им.. Смысл cdev - это файловый дескриптор. По другому - поток управления и данных, который может быть зашарен на несколько процессов. Если ты попытаешься из одного процесса установить два и более соединения к этому модулю, то система между ними не будет видеть никакой разницы. В каком порядке должен в этом случае выполняться d_close, и как должен поступать в этом случае d_open, открывая второй дескриптор ? Ядро не передает дополнительной информации об этом, кроме той, что указана в cdev и в proc.

Кстати, чисто принципиально возможно посроить зловредный код, если проверка выполняется только по одному pid и файловый дескриптор мог быть передан потомку без закрытия. К сожалению структура proc другой идентифицирующей информацией не располагает, что процесс именно тот, что изначально его открыл, а не маскируется его идентификатором

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

Чтобы автоматически создавать девайс, не нужно никакого управления из вне. Достаточно правильно настроить eventhandler с dev_clone параметром. Хотя я думаю, ты уже что то подобное уже делал. Создание клонов можно возложить на d_open, а удаление, на d_close. Вернее dev_clone создает свободный cdev для того, чтобы к нему можно было обратиться через d_open.

cdev считается неиспользуемым системой, если cdev->si_drv1 == NULL. Но зато к нему теперь можно обращаться как к "/dev/newdevice123", и если он не используется, то разрешить вызов d_open (хотя на самом деле это d_open проверяет, используется он, или нет).

>када юзер в клиентской программе делает open - создается структура с его
>параметрами(пока только access mode), она регистрируется у манагера. B вносится в
>лист активных клиентов
>типа так
>
>extern struct mru_softc *sc;
>
>int mru_open(struct cdev *dev, int flag, int mode, struct thread *td)
>{
>  struct proc       *procp = td->td_proc;
>  struct usrcl      *cl  
> = NULL;
>.
>.
>  MALLOC(cl, struct usrcl*, sizeof(*cl), M_TKR_MRU_SC, M_WAITOK | M_ZERO);
>  if(cl == NULL) {
>   ...
>  }
>  cl->id = procp->p_pid;
>.
>.
>  if((err = tkr_modregister(cl->id, "name", (void*)(cl))))
>    return err;
>
>  sc->clcnt++;
>  LIST_INSERT_HEAD(sc->cldb, cl, cl_next);  // insert to client list
>.
>.
>}

все это в MP-Safe ? (d_flag|D_NEEDGIANT) == 0 ?

>ну тока эт не все канечна.. мутексом там все закрыто критическое.

да, без мутексов в ядре - никуда

С такими большими сообщениями наверно лучше удалиться в почту или в аську ?

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

11. "загрузка/выгрузка драйверов во фре"  
Сообщение от pvl email(ok) on 08-Дек-06, 17:41 
>С такими большими сообщениями наверно лучше удалиться в почту или в аську
не нужно..
мы уже заканчиваем
гы гы гы....
большую часть я уже понял

>>и создается ОДИН!!! cdev.
>Извини, но это зря. Иначе d_open и d_close будут с ума сходить ...
>Чтобы автоматически создавать девайс, не нужно никакого управления из вне. Достаточно правильно
>настроить eventhandler с dev_clone параметром. Хотя я думаю, ты уже что
>то подобное уже делал. Создание клонов можно возложить на d_open, а
>удаление, на d_close. Вернее dev_clone создает свободный cdev для того, чтобы
>к нему можно было обратиться через d_open.>

не совсем я вьезжаю в клонеров драйверов по исходникам.
не располагаете ли докой какойнибудь.
понятно что при вызове clone_create создастся еще один cdev но я никак не вьеду как это все для юзера будет выглядеть.
типа.. хотим
p = open("/dev/mru", 0);
а на самом деле в опене делаем clone_create и получается что открываем /dev/mruN ?? или как??

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

12. "загрузка/выгрузка драйверов во фре"  
Сообщение от BigHo on 08-Дек-06, 18:29 
>>>и создается ОДИН!!! cdev.
>>Извини, но это зря. Иначе d_open и d_close будут с ума сходить ...
>>Чтобы автоматически создавать девайс, не нужно никакого управления из вне. Достаточно правильно
>>настроить eventhandler с dev_clone параметром. Хотя я думаю, ты уже что
>>то подобное уже делал. Создание клонов можно возложить на d_open, а
>>удаление, на d_close. Вернее dev_clone создает свободный cdev для того, чтобы
>>к нему можно было обратиться через d_open.>
>
>не совсем я вьезжаю в клонеров драйверов по исходникам.
>не располагаете ли докой какойнибудь.

я видел только неполную документацию по этому вопросу. Нормальной еще никто не напечатал.

>понятно что при вызове clone_create создастся еще один cdev но я никак
>не вьеду как это все для юзера будет выглядеть.
>типа.. хотим
> p = open("/dev/mru", 0);
>а на самом деле в опене делаем clone_create и получается что открываем
>/dev/mruN ?? или как??


Использование clone_create начинается с dev_clone, а не с d_open. Вернее регистрится обработчик событий - dev_clone, который в качестве агрумента использует еще одну функцию, в которой и должна вызываться clone_create.

Если мы говорим про именованые девайсы, то пользователь обращаясь к пути /dev/mruN вызывает к жизни несколько обработчиков - те что были зарегестированны EVENTHANDLER_REGISTER(dev_clone, mru_clone, ...). Допустим один из обработчиков "признал за своего" имя, по которому происходит обращение. Он должен вызвать создание нового девайса, будь то через clone_create, или через make_dev. По мне, во втором случае логика намного понятней получается.

Если начинаешь пользоваться make_dev, то чтобы один слот не мог быть роздан на нескольких потоков (процессов), надо использовать rman(9). Его использование сравни использованию mtx_trylock/mtx_unlock, по сравнению с которыми не имеет побочных эффектов и представлен даже не как один замок, а как их массив.

После того, как был создан девайс, он может быть передан обработчику d_open. Пока cdev->si_drv1 не заполнен, система его считает незанятым, и будет стараться выделить его для d_open над "/dev/mru".

Если обратиться четко по имени (например - /dev/mru0), то d_open может выполниться и для cdev с уже заполеным si_drv1.

Вообщем там есть и другие ньюансы, но тем, кто с этим разберется, d_close будет закрывать именно то, что надо, а не то, что легче.

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

Архив | Удалить

Индекс форумов | Темы | Пред. тема | След. тема
Оцените тред (1=ужас, 5=супер)? [ 1 | 2 | 3 | 4 | 5 ] [Рекомендовать для помещения в FAQ]




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2025 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру