Linux за българи: Форуми

Програмиране => Общ форум => Темата е започната от: Lord Bad в Aug 08, 2006, 16:10



Титла: Работа с големи буфери в ядрото
Публикувано от: Lord Bad в Aug 08, 2006, 16:10
Здравейте!
Имам сериозен проблем и се нуждая от помощ. Проблема е следния - работя по драйвер който да заделя големи буфери от линейна памет в ядрото и после ги прехвърля в user space-a, където потребителска програма го обработва. За да заделя толкова голям буфер използвам следната техника:
Ако имам 32М оперативна памет стартирам Линукс с boot arg mem=30M, за да запазя от употреба от страна на ядрото(и евентуална фрагментация) последните 2М. После в драйвера правя следното нещо:
Примерен код

    volatile void *remapped;
    unsigned long trial_size = 0x100000; // 1MB

    printk(KERN_INFO "Allocator module was loaded successfully!\n");
    
    remapped = ioremap(0xA1E00000, trial_size);

    if (!remapped)
      return -1;
    
    printk(KERN_INFO "Allocator module mapped memory successfully!\n");


На този етап аз имам указател към 1М блок от памет, която мога да си правя каквото си искам. Остава само да мапна същия физически адрес и в user space-a и да изчета съдържанието на буфера. За съжаление нямам идея как мотова може да стане, а без такъв начин от техниката не би имало особен смисъл...


Титла: Работа с големи буфери в ядрото
Публикувано от: sdr в Aug 08, 2006, 17:44
Моята добрата стара механична памет ми подсказа
splice незнам дали има нещо общо с тебе и твоя проблем но друго просто не се сетих :( а доколкото знам кернелмемори-то никога не се свапва и ако сам не си я фрагментираш няма как да се фрагментира та...





Титла: Работа с големи буфери в ядрото
Публикувано от: в Aug 08, 2006, 17:47
Ъъъъъм, това е интересен въпрос, всъщност не е невъзможно.

Да предадеш pointer към данни от кърнълспейс към юзърспейс-а и оттам да си ги четеш естествено няма да стане, поради ред причини, едната от които е, че от гледна точка на юзърския процес, адресът от указателя сочи към съвсем различно място във физическата памет (не виждам как при многозадачна операционна система нещата да не стоят така).

Да приемем, че юзърския процес има съответните привилегии (уид0), единият сигурен начин да направиш това  е чрез /dev/mem (/dev/kmem сигурно щеше да върши перфектна работа, ама тц, не става така от доста време насам)). Вероятно може да се спретне друг трик, но наистина нямам идея.

Друг е въпроса, че не е нужно (а и вероятно е малко грубо) трансфера на данни да става по такъв начин - иначе начини колкото искаш - примерно сокети, copy_to_user() - последното вероятно е точно това, което ти трябва.

Между другото, какъв драйвер разработваш, че ти трябват такива обеми данни? Просто ми стана интересно...


Титла: Работа с големи буфери в ядрото
Публикувано от: в Aug 08, 2006, 17:53
а, да не забравя че можеш и през procfs, стига да те удовлетворява и да имаш желание...


Титла: Работа с големи буфери в ядрото
Публикувано от: в Aug 08, 2006, 19:57
Аааа сега погледнах и примерния код, защо го правиш с ioremap(), а не с kmalloc(), ако си сигурен че така и с този адрес няма да имаш проблеми при x86, при други архитектури не е гаранция предполагам..

Със сигурност copy_to_user() в твоят вариант, за tee/splice нямам идея, предполагам и това  е вариант, поне в по-новите ядра.

Performance-a важен ли е? Тогава разните procfs/pipe/socket глупости могат да се окажат спънка предполагам..


Титла: Работа с големи буфери в ядрото
Публикувано от: Lord Bad в Aug 09, 2006, 09:46
Ами значи архитектурата не е x86 въобще, а е АRM(PXA255). По принцип в момента драйвера има работеща версия която е с copy_to_user, но заради ограниченията на функцията това вкарва сериозно забавяне на производителността. За какво точно става дума - имам аз един(даже 2) CMOS сензора които правят снимки с доста голяма скорост, пращят ги на един ДСП процесор, той ги обработва и ги праща на АРМ-а. Взехме решение тук че ако работим с един голям буфер вместо с много малки вероятно ще си увеличим производиелността по следния начин. Maр-ваме колкото памет ни трябва от тази на АРМ-а с ioremap, пишем там картинките и после вместо да копираме този голям буфер в user space да се опитаме да map-нем и от там същия физически адрес и прочетем направо съдържанието на него, което ефективно ще ни спести адски много копиране... Само дето там ударих на камък - мисля си по настоящем да се опитам да направя това с mmap и /dev/mem наистина, но ако някой има по-добра идея ще се радвам да я чуя...


Титла: Работа с големи буфери в ядрото
Публикувано от: в Aug 09, 2006, 10:29
Хм, доколкото знам uClinux вероятно ще е добър вариант - разработван е специално за разни embedded джаджи и няма paging и address separation, което предполагам означава, че съвсем спокойно би могло потребителския процес да адресира "чужда" памет, въпреки че никога не съм си играл с това и не гарантирам, просто съм чел. Не знам дали ще свърши работа точно във вашия случай, но се надявам.

Апропо, през /dev/mem няма да постигнеш някакво особено подобрение в скоростта според мен, защото се минава през достатъчно много "утежняващи" моменти и в крайна сметка нищо чудно с copy_to_user да върви по-бързо.


Титла: Работа с големи буфери в ядрото
Публикувано от: в Aug 09, 2006, 10:41
Между другото като отвориш /dev/mem и mmap-неш част от съдържанието му (подобно нещо прави X-a за да пише директно в някакъв регион от паметта, заради графиката) - трябва да се замислиш дали това не прави нещо подобно на copy_to_user() - т.е "експорт-натата" чрез /dev физическа памет просто се копира в регион от физическата памет, заделен от потребителския процес. Тъй като това се извършва в userspace вероятно дори ще е по-бавно. Поне според мен, не съм някакъв експерт по ядрата и драйверите, така че питай все пак някой, който се занимава изключително с това, може и да има  някакъв хитър номер, който да свърши работа.


Титла: Работа с големи буфери в ядрото
Публикувано от: sdr в Aug 09, 2006, 11:13
Защо не завъртите нещата: suer land-a да алокира памет и да я подаде на кернела той да я локне и да си маже по нея Така ми се струва че ще е по-лесно


Титла: Работа с големи буфери в ядрото
Публикувано от: в Aug 09, 2006, 11:38
Защото идеята е нещата да вървят в обратната посока - камерите capture-ват изображения, драйвера в ядрото ги изчита от някакъв абсолютен адрес във физическата памет и трябва по някакъв начин да ги подаде към приложенията, които работят с тях, т.е не е идеята приложенията да подават информация към ядрото, а то към хардуера, просто характера на хардуера е такъв, на камерите надали нещо се подава освен може би някакви команди за инициализация..


Титла: Работа с големи буфери в ядрото
Публикувано от: в Aug 09, 2006, 11:50
Уф чакай, не съм разбрал добре, съжалявам.

Проблемът е че това няма да изключи момента с копирането, а и кодът бая ще се утежни. Значи драйвера в ядрото ще трябва да знае къде точно се намира заделената от процеса памет - нещо което няма да е толкова лесно, защото трябва да се правят сметки, да се гледат разни алокатори и т.н глупости. Нямам много идея за АRМ архитектурата и дали там съществува понятието swapping, но ако malloc-натата памет от процеса по някакъв начин влезе в swap-а ще стане доста мътна и кървава. При което въпреки всичко накрая ще трябва да се изкопира  съдържанието на паметта от адрес 0xA1E00000 върху мястото където е заделената памет от процеса и няма да има особено подобрение.


Титла: Работа с големи буфери в ядрото
Публикувано от: Lord Bad в Aug 09, 2006, 12:51
Аз тука направих следните неща междудругото - набих един 16 байтов низ в буфера от драйвера в цикъл така че да се запълни целия буфер и след това реших да проверя дали ще имам достъп както си мислех до буфера през /dev/mem. За целта написах набързо следната програмка:

Примерен код

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>

int main(void)
{
   int mem_fd, i;
   char test_string[] = "0123456789abcde";
   volatile void *mapped;

   if ((mem_fd = open("/dev/mem", O_RDONLY)) < 0) {
      printf("\n\nProblem in opening /dev/mem");
      exit(-1);
   }

   mapped = mmap(0, 0x100000, PROT_READ | PROT_WRITE, MAP_FIXED, mem_fd, 0xA1E00000);

   if (!mapped)
      return -1;

   printf("Mmap mapped memory successfully!\n");

      for (i = 0; i < 0x100000; i += 16) {
      printf("Current i is : %d\n", i);
      if (strncmp((char *)(mapped) + i, test_string, 16)) {
         printf("Compare failure, i = %d!\n", i);
         printf("mapped : %s\n", (char *)mapped);
         break;
      }
    }

    munmap(0, 0xA1E00000);

   return 0;
   
}


Само дето веднага като я пусна(като root разбира се) следва това:
Цитат
-bash-2.05b# ./readmem
Mmap mapped memory successfully!
Current i is : 0
Segmentation fault

Някакви идеи - в гугъл една хубава и изчерпателна статия не мога да намеря за /dev/mem, ако не измисля нещо друго ще пробвай след малко и read от /dev/mem...


Титла: Работа с големи буфери в ядрото
Публикувано от: в Aug 09, 2006, 13:55
А ако пробваш просто да четеш файла, без да го мап-ваш в паметта (lseek/read) какво се случва, пак ли сегфолтва?

Мисля че съм чел за някакви дивотии свързани с mmap-ване на /dev/mem и някакви региони от паметта дето били маркирани от ядрото по начин, който не позволявал да може да се мап-ват в паметта, но нямам идея, ще се разтърся в гугъл-а да проверя..


Титла: Работа с големи буфери в ядрото
Публикувано от: Lord Bad в Aug 09, 2006, 16:09
Ами да пак нещо гърми но поне няма seg fault:
Примерен код
   charp = (char *)malloc(16);
   lseek(mem_fd, 0xA1E00000, SEEK_CUR);
   ret = read(mem_fd, charp, 16);

   printf("Ret is %d\n", ret);
   printf("Charp is %s\n", charp);

Цитат
-bash-2.05b# ./readmem
Ret is -1
Charp is

А очакваните стойности за ret и charp са съответно 16 и 0123456789abcde... Мама му, почна да ми лази по нервите сериозно това...


Титла: Работа с големи буфери в ядрото
Публикувано от: в Aug 09, 2006, 16:32
Ми недей да се нервираш, дай да видим защо четенето се дъни...

Цитат

#include <errno.h>
int ern;
...
ret = read(mem_fd, charp, 16);
if (ret <0 ) {ern=errno;printf ("We have error#%d",ern);}
...


Може би ще помогне да разберем какво става, защо не иска да чете...


Титла: Работа с големи буфери в ядрото
Публикувано от: Lord Bad в Aug 10, 2006, 11:27
Цитат
Error reading mem_fd, error 14 : Bad address
Ret is -1
Charp is

Не е изненада за мен де:) Мисля си че сигурно офсета не трябва да е такъв, лошо че колегата дето разбира повече от хардуера е болен... Ще продължавам да го мъча.


Титла: Работа с големи буфери в ядрото
Публикувано от: в Aug 10, 2006, 11:51
EFAULT - buf is outside your accessible address space.


Не знам защо ми хрумна, но я пробвай така:

char *charp=malloc(16);
...
ret = read(mem_fd, charp, 16);

Би трябвало грешката да идва оттам, че четеш от файла повече байтове, отколкото ти е буфера, което не изглежда логично, но не знам...пробвай също да изчетеш не 16, ами 8 и после 4 байта, и аз не знам защо, но просто да сме сигурни че не е някаква малоумна ситуация. Въпреки че си изглежда наред.


Титла: Работа с големи буфери в ядрото
Публикувано от: Lord Bad в Aug 10, 2006, 12:22
Пробвах предложенията ти, макар да не бях никак убеден че е такъв проблема - продължавам да получвам същите грешки, което ме убеждава че проблема че май не адресирам правилните адреси. Ще видя какво казва книгата Linux Device Drivers, 3rd edition по въпроса...


Титла: Работа с големи буфери в ядрото
Публикувано от: в Aug 10, 2006, 13:06
:)
Написах си подобна програмка тук (х86). Забелязвам, че с някои offsets спокойно се чете, с други read връща същата грешка като при теб.

Според мен ядрото маркира някои региони от паметта като in use или нещо от сорта и не дава достъп до тях през /dev/mem, поне друго обяснение за проблема нямам.

Странното е че примерно ако направя cat /dev/mem > file, то после големината на файла е точно толкова колкото на ZONE_NORMAL (896MB), като все пак накрая избълва грешка, но тя предполагам идва оттам че се опитва да чете след края на адресното пространство. Би трябвало да изпищи за някаква грешка доста преди това, че не е успяло да изчете нещо от файла, но не е такъв случая :)

Верно голяма мистерия :) П.П - не знаех че толкова интересни неща си стояли в cleartext в рам-та, някои програмери са за убиване :)

Цитат

gat3way:/# grep --binary-file=text <parolata_za_usera_mi> /dev/mem 2>/dev/null|wc -l
18


Титла: Работа с големи буфери в ядрото
Публикувано от: в Aug 10, 2006, 13:10
Хахахаххаха лелелелле това не го бях очаквал :)

Цитат

gat3way:/# grep --binary-file=text "eba " /dev/mem 2>/dev/null|wc -l
1377


Наистина стана така ахаххаха. "eba " is leet :)


Титла: Работа с големи буфери в ядрото
Публикувано от: the_real_maniac в Aug 10, 2006, 13:21
Цитат (Lord_Bad @ Авг. 09 2006,10:46)
За какво точно става дума - имам аз един(даже 2) CMOS сензора които правят снимки с доста голяма скорост,

offtopic:

Интересна дискусия си водите :-) Евалата или браво :-D

Аз обаче имам едно питане извън темата относно CMOS сензорите. Доколото се разбира си в БГ ?
Ако да - какъв модел са CMOS сензореите и откъде ги взехте ?


Титла: Работа с големи буфери в ядрото
Публикувано от: Lord Bad в Aug 10, 2006, 13:51
Сензорите са National, но тях ги купиха Кодак наскоро така че може да ги броиш за Кодак. Модела точно не го знам понеже аз съм главно по софтуерното осигуряване и някои хардуерни детайли ми убягват. Не знам дали въобще такива се продават в България. Ние знам че ги купуваме от Виена.

А иначе по темата - баси на мем и греп-а ми дава seg fault. Да го такова у /dev/mem-a. Ся гледам някфа алтернатива boot mem alloc, ама ми се види уникално мръсно... Трябва драйвера да е вграден в имиджа на ядрото за да може да заделя памет при boot - мръсна история. Другия вариант който се сещам  е ако не измисля как да станат нещаат с /dev/mem да направя /dev/myalloc - някакъв character device, да му сложа един vma и да мапвам него ама бая писане ще падне...





Титла: Работа с големи буфери в ядрото
Публикувано от: ivak в Aug 11, 2006, 10:40
Lord_Bad,

мисля че има готово решение за твоя случай.
прегледай файла drivers/media/video/video-buf.c


Титла: Работа с големи буфери в ядрото
Публикувано от: kennedy в Aug 11, 2006, 16:02
хммм това което правиш някак си ще му намеря приложение при мен. Имам само 1 въпрос. Това процесорче, колко кадара ще може да обработи като картинки (в смисъл ако се ползва за ахранителна камера или нещо подобно)?


Титла: Работа с големи буфери в ядрото
Публикувано от: Lord Bad в Aug 11, 2006, 17:02
@ivak,
Ще го погледна макар че на пръв поглед ми се струва че този драйвер използва dma а ние се надявахме да избегнем това. Мерси все пак.

@kennedy,
Ами не мога да ти кажа цифра точна, но няма да са никак малко - процесора е адски бърз и скъп - все пак е от серията TMS320C6000. Целта на проекта - от две стерео изображения да се създаде триизмерно...


Титла: Работа с големи буфери в ядрото
Публикувано от: ivak в Aug 11, 2006, 17:49
Цитат (Lord_Bad @ Авг. 11 2006,17:02)
@ivak,
Ще го погледна макар че на пръв поглед ми се струва че този драйвер използва dma а ние се надявахме да избегнем това. Мерси все пак.


video_buf е предназначен именно за фрейм грабери, които сипват данни през DMA. всъщност, проблем с линейната памет има само тогава. ако ползваш PIO, можеш да пишеш където си поискаш, включително и да работиш изцяло в user space. ако пък имаш dual port memory, можеш да я mmap-неш без никакви проблеми.

апропо, какъв е интерфейсът на твоите имидж сензори? опиши накратко каква ти е постановката. евентулно бих могъл да ти дам някоя идея; правил съм подобни неща в миналото, макар и за x86.


Титла: Работа с големи буфери в ядрото
Публикувано от: kennedy в Aug 11, 2006, 19:39
малееее може да ми свърши работа ако е на поносима цена де ....


Титла: Работа с големи буфери в ядрото
Публикувано от: mhydra в Aug 11, 2006, 23:04
Ами поносима е ..... като го купиш едно такова и после 1 година ще имаш възможност да му носиш изплащането. :D  :D


Титла: Работа с големи буфери в ядрото
Публикувано от: Boiler в Aug 24, 2006, 18:18
Lord_Bad, направи ли го все пак драйвера или още имаш нужда от помощ? Има една статия: Developing a Linux Driver for the StrongARM Platform. Малко е постничка, но има нещо в нея.


Титла: Работа с големи буфери в ядрото
Публикувано от: Lord Bad в Sep 07, 2006, 15:37
Съжелявам за дългото прекъсване по темата, но излязох в отпуск точно след последния си пост. Сега тъкмо се захващам пак с историята и нещата все още не изглеждат добре. Големия ми мерак продължава да е да направя успешен mmap на /dev/mem, но все още не се получава по необяснима причина. Какъвто и да е проблема силно се съмнявам че той е свързан с ARM процесора. Както и да е, за заинтересованите ще публикувам още веднуж актуалната версия на драйвера който ме тормози и на програмката с която тествам работата му.
Драйвера:
Примерен код
#include <linux/version.h>
#include <linux/config.h>
#include <linux/module.h>
#include <linux/vmalloc.h>

#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/proc_fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/fcntl.h>   /* O_ACCMODE */
#include <linux/seq_file.h>
#include <linux/cdev.h>

#include <asm/page.h>
#include <asm/io.h>

#include "hpialloc.h"

int hpialloc_major = HPIALLOC_MAJOR;
int hpialloc_minor = 0;
int hpialloc_nr_devs = HPIALLOC_NR_DEVS;

module_param(hpialloc_major, int, S_IRUGO);
module_param(hpialloc_minor, int, S_IRUGO);
module_param(hpialloc_nr_devs, int, S_IRUGO);

MODULE_AUTHOR("Bozhidar Bastov");
MODULE_LICENSE("GPL");

struct hpialloc_dev *hpialloc_devices;

/*
 * Open and close
 */

int hpialloc_open(struct inode *inode, struct file *filp)
{
   struct hpialloc_dev *dev; /* device information */

   dev = container_of(inode->i_cdev, struct hpialloc_dev, cdev);
   filp->private_data = dev; /* for other methods */

   return 0;          /* success */
}

int hpialloc_release(struct inode *inode, struct file *filp)
{
   return 0;
}

struct file_operations hpialloc_fops = {
   .owner =    THIS_MODULE,
   .llseek =   NULL,
   .read =     NULL,
   .write =    NULL,
   .ioctl =    NULL,
   .open =     hpialloc_open,
   .release =  hpialloc_release,
};

/*
 * Finally, the module stuff
 */

/*
 * The cleanup function is used to handle initialization failures as well.
 * Thefore, it must be careful to work correctly even if some of the items
 * have not been initialized
 */

void hpialloc_cleanup_module(void)
{
   int i;
   dev_t devno = MKDEV(hpialloc_major, hpialloc_minor);

   /* Get rid of our char dev entries */
   if (hpialloc_devices) {
      for (i = 0; i < hpialloc_nr_devs; i++) {
         cdev_del(&hpialloc_devices[i].cdev);
      }
      kfree(hpialloc_devices);
   }

   /* cleanup_module is never called if registering failed */
   unregister_chrdev_region(devno, hpialloc_nr_devs);

   printk(KERN_WARNING "hpialloc: smpd module unloaded!\n");

}

/*
 * Set up the char_dev structure for this device.
 */

static void hpialloc_setup_cdev(struct hpialloc_dev *dev, int index)
{
   int err, devno = MKDEV(hpialloc_major, hpialloc_minor + index);
    
   cdev_init(&dev->cdev, &hpialloc_fops);
   dev->cdev.owner = THIS_MODULE;
   dev->cdev.ops = &hpialloc_fops;
   err = cdev_add (&dev->cdev, devno, 1);
   /* Fail gracefully if need be */
   if (err)
      printk(KERN_NOTICE "Error %d adding hpialloc%d", err, index);
}


int hpialloc_init_module(void)
{
   int result, i;
   dev_t dev = 0;
   volatile void *remapped;
    unsigned long trial_size = 0x100000; // 1MB
   char test_string[] = "0123456789abcde"; // 16 bytes

/*
 * Get a range of minor numbers to work with, asking for a dynamic
 * major unless directed otherwise at load time.
 */
   if (hpialloc_major) {
      dev = MKDEV(hpialloc_major, hpialloc_minor);
      result = register_chrdev_region(dev, hpialloc_nr_devs, "hpialloc");
   } else {
      result = alloc_chrdev_region(&dev, hpialloc_minor, hpialloc_nr_devs,
            "hpialloc");
      hpialloc_major = MAJOR(dev);
   }
   if (result < 0) {
      printk(KERN_WARNING "hpialloc: can't get major %d\n", hpialloc_major);
      return result;
   }

    /*
    * allocate the devices -- we can't have them static, as the number
    * can be specified at load time
    */
   hpialloc_devices = kmalloc(hpialloc_nr_devs * sizeof(struct hpialloc_dev), GFP_KERNEL);
   if (!hpialloc_devices) {
      result = -ENOMEM;
      goto fail;  /* Make this more graceful */
   }
   memset(hpialloc_devices, 0, hpialloc_nr_devs * sizeof(struct hpialloc_dev));

   /* Initialize each device. */
   for (i = 0; i < hpialloc_nr_devs; i++) {
      hpialloc_setup_cdev(&hpialloc_devices[i], i);
   }
                                    
   printk(KERN_WARNING "hpialloc: hpialloc module loaded!\n");

       
    remapped = ioremap(0xA1E00000, trial_size);

    if (!remapped)
      return -1;

   printk(KERN_INFO "hpialloc: hpialloc module mapped memory successfully!\n");

   for (i = 0; i < trial_size; i += 16) {
      strcpy((char *)(remapped) + i, test_string);
        if (strcmp((char *)(remapped) + i, test_string)) {
         printk(KERN_INFO "Compare failure, i = %d!\n", i);
         printk(KERN_INFO "remapped : %s\n", (char *)remapped);
         break;
      }
    }

   for (i = 0; i < trial_size; i += 16) {
      strncpy(test_string, (char *)(remapped) + i, 16);
        if (strcmp((char *)(remapped) + i, test_string)) {
         printk(KERN_INFO "Compare failure, i = %d!\n", i);
         printk(KERN_INFO "remapped : %s\n", (char *)remapped);
         break;
      }
    }

    //iounmap((void *)remapped);
   
   return 0; /* succeed */

  fail:
   hpialloc_cleanup_module();
   return result;
}


module_init(hpialloc_init_module);
module_exit(hpialloc_cleanup_module);


Тестовата програма:

Примерен код
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>

int main(void)
{
   int mem_fd, i, ret;
   char test_string[] = "0123456789abcde";
   volatile void *mapped;
   char *charp;

   if ((mem_fd = open("/dev/mem", O_RDONLY)) < 0) {
      printf("\n\nProblem in opening /dev/mem");
      exit(-1);
   }
   
   
   mapped = mmap(0, 0x100000, PROT_READ | PROT_WRITE, MAP_FIXED, mem_fd, 0x01E00000);

   if (!mapped)
      return -1;

   printf("Mmap mapped memory successfully!\n");

   for (i = 0; i < 0x100000; i += 16) {
      printf("Current i is : %d\n", i);
      if (strncmp((char *)(mapped) + i, test_string, 16)) {
         printf("Compare failure, i = %d!\n", i);
         printf("mapped : %s\n", (char *)mapped);
         break;
      }
   }
     

   munmap(0, 0xA1E00000);

   /*   
   charp = malloc(16);
   lseek(mem_fd, 0xA1E00000, SEEK_CUR);
   ret = read(mem_fd, charp, 16);
   if (ret < 0)
      printf("Error reading mem_fd, error %d : %s\n", errno, strerror(errno));

   printf("Ret is %d\n", ret);
   printf("Charp is %s\n", charp);

   */
   return 0;
   
}



Съзнавам че кода е доста дълъг за един форум, но в драйвера не гледайте всичко наред. Само hpialloc_init_module е важна, другите като изключим cleanup-a са за да има entry драйвера в /dev файловата система. Това се случва като тествам драйвера аз:
Примерен код
-bash-2.05b# insmod hpialloc.ko
hpialloc: hpialloc module loaded!
hpialloc: hpialloc module mapped memory successfully!
-bash-2.05b# ./readmem
Mmap mapped memory successfully!
Current i is : 0
Segmentation fault


Ако някой се сети нещо, което може да ми помогне ще съм много благодарен.


Титла: Работа с големи буфери в ядрото
Публикувано от: Lord Bad в Sep 08, 2006, 13:41
Гледам никой нищо май няма да каже, та ще споделя с вас последните си разкрития, които ме отказаха да ползвам mmap /dev/mem... Написах следната програма, която просто трябва да сканира оперативната памет и да определи размера и чрез /dev/mem:
Примерен код
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>

int main()
{
   int mem_fd, ret;
//   char var_char[4];
   char *charp;
   int count = 0;

   if((mem_fd = open("/dev/mem",O_RDONLY)) < 0){
      printf("\n\nProblem in opening /dev/mem");
      exit(-1);
   }

   ret = 1;
   charp = (char *)malloc(sizeof(char) * 1024 * 1024);
   
   while(ret > 0){
      ret = read(mem_fd, charp,sizeof(char) * 1024 *1024);
      printf("\nret:%d",ret);
      if (ret > 0)
         count++;
   }
   
   printf("\nMemory Read:%d MB",count);

   exit(0);
}


Като го тествах на служебния ми комп, на който върви Федора 5 с ядро  2.6.17 резултата беше следния:
Примерен код
[root@bozhidar hpialloc]# ./read_mem

ret:1048576
ret:-1
Memory Read:1 MB



А на ARM-a полежението е още по-зле:
Примерен код
-bash-2.05b# ./read_mem_linux
Unable to handle kernel paging request at virtual address 20000000
pgd = c18e0000
[20000000] *pgd=00000000
Internal error: Oops: f5 [#3]
Modules linked in:
CPU: 0
PC is at .c2u_0fupi+0xc/0x50
LR is at read_mem+0x74/0xa4
pc : [<c00a6c60>]    lr : [<c00aec70>]    Not tainted
sp : c1be1f1c  ip : 00000000  fp : c1be1f50
r10: c1c9d0a4  r9 : 40149008  r8 : 00100000
r7 : fffffff2  r6 : c1c9d0a4  r5 : 00100000  r4 : 81249007
r3 : 00000000  r2 : 000ffffc  r1 : 20000000  r0 : 40149008
Flags: nzCv  IRQs on  FIQs on  Mode SVC_32  Segment user
Control: 397F  Table: A18E0000  DAC: 00000015
Process read_mem_linux (pid: 79, stack limit = 0xc1be00fc)
Stack: (0xc1be1f1c to 0xc1be2000)
1f00:                                                                00100000
1f20: 81249007 00100000 c1c9d0a4 fffffff2 c00aec70 00000000 c1c9d080 00000000
1f40: 00000000 c1be1f84 c1be1f54 c006112c c00aec08 c0056d8c c1cbe680 fffffff7
1f60: 40149008 c1c9d080 00000003 c001d224 c1be0000 401421a0 c1be1fa4 c1be1f88
1f80: c006136c c0061050 00000000 4001d9cc befffe34 00008544 00000000 c1be1fa8
1fa0: c001d0a0 c0061338 4001d9cc c0023b08 00000003 40149008 00100000 00000001
1fc0: 4001d9cc befffe34 00008544 4000c85c 00000001 00008470 401421a0 befffe10
1fe0: 400e40a0 befffdf0 000084f0 400e40a4 60000010 00000003 9feb7c4a 3fd67f64
Backtrace:
[<c00aebfc>] (read_mem+0x0/0xa4) from [<c006112c>] (vfs_read+0xe8/0x120)
 r7 = 00000000  r6 = 00000000  r5 = C1C9D080  r4 = 00000000
[<c0061044>] (vfs_read+0x0/0x120) from [<c006136c>] (sys_read+0x40/0x5c)
[<c006132c>] (sys_read+0x0/0x5c) from [<c001d0a0>] (ret_fast_syscall+0x0/0x2c)
 r6 = 00008544  r5 = BEFFFE34  r4 = 4001D9CC
Code: 1a000037 e2522004 4282c004 4a000026 (e4913004)
 Segmentation fault
-bash-2.05b#



Затова отново прегледах из гугъл и разбрах следните неща - на х86 архитектурата това е работело в 2.14 сериите на ядро, но после в 2.16 са били направени промени и /dev/mem може да се ползва надеждно само за четене/писане по ioport-ове. Главния му потребител се оказва че е Х сървъра... В arm не е ясно дали някога е работело въобще затова сега ще търся други варианти...


Титла: Работа с големи буфери в ядрото
Публикувано от: gat3way в Sep 12, 2006, 12:02
Тъй...регистрирах се, блях

Ъм...при мен изхода от програмата е:

ret:1048576
ret:1048576
.....
......
ret:1048576
ret:-1
Memory Read:896 MB

896МВ е големината на ZONE_NORMAL, /dev/mem не дава достъп до ZONE_HIMEM, така че няма как да изчета останалата памет до 1280-тия мегабайт.

Т.е при мен няма проблем с изчитането.

Сега обаче като се замисля...вероятно причината за това е хардуерен. Доколкото знам първите 16MB се водят ZONE_DMA - т.е адресно пространство използвано за ДМА трансфери от ISA и някои PCI устройства..нямам обаче много ясна идея защо става така при теб.

Можеш ли да пейстнеш какво има в /proc/zoneinfo BTW?


Титла: Работа с големи буфери в ядрото
Публикувано от: Lord Bad в Sep 12, 2006, 12:54
Разбира се:
Цитат
[root@bozhidar hpialloc]# cat /proc/zoneinfo
Node 0, zone      DMA
  pages free     3096
        min      17
        low      21
        high     25
        active   0
        inactive 0
        scanned  0 (a: 0 i: 0)
        spanned  4096
        present  4096
        protection: (0, 0, 879, 1519)
  pagesets
  all_unreclaimable: 0
  prev_priority:     12
  temp_priority:     12
  start_pfn:         0
Node 0, zone   Normal
  pages free     48198
        min      939
        low      1173
        high     1408
        active   90048
        inactive 54868
        scanned  0 (a: 0 i: 0)
        spanned  225279
        present  225279
        protection: (0, 0, 0, 5119)
  pagesets
    cpu: 0 pcp: 0
              count: 175
              high:  186
              batch: 31
    cpu: 0 pcp: 1
              count: 9
              high:  62
              batch: 15
  all_unreclaimable: 0
  prev_priority:     12
  temp_priority:     12
  start_pfn:         4096
Node 0, zone  HighMem
  pages free     1045
        min      128
        low      298
        high     469
        active   82137
        inactive 77478
        scanned  0 (a: 0 i: 0)
        spanned  163825
        present  163825
        protection: (0, 0, 0, 0)
  pagesets
    cpu: 0 pcp: 0
              count: 158
              high:  186
              batch: 31
    cpu: 0 pcp: 1
              count: 10
              high:  62
              batch: 15
  all_unreclaimable: 0
  prev_priority:     12
  temp_priority:     12
  start_pfn:         229375