Re[2]: Linux. Драйвер. Память.
От: unkn2000  
Дата: 22.12.03 09:49
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Вариант:


А>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);
}

Что я сделал не так?
Где ошибся?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.