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

Программеры АААААА!!!!!

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





СообщениеДобавлено: Ср Июн 25 2003 14:38    Заголовок сообщения: Программеры АААААА!!!!! Ответить с цитатой

Народ подскажите участок кода для отображения памяти.
В драйвере устройства есть буфер. В пользовательско задаче тоже есть подобный буфер. Нужно чтобы пользовательский буфер по указателю работал бы с данными в буфере драйвера.
Мне нужен код или перечень функций (или просто хорошая идея) как бы такое сделать как на строне драйвера, так и на стороне пользователя (ядро 2.3.?)

HELP!
Вернуться к началу
Борис
Гость





СообщениеДобавлено: Ср Июн 25 2003 16:53    Заголовок сообщения: А исходники драйвера есть? (-) Ответить с цитатой

-
Вернуться к началу
werter
Гость





СообщениеДобавлено: Чт Июн 26 2003 10:46    Заголовок сообщения: Re: А исходники драйвера есть? (-) ЕСТЬ Ответить с цитатой

Пока это не совсем драйвер реального устройства, но тестовый код такой

//Фрагмент кода драйвера:

short driverbuf[256];//буфер данных драйвера
...
/*
далее функция mmap которая должна отобразить буфер driverbuf на указатель
пользовательской программы, чтобы та имела доступ к driverbuf через операции с указателями
*/
static int drv_mmap(struct file *filp, struct vma_area_struct *vma)
{
/*
Вот здесь и нужно что то сделать чтобы
отобразить driverbuf на пользовательскую программу
*/
return 0;
}
...

//Фрагмент кода пользовательской программы
void main()
{
...
fd= open(/dev/mydriver", O_RDWR);
...
/*
буфер куда планируется отобразить данные драйвера
*/
short userbuf[256];
//указатель на отображенную область
short *pbuf;
...
pbuf=(short*) mmap((short*) userbuf, sizeof(userbuf), PROT_READ | PROT_WRITE, MAP_PRIVATE, fd,0);
/*
Ну и далее типа таких операций
pbuf[2]= 0x1234;
short datafromdriverbuf= pbuf[2];
*/
...
}

В общем все это работает не так как надо. То сигналы всякие вылетают по типу не та область памяти, то параметры mmap задаются неверно (если последний параметр сделать не равным 0), а в коде драйвера размер запрашиваемого прикладной задачей блока всегда равен 4096 байт (ну возможно это условие гранулярности страниц памяти Linux)
Вернуться к началу
Борис
Гость





СообщениеДобавлено: Чт Июн 26 2003 12:55    Заголовок сообщения: Вопрос стал неясным, но попробую. Ответить с цитатой

Строки:

>>> static int drv_mmap(struct file *filp, struct vma_area_struct *vma)...
>>> pbuf=(short*) mmap((short*) userbuf, sizeof(userbuf), PROT_READ | PROT_WRITE, MAP_PRIVATE, fd,0);

предполагают, что адрес пользовательского буфера попадает в одно из полей переменной *filp (а именно, в первое поле). Кроме того, вероятно, в твоём драйвере есть функции, которые совместно используют буфер

>>> short driverbuf[256];//буфер данных драйвера

иначе зачем он нужен? Если сказанное верно, то твой вопрос звучит так: как сделать, чтобы работа с буфером driverbuf в действительности была работой с переданным из пользовательской функции адресом? Ответ, например, такой:
вместо

short driverbuf[256];

написать

short* driverbuf;

а внутри функции

static int drv_mmap(struct file *filp, struct vma_area_struct *vma)...

написать присвоение переменной driverbuf значения из первого поля *filp:

driverbuf = filp->имя_поля;

Тогда все другие функции драйвера будут работать с буфером, который передан из пользовательской функции.

Думаю, идея понятна.
Вернуться к началу
werter
Гость





СообщениеДобавлено: Чт Июн 26 2003 13:51    Заголовок сообщения: Re: Вопрос стал неясным, но попробую. Ответить с цитатой

Я понял, что ты предлагаешь. Спасибо.
Действительно с driverbuf[256] в моем драйвере работают еще и read() и write() и ioctl().
Но в драйвере реального устройства driverbuf будет не софтовым буфером, а указателем на физический адрес регистров устройства. Этот адрес определит сам драйвер (устройство PCIное) и нужно чтобы по этому адресу можно было обмениваться данными в пользовательской программе. Т.е. нужно каким то образом отобразить физический адрес устройства через мой драйвер на область памяти пользовательского процесса.
Я прикидывал вариант с отображением памяти через драйвер /dev/mem, но нехотелось бы для работы с одним устройством использовать два разных драйвера. хотелось бы узнать название сишного файла, который реализует драйвер /dev/mem, возможно там в исходниках будет что то полезное. А то у меня Linux без исходников, а ставить их неоткуда (ядро кемто перелопачено, а исходники не поставляются)
Вернуться к началу
Борис
Гость





СообщениеДобавлено: Чт Июн 26 2003 15:54    Заголовок сообщения: Теперь прояснилось. Ответить с цитатой

То есть driverbuf[256] у тебя не сдвинуть, так как аппаратные операции работают конкретно с этими адресами, но нужно чтобы содержимое этих адресов отображалось в поставляемый пользовательской функцией буфер. Тогда можно ввести вспомогательный указатель по тому же принципу, что в предыдущем сообщении, и во всех функциях до или после требуемых действий синхронизировать содержимое этих двух буферов. Кстати, здесь удобнее использовать C++ с его переопределением операторов и функций вместо C, чтобы не заботиться о синхронизации.

Но в любом случае при наличии двух буферов (аппаратного и программного) возникает вопрос актуальности информации для прикладных процессов. Это Вас не беспокоит?
Вернуться к началу
werter
Гость





СообщениеДобавлено: Пт Июн 27 2003 09:50    Заголовок сообщения: Re: Идею я понял но это, по моему, не совсем то. Ответить с цитатой

Ситуация такая:

Драйвер:
/*
в драйвере указатель настраивается на область памяти устройства (DEVICE_MEM - виртуальный адрес для физических адресов устройства)
*/
short *p_device= DEVICE_MEM;

/*
далее в драйвере следующая операция приводит к передачи данных device_data в регистры устройсва с заданным смещением
*/
*(p_device + (offset>>1))= device_data;



ПРОГРАММА:
В программе нужно работать с регистрами устройства так же как и в драйвере, т.e. по указателю.

short *p_proga= null;
/*
следующая операция должна для устройства (fd -дескриптор устройства) в программе создать указатель, по которому прикладная программа как и в коде драйвера моглабы работать напрямую с памятью устройства
*/
p_proga= mmap(p_proga,..., fd, 0);
*(p_proga+(offset>>1))= device_data;


Т.е. идея с двумя разными буферами, которые синхронизируются между собой, здесь не совсем то что нужно. Скорее нужно просто создать два указателя (один в драйвере, другой в программе), настроенных на один и тот же физический адрес памяти. В драйвере это не проблема, а вот в прикладной программе - это проблема. Причем хотелось бы чтобы прикладная программа получала указатель на физический адрес от моего драйвера, а не от какого то друго, например, /dev/mem. Для /dev/mem операция mmap в пользовательской программе как раз и создает указатель на заданный физический адрес (сам не проверял, но в internet источниках приводится подобный пример). Посмотреть бы как mmap реализован в драйвере /dev/mem. Но какой у этого драйвера файл с исходником (drivers/char/mem.c не уверен)?
Вернуться к началу
Борис
Гость





СообщениеДобавлено: Пт Июн 27 2003 16:48    Заголовок сообщения: Re: Идею я понял но это, по моему, не совсем то. Ответить с цитатой

Так что тебе мешает возвратить из драйверной функции drv_mmap() не ноль, а адрес буфера, то есть p_device?
Вернуться к началу
werter
Гость





СообщениеДобавлено: Вт Июл 01 2003 15:20    Заголовок сообщения: Что и все? Ответить с цитатой

Т.е. если я в драйвере где-то (например в open) создаю указатель на нужные мне физические адреса типа
p_device= __ioremap(PHYS_ADDR, LEN, 0);
, то достаточно в drv_mmap сделать так?

int drv_mmap(...)
{
return p_device;
//или так?
remap_page_range(vma->vm_start, __io_phys(p_device), size, prot);
/*
Вот здесь предположительно возникает ошибка -ядро не хочет ремапить память на пользовательскую область (vm_start) потому как эта область уже отремаплина на область драйвера (p_device).
*/
return 0;
}

И это должно сработать? Но, по моему, нужно возвращать 0, чтобы пользовательский mmap не завершился с ошибкой и как в этом случае соотносятся адресное пространство ядра (драйвера) и пользовательское.
Но чувствую, я уже достаточно близко подобрался к разгдке сей Linux тайны. Уже могу создать общий для драйвера и пользовательской программы буфер, чтобы работать с ним указательными операциями. Правда беда в том, что буфер етот расположен не знамо где, а мне нужно там где знамо.
Вернуться к началу
Борис
Гость





СообщениеДобавлено: Ср Июл 02 2003 12:59    Заголовок сообщения: Re: Что и все? Ответить с цитатой

С точки зрения C/C++ должен работать такой твой вариант (p_device, естественно, должен быть видим для всех функций драйвера):

...
p_device= __ioremap(PHYS_ADDR, LEN, 0);
...

int drv_mmap(...)
{
  return p_device;
}

Но ты совершенно верно беспокоишься по поводу прав драйверного и пользовательского процессов.

>>> по моему, нужно возвращать 0, чтобы пользовательский mmap не завершился с ошибкой и как в этом случае соотносятся адресное пространство ядра (драйвера) и пользовательское.

Я, к сожалению, вплотную этим не занимался, поэтому только предположу, что в драйверной функции drv_mmap() нужно понизить права и только потом возвратить указатель. (В этом и состоит концепция "процесс в ядре в режиме пользователя".) Еще, конечно, перед понижением прав не забыть установить специальный флаг, сигнализирующий о захвате устройства прикладным процессом. Но еще раз напоминаю, что это только общие соображения, и очень вероятно, что ты тут знаешь больше меня.
Вернуться к началу
werter
Гость





СообщениеДобавлено: Чт Июл 03 2003 12:50    Заголовок сообщения: Re: Программеры АААААА!!!!! Ответить с цитатой

Уфф, Вроде разобрался

Не понимаю почему заработало, но факт - работает.
Просто убрал из кода драйвера то, что было явно ненужно.

И протестировал это дело на видеопамяти не из-под VMWare, а из просто Linux. Хочется надеяться, что и для других устройств ето будет работать.

Спасибосибочки огромное.
Будем искать новые заморочки...
Вернуться к началу
Борис
Гость





СообщениеДобавлено: Чт Июл 03 2003 15:59    Заголовок сообщения: Рассказал бы, что ли, что было, как решил. Думаю, многим (мне точно) будет интересно. (-) Ответить с цитатой

-
Вернуться к началу
werter
Гость





СообщениеДобавлено: Пт Июл 04 2003 12:40    Заголовок сообщения: Re: Рассказал бы, что ли, что было, как решил. Думаю, многим (мне точно) будет интересно. (-) Ответить с цитатой

Идея следующая: создать два указателя на один и тот же физический адрес некоторого устройства. Причем один указатель должен быть в драйвере, а второй в пользовательской программе. В качестве тестового устройства я взял память видеоадаптера. Физическия адрес начала этой памяти можно посмотреть где угодно, а в частности в /proc/pci или самому программно определить етот адрес.
Да не стоит проверять из под VMWare (у меня Linux запускался из под WinXP). И возможны проблемы из-за собственно видеокарты.
У меня на рабочей машине все работает, а на домашней попытка напрямую писать в видеопамять приводит к перезагрузки машины (возможно потому, что Linux находится в консольном текстовом режиме, может какие то аппаратные глюки именно из-за этого).
Если все правильно сработает, то запись в видеопамять каких то байтов приведет к появлению на экрае разных (бессмысленных) символов определенного цвета, соответствующих передаваемым байтам.

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

--------------------------------------
Драйвер:

#defien LEN (64*1024);//размер выделяемой памяти должен быть кратен 64кБ, но возможно это не обязательно (хотя скорее всего обязательно)

u_long phys_addr= 0xabcdefg1;//к примеру

char *device_buf;//указатель на память устройства

device_buf= __ioremap(phys_addr, LEN); //так можно создать указатель на память устройства в драйвере.

iounmap(device_buf);// так выделенная ранее в драйвере память освобождается.

//через следующую функцию пользовательская программа настраивает свой указатель на заданный физический адрес.
int my_mmap(struct file *file, struct vm_area_struct *vma)
{
u_long user_buf;
u_long addr, leng;
user_buf= vma->vm_start;//получить виртуальный пользовательский адрес, через который пользовательская програ должна получить доступ к физическому адресу

addr= phys_addr;
или
addr= vma->vm_offset;//если пользовательская программа сама хочет указать к какому физическому адресу ей нужен доступ

leng= vma->vm_end - vma->vm_start; //размер запрашиваемой памяти (Linux автоматически делает кратным 64кБ)

//далее происходит собственно отображение памяти
if(remap_page_range(user_buf, addr, leng, vma->vm_page_prot)) return ERROR;

/*
указатель драйвера еще можно настроить таким образом
device_buf= (char*) user_buf;
но это имеет смысл делать только после успешного отображения пользовательского буфера, например в ioctl или гдето еще.
Но в этом случае виртуальный адрес пользовательского и драйверного указателя будет один и тот же (пользовательский), но проблем с доступом к нему из драйвера не будет (если наоборот, то были бы проблемы с правами доступа, а как их менять я неразбирался и думаю это не просто(какой нибудь массив структур, в котором надо кучу параметров изменить)).
*/

return 0;
}

-------------------------------
Пользовательская программа:

#defien LEN (64*1024)
char *buf;
int fd;
u_long phys_addr=0;
fd= open("/dev/xxx", IO_RDWR);
buf= mmap(0, LEN, ...
Вернуться к началу
Показать сообщения:   
Этот форум закрыт, вы не можете писать новые сообщения и редактировать старые.   Эта тема закрыта, вы не можете писать ответы и редактировать сообщения.    Список форумов Архив форумов ЦИТФорума -> Unix Часовой пояс: 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
Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Подробнее...