Здравствуйте, Аноним, Вы писали:
А>Вариант:
А>1. В kernel выделяешь кусок памяти ( DrvBuf ) ( kmalloc или ставь патч bigphysarea с http://www.polyware.nl/~middelink/En/hob-v4l.html#bigphysarea )
А>2. Регистрируешь в драйвере ( file_operations ) обработчик mmap, вида
А>int my_mmap( struct file* file, struct vma_area_struct* vma )
А>{
А> unsigned long size = vma->vm_end — vma->vm_start; /* == BufferLength см. ниже */
А> ...
А> return remap_page_range( vma_vm_start, __pa( DrvBuf ), size, vma->vm_page_prot );
А>}
А>3. Вызываешь из приложения mmap( NULL, BufferLength, PROT_READ | PROT_WRITE, MAP_SHARED, driverFD, 0 ). Этот вызов подцепить то, что ты зарегистрируешь в п.2
А>4. mmap возвратит приложению виртуальный отмапенный( ну и слово ) на userspace адрес буфера драйвера ( UserBuf ).
А>5. Далее
А> а) если писать в устройсво
А> Приложение записывает по UserBuf всё что нужно и пинает драйвер. Драйвер скармливает __pa( DrvBuf ) dma'ю или как там у тебя.
А> б) если читать, то всё наоборот
А>Кажись всё. Удачи!
Большое спасибо за помощь.
Для проверки предложенного вами варианта я написал небольшой драйверок и тестовое приложение.
В драйвере в mmap с помощью kmalloc выделяю память (256 байт) и пишу в каждый байт буфера число 55. В приложении вызываю mmap и пытаюсь читать память, выделенную в драйвере. Но чего-то не получается. Вместо записанного числа 55 выводятся одни нули.
В драйвере:
#include <linux/kernel.h>
#include <linux/mm.h>
#include "common.h"
char *KBuffer;
int DrvMmap(struct file* File, struct vm_area_struct* vma)
{
unsigned long i = 0;
unsigned long size = vma->vm_end - vma->vm_start;
/*
Мне необходимы буферы от 3 - 100 KB
Поэтому мне достаточно использовать kmalloc (как я понял, эта функция может выделять до 131056 байт)
*/
KBuffer = kmalloc(size, GFP_KERNEL);
if(NULL == KBuffer)
{
printk("testdrv: error! kmalloc can not alloc memory.\n");
return (-1);
}
for(i = 0; i < 256; i++) KBuffer[i] = 55;
return remap_page_range(vma->vm_start,
__pa(KBuffer),
size,
vma->vm_page_prot);
}
В приложении:
#define DEVICE "/dev/testdrv"
int Fd = -1;
char *AddrBuff;
int main(void)
{
mknod(DEVICE, S_IFCHR|S_IRWXU|S_IRWXO, (32<<8) | 0);
Fd = open(DEVICE, O_RDWR|O_NONBLOCK|O_NOCTTY);
AddrBuff = (char*) mmap(NULL,
256,
PROT_READ|PROT_WRITE,
MAP_SHARED,
Fd,
0);
if(AddrBuff == MAP_FAILED)
{
perror("mmap");
if( -1 == unlink(DEVICE)) perror("unlink");
return -1;
}
for(int i = 0; i < 256; i++) printf("%u, AddrBuff[i]);
return (0);
}
Что я сделал не так?
Где ошибся?