LINUX.ORG.RU

Работа с памятью пользователя в драйвере


0

0

Есть драйвер chrdev. Раньше по DMA писал в системную область а потом с помощью copy_to _user переписвывал в память пользователя. Сейчас встала задача ускорить процесс. Подскажите, как сразу писать в память пользователя, т.е. получить ее физические адреса?


Ответ на: комментарий от xnix

>делать это крайне не рекомендуется.

Ашшо скажи что mmap фтопку ;)

По топику. Реализуй в драйвере file_operations.mmap +cм. remap_pfn_range и вообще как сия(mmap) операция реализуется в драйверах.

Токо придётся переточить юзерспейс под mmap (я так понимаю что сейчас у тебя юзается file_operations.read ?)

sS ★★★★★
()

А как драйвер может быть уверен, что страницы пользователя во время передачи будут в физической памяти по тому же адресу, а не где-нибудь в свопе?

zaregazza
()
Ответ на: комментарий от anonymous

Вот нашел интересный код в драйвере framebuffera. Вроде то, что мне надо. Сделал все аналогично. Ничего не виснет, только в памяти нет данных. Подскажите, почему?

static ssize_t pvr2fb_write(struct file *file, const char *buf,
			    size_t count, loff_t *ppos)
{
	unsigned long dst, start, end, len;
	unsigned int nr_pages;
	struct page **pages;
	int ret, i;

	nr_pages = (count + PAGE_SIZE - 1) >> PAGE_SHIFT;

	pages = kmalloc(nr_pages * sizeof(struct page *), GFP_KERNEL);
	if (!pages)
		return -ENOMEM;
	
	down_read(&current->mm->mmap_sem);
	ret = get_user_pages(current, current->mm, (unsigned long)buf,
			     nr_pages, WRITE, 0, pages, NULL);
	up_read(&current->mm->mmap_sem);

	if (ret < nr_pages) {
		nr_pages = ret;
		ret = -EINVAL;
		goto out_unmap;
	}

	dma_configure_channel(shdma, 0x12c1);
	
	dst   = (unsigned long)fb_info->screen_base + *ppos;
	start = (unsigned long)page_address(pages[0]);
	end   = (unsigned long)page_address(pages[nr_pages]);
	len   = nr_pages << PAGE_SHIFT;

lintim
() автор топика
Ответ на: комментарий от anonymous

Отличия минмальные. Полученыые по pages_address адреса + длина записывал в почтовые ящики и запускал устройство.

lintim
() автор топика
Ответ на: комментарий от lintim

Я кажется понял в чем проблема, page_address выдает виртуальный адрес. Нужно еще вызвать virt_to_bus для получения физического адреса. Поправте, если я не прав.

lintim
() автор топика
Ответ на: комментарий от lintim

если вы все еще хотите получить ответ на свой вопрос, то необходимо предоставить СВОЙ хорошо ОТФОРМАТИРОВАННЫЙ код, несмотря на то, что отличия от оригинального кода драйвера фреймбуфера минимальны.

С искренним уважением, A.

anonymous
()
Ответ на: комментарий от lintim

AFAIK, dma не работает с mmu.

С размером данных <=PAGE_SIZE должно получиться.

А вообще зачем такие извраты, copy_to_user быстрая.

xnix ★★
()
Ответ на: комментарий от xnix

Все не так просто. Драйвер работает на MB размером 4x8 см и процессор 166 Мгц. Как тормозит copy_to_buffer видно на глаз (по морганию лампочкой)

lintim
() автор топика
Ответ на: комментарий от lintim

>copy_to_buffer

Имелось в виду copy_to_user ?

На архитектуре i386/amd64(остальные не смотрел) copy_to_user работает следующем образом:

1)Проверяем , сто вписываемся в сегмент данных задачи(обычно 3гига) , чтоб не записать в область ядра. (access_ok)

2) _просто_ копируем, никаких проверок. Пофиг есть там страница или нет . Если page_fault, то ищем eip/rip в __ex_table, находим его, делаем fixup.

Так что скорость copy_to_user==memcpy.

xnix ★★
()
Ответ на: комментарий от xnix

> Имелось в виду copy_to_user ?

не кошерно....
для DMA см.
dma_addr =  (unsigned int*)dma_alloc_coherent(...)
для mmap() рыть -
remap_pfn_range(vma, vma->vm_start,  page_to_pfn(virt_to_page(dma_addr)),
vma->vm_end - vma->vm_start, vma->vm_page_prot)...
и всё прямо в user- space...

senji
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.