Титла: Работа с големи буфери в ядрото Публикувано от: Lord Bad в Aug 08, 2006, 16:10 Здравейте!
Имам сериозен проблем и се нуждая от помощ. Проблема е следния - работя по драйвер който да заделя големи буфери от линейна памет в ядрото и после ги прехвърля в user space-a, където потребителска програма го обработва. За да заделя толкова голям буфер използвам следната техника: Ако имам 32М оперативна памет стартирам Линукс с boot arg mem=30M, за да запазя от употреба от страна на ядрото(и евентуална фрагментация) последните 2М. После в драйвера правя следното нещо:
На този етап аз имам указател към 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. За целта написах набързо следната програмка:
Само дето веднага като я пусна(като root разбира се) следва това:
Някакви идеи - в гугъл една хубава и изчерпателна статия не мога да намеря за /dev/mem, ако не измисля нещо друго ще пробвай след малко и read от /dev/mem... Титла: Работа с големи буфери в ядрото Публикувано от: в Aug 09, 2006, 13:55 А ако пробваш просто да четеш файла, без да го мап-ваш в паметта (lseek/read) какво се случва, пак ли сегфолтва?
Мисля че съм чел за някакви дивотии свързани с mmap-ване на /dev/mem и някакви региони от паметта дето били маркирани от ядрото по начин, който не позволявал да може да се мап-ват в паметта, но нямам идея, ще се разтърся в гугъл-а да проверя.. Титла: Работа с големи буфери в ядрото Публикувано от: Lord Bad в Aug 09, 2006, 16:09 Ами да пак нещо гърми но поне няма seg fault:
А очакваните стойности за ret и charp са съответно 16 и 0123456789abcde... Мама му, почна да ми лази по нервите сериозно това... Титла: Работа с големи буфери в ядрото Публикувано от: в Aug 09, 2006, 16:32 Ми недей да се нервираш, дай да видим защо четенето се дъни...
Може би ще помогне да разберем какво става, защо не иска да чете... Титла: Работа с големи буфери в ядрото Публикувано от: Lord Bad в Aug 10, 2006, 11:27
Не е изненада за мен де ![]() Титла: Работа с големи буфери в ядрото Публикувано от: в 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), като все пак накрая избълва грешка, но тя предполагам идва оттам че се опитва да чете след края на адресното пространство. Би трябвало да изпищи за някаква грешка доста преди това, че не е успяло да изчете нещо от файла, но не е такъв случая ![]() Верно голяма мистерия ![]() ![]()
Титла: Работа с големи буфери в ядрото Публикувано от: в Aug 10, 2006, 13:10 Хахахаххаха лелелелле това не го бях очаквал
![]()
Наистина стана така ахаххаха. "eba " is leet ![]() Титла: Работа с големи буфери в ядрото Публикувано от: the_real_maniac в Aug 10, 2006, 13:21
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
video_buf е предназначен именно за фрейм грабери, които сипват данни през DMA. всъщност, проблем с линейната памет има само тогава. ако ползваш PIO, можеш да пишеш където си поискаш, включително и да работиш изцяло в user space. ако пък имаш dual port memory, можеш да я mmap-неш без никакви проблеми. апропо, какъв е интерфейсът на твоите имидж сензори? опиши накратко каква ти е постановката. евентулно бих могъл да ти дам някоя идея; правил съм подобни неща в миналото, макар и за x86. Титла: Работа с големи буфери в ядрото Публикувано от: kennedy в Aug 11, 2006, 19:39 малееее може да ми свърши работа ако е на поносима цена де ....
Титла: Работа с големи буфери в ядрото Публикувано от: mhydra в Aug 11, 2006, 23:04 Ами поносима е ..... като го купиш едно такова и после 1 година ще имаш възможност да му носиш изплащането.
![]() ![]() Титла: Работа с големи буфери в ядрото Публикувано от: 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 процесора. Както и да е, за заинтересованите ще публикувам още веднуж актуалната версия на драйвера който ме тормози и на програмката с която тествам работата му.
Драйвера:
Тестовата програма:
Съзнавам че кода е доста дълъг за един форум, но в драйвера не гледайте всичко наред. Само hpialloc_init_module е важна, другите като изключим cleanup-a са за да има entry драйвера в /dev файловата система. Това се случва като тествам драйвера аз:
Ако някой се сети нещо, което може да ми помогне ще съм много благодарен. Титла: Работа с големи буфери в ядрото Публикувано от: Lord Bad в Sep 08, 2006, 13:41 Гледам никой нищо май няма да каже, та ще споделя с вас последните си разкрития, които ме отказаха да ползвам mmap /dev/mem... Написах следната програма, която просто трябва да сканира оперативната памет и да определи размера и чрез /dev/mem:
Като го тествах на служебния ми комп, на който върви Федора 5 с ядро 2.6.17 резултата беше следния:
А на ARM-a полежението е още по-зле:
Затова отново прегледах из гугъл и разбрах следните неща - на х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 Разбира се:
|