- Последний пост
- 14 авг.
- Последнее чтение
- 14 авг.
- Постов за неделю
- 1
- Всего постов
- 43
- Тип
- открытый
- Язык
- персидский
- В каталоге с
- 14 авг.
- 1/24сутки в ленте
- 11
- 1/48двое суток
- 12
- 1/72трое суток
- 13
Оценка по просмотрам недавних постов: пост набирает почти всё за первые сутки.
Посты
видео или голосовое, без подписи
گاهی اوقات سریعتر اجرا کردن، یعنی لو دادن اطلاعات محرمانه رویکردهای مختلفی برای تسریع کار سی پی یو وجود داره. یکیش بالا بردن فرکانسه، ولی همیشه ایدهی خوبی نیست، چون هرچی فرکانس رو بیشتر کنیم به گرما و مصرف توان غیرقابل قبول میرسیم. یه رویکرد دیگه که خیلی…
گاهی اوقات سریعتر اجرا کردن، یعنی لو دادن اطلاعات محرمانه رویکردهای مختلفی برای تسریع کار سی پی یو وجود داره. یکیش بالا بردن فرکانسه، ولی همیشه ایدهی خوبی نیست، چون هرچی فرکانس رو بیشتر کنیم به گرما و مصرف توان غیرقابل قبول میرسیم. یه رویکرد دیگه که خیلی جاها ازش استفاده میشه، همزمانیه (اجرای موازی). در نگاه ساده، سی پی یو باید دستورات رو یکییکی fetch، decode، execute کنه. ولی این رویکرد خیلی وقته عوض شده. طراحهای سختافزار به این نتیجه رسیدن که اگه بخوان دستور بعدی رو معطل کنن تا دستور قبلی کامل شه، عملاً دارن ریسورس هدر میدن. برای همین اومدن این سه مرحله رو بهصورت پایپ لاین چیدن، تا وقتی دستور اول در حال decode شدنه، fetch میتونه هم زمان بره سراغ دستور دوم، و دستور سوم هم پشت سرش تو صف باشه. دستور fetch فقط بایت خام دستور رو از I-Cache میاره، decode هم فقط تفسیرش میکنه که این دستور چیه و عملوندهاش کجان، و نتیجه رو میذاره تو یه صف (بافر دستورالعمل). تا اینجا هیچ محاسبهای انجام نشده، هیچ حافظهای دستکاری نشده (دستور فقط "توصیف" شده، نه اجرا) وقتی نوبت execute دستور میرسه. یعنی عملوند ها آماده ان و یه واحد اجرایی آزاده. محاسبه در همین مرحله انجام میشه برای مثال اگه یه load وجود داشته باشه، درخواست واقعی به حافظه فرستاده میشه و کش پر میشه. یه دستور میتونه کامل decode بشه و تو صف بشینه، ولی اگه قبل از رسیدن نوبتش سی پی یو صلاح بدونه که باید حذف بشه (Squash)، هیچ اثری از خودش تو کش یا هیچجای دیگه بهجا نمی ذاره. وقتی سی پی یو به یه if میرسه، تا نتیجهی شرط واقعاً محاسبه نشه نمیدونه دستور بعدی کدومه. و محاسبهی این نتیجه ممکنه چند سیکل طول بکشه، خصوصاً اگه به یه مقدار لود شده از حافظه وابسته باشه. اگه سی پی یو بخواد صبر کنه، پایپلاین چند سیکل خالی میمونه. برای پردازندهای که هدفش پرنگهداشتن پایپلاینه، این توقف اصلاً پذیرفتنی نیست. راهحلش پیشبینی شاخهست (Branch Prediction). سیپییو بهجای صبر کردن، بر اساس تاریخچهی رفتار همون شاخه حدس میزنه کدوم مسیر طی میشه، و میره سراغ fetch و decode همون مسیر پیشبینیشده. ولی حدس زدن به تنهایی کافی نیست. اگه فقط decode بشن و همونجا معطل بمونن، سود چندانی نداره. برای همین یه قدم جلوتر میره. این دستورا execute هم میشن، قبل از اینکه مشخص بشه پیشبینی درست بوده یا نه. یعنی محاسبات و loadها واقعاً روی سختافزار اتفاق میافتن، بدون هیچ تضمینی که این مسیر درسته. حالا برای اینکه این قمار امن بمونه، معماری پردازنده دو تا مفهوم رو از هم جدا میکنه: حالت معماریای (Architectural State) که همون چیزیه که برنامه میبینه (رجیسترها، حافظهی قابلمشاهده)، و حالت ریزمعماریای (Microarchitectural State) که فقط برای خود سختافزاره و برنامه بهش دسترسی مستقیم نداره (مثل کش، جدولهای پیشبین شاخه، بافرهای داخلی). نتیجهی دستورهای حدسی تو بافرROB نگه داشته میشه، و تا وقتی مطمئن نشن پیشبینی درست بوده، کامیت نمیشن. اگه معلوم بشه پیشبینی غلط بوده، رولبک اتفاق می افته. هرچی تو ROB مونده دور ریخته میشه، پایپلاین flush میشه، و از دید معماری انگار هیچی اتفاق نیفتاده. اما یه چیز هست که این وسط جا میمونه و پاک نمیشه: کش. اگه یه load حدسی زودتر از کشفشدن misprediction به execute رسیده باشه، درخواستش رو واقعاً فرستاده و داده رو واقعاً تو کش نشونده. کش اصلاً نمیدونه و اهمیتی هم نمیده که این درخواست از یه مسیر حدسی اومده یا از یه مسیر تأییدشده. اینجا دقیقاً یه مسابقهی زمانیه بین دو اتفاق: یکی اینکه کِی misprediction کشف میشه، یکی اینکه کِی اون load وابسته به مسیر حدسی به execute میرسه. هرچی پنجرهی حدسیبودن عمیقتر باشه، شانس بیشتری هست که اون load قبل از flush شدن واقعاً اجرا بشه و کش رو دستکاری کنه.
Some very good articles on Linux kernel, filesystems and GO https://internals-for-interns.com/series/
An analysis of Ext4 for digital forensics https://www.sciencedirect.com/science/article/pii/S1742287612000357
Understanding Linux device nodes - sysfs - devtmpfs - udev/mdev - major/minor numbers and everything in between https://ruvi-d.medium.com/understanding-linux-device-nodes-deaca8cb8069 #EmbeddedLinux
🤩 ۵۵٪ تخفیف برای تاریخ خاص ۰۵/۰۵/۰۵ آفر ویژهی خانه لینوکس ایران! از اون جایی که ما همیشه به دنبال یک تغییر واقعی در مسیر رشد و ارتقای شغلی شما هستیم، برای همراهی با شما در این روزها، در این روز خاص یک آفر ویژه براتون در نظر گرفتیم: 🎁 ۵۵٪ تخفیف روی تمام دورهها 👥 ویژه ۵۵ نفر اول ⏳ فقط تا پایان روز ۱۴۰۵/۰۵/۰۵ اگه مدتهاست به فکر ارتقای مهارت، ورود جدیتر به بازار کار یا ساختن مسیر حرفهای قویتر هستین، این فرصت رو از دست ندین ☺️ کنارتون هستیم.🤝 🔗 عناوین و زمانبندی دورهها 🔗 تکمیل فرم پیش ثبت نام 🔗 مشاوره تخصصی رایگان 🔗 وبسایت ما 🆔 ارتباط با ادمین: @iranlinuxhouse_anisa ☎️ راههای ارتباطی: 021-92009515 021-88712172 021-88716168 0910-8555111
دسترسی به دوایستری درون درایور فرض کنید که ما یه پریفرال خاص داریم که خودمون درایورش رو نوشتیم و توی دیوایستری مشخصات و پراپرتیهای لازمش رو تعریف کردیم سوال اینه که چجوری میشه از داخل درایور به پراپرتیهای این دوایس که توی دیوایستری تعریف شدن دسترسی داشت و جواب استفاده از api های کرنل مختص این کاره. مثلا api زیر رو در نظر بگیرید: of_find_node_by_path() این تابع یه مسیر میگیره و بهمون یدونه struct device_node* برمیگردونه. یا api زیر of_find_node_by_name() رو داریم که بجای path از ما label میگیره و struct device_node* برمیگردونه. یا با استفاده از api زیر میتونیم به لیست propertyهای یک نود دسترسی داشته باشیم: for_each_property_of_node() لیست کامل این apiها رو میتونین توی فایل زیر از کرنل ببینید: include/linux/of.h #EmbeddedLinux
استخراج دیوایستری اگه یه سیستم لینوکسی با یه شل دارین و لازمه که دیوایستری سیستم رو استخراج کنین، جالبه بدونین که dtc اینکار رو انجام میده: dtc -I fs /proc/device-tree -o exported.dts درواقع مسیر /proc/device-tree همواره دیوایستری سیستم رو به شکل فایلسیستم مجازی در اختیارمون قرار میده اما اگه لازم بود یدونه dts از این فایل سیستم مجازی استخراج کنیم، دستور بالا کمک کننده خواهد بود #EmbeddedLinux
https://youtu.be/GK2pZ_oVU1o?is=EdVFUvjqKMJP8HgH
https://youtu.be/GK2pZ_oVU1o?is=EdVFUvjqKMJP8HgH
نحوه تعریف آرگومان خط فرمان برای درایورهای لینوکسی اطلاعات بیشتر: https://devarea.com/linux-kernel-development-kernel-module-parameters/ #linux
نحوه تعریف آرگومان خط فرمان برای درایورهای لینوکسی اطلاعات بیشتر: https://devarea.com/linux-kernel-development-kernel-module-parameters/ #linux
راهاندازی RAM در سیستمهای x86-64 وقتی پردازنده ریست میشه، رجیستر CS و IP طوری مقداردهی میشن که به یه آدرس مشخص روی SPI Flash اشاره کنن که حاوی UEFI/BIOS فریموره. پردازنده دستورات رو مستقیماً از همون Flash میخونه، بدون اینکه چیزی رو کپی کنه داخل رم به…
راهاندازی RAM در سیستمهای x86-64 وقتی پردازنده ریست میشه، رجیستر CS و IP طوری مقداردهی میشن که به یه آدرس مشخص روی SPI Flash اشاره کنن که حاوی UEFI/BIOS فریموره. پردازنده دستورات رو مستقیماً از همون Flash میخونه، بدون اینکه چیزی رو کپی کنه داخل رم به این روش Execute-In-Place میگن. دلیلش اینه که تو این استیج، DRAM هنوز پیکربندی نشده، و برخلاف خیلی از سیستمهای embedded که یه بلوک SRAM داخلی دارن ، تو اکثر پلتفرمهای x86 همچین چیزی در دسترس فریمور نیست. پس تا اینجا هیچ حافظهی read/write نداریم، در نتیجه stack هم نداریم. و بدون stack، اجرای کد C عملاً غیرممکنه، چون هر فراخوانی تابع و هر متغیر محلی به یه جای read/write نیاز داره. راهحلی که اینجا استفاده میشه اینه که بهجای رم، به کش خود پردازنده تکیه کنیم. یعنی یه بازه از کش رو طوری پیکربندی کنیم که بهجای اینکه فقط نسخهی موقتی دادههای رم باشه، خودش مستقل عمل کنه و بشه توش خوند و نوشت به این تکنیک هم Cache-as-RAM یا CAR میگن. راهاندازی خود CAR با چند دستور اسمبلی انجام میشه. اولین فاز UEFI، فاز SEC هست. تو همین فاز، کش وارد حالت CAR میشه تا یه stack موقت داشته باشیم. از این لحظه به بعد، فریمور یه محیط اجرایی کاملتر داره بعد از SEC، وارد فاز PEI میشیم. این فاز از یه سری ماژول به اسم PEIM تشکیل شده که به ترتیب وابستگی اجرا میشن. تو همین فاز DRAM راهاندازی میشه. تا وقتی PEIM حافظه کارش تموم نشده، هیچ ماژول دیگهای حق نداره فرض کنه RAM واقعی در دسترسه. مادربرد از قبل نمیدونه کاربر چه ماژول رمی نصب کرده. داخل DIMM که شامل تراشههای DRAM هست، یه EEPROM کوچیک وجود داره که بهش SPD میگن. PEIM حافظه، تو همین مرحله محتوای این EEPROM رو معمولاً از طریق SMBus میخونه. داخل این EEPROM اطلاعاتی مثل نوع رم، ظرفیت، تعداد رنک، و تایمینگهای استاندارد ذخیره شده. حالا که فریمور فهمید دقیقاً چه رمی داره، نوبت میرسه به بخش پیکربندی رم. این بخش با توجه به اطلاعاتی که از SPD خونده، فرکانس، تایمینگ و ولتاژ درست رو روی کنترلر حافظه تنظیم میکنه، و بعدش یه سری کالیبراسیون و تست سیگنالی (memory training) انجام میشه تا مطمئن بشه رم بهصورت پایدار کار میکنه. وقتی این مرحله موفق تموم شد، فریمور یه سرویس رو صدا میزنه که اساساً به بقیهی سیستم اعلام میکنه از الان این بازه از DRAM واقعی قابلاعتماده. همراه این اعلام، هرچی که تا حالا روی CAR نگه داشته میشد منتقل میشه به DRAM واقعی. بعد از این انتقال، CAR دیگه لازم نیست و باید غیرفعال بشه. بعد از فاز PEI، کنترل میره به فاز بعدی UEFI به اسم DXE. برخلاف همهی مراحل قبلی که یا از Flash یا از CAR اجرا میشدن، این فاز روی DRAM واقعی که آماده کردیم اجرا میشه. تو این فاز، درایورهای کاملتر سیستم مثل دیسک، شبکه و USB لود میشن، و در نهایت کنترل تحویل داده میشه به بوتلودر سیستمعامل. Abbreviation XIP — Execute-In-Place CAR — Cache-as-RAM SEC — Security Phase PEI — Pre-EFI Initialization PEIM — PEI Module DIMM — Dual Inline Memory Module SPD — Serial Presence Detect DXE — Driver Execution Environment
видео или голосовое, без подписи
یک مثال از Pinctrl توی پست قبل گفتیم که pinctrl چی هست تو این پست میخوایم یه تیکه device tree برد ارنچ پای zero3 رو ببینیم و یه باگی که توی SPIاش وجود داره رفع کنیم فرض کنید میخوایم یه پریفرالی رو به SPI ارنج پایمون وصل کنیم و شروع کنیم به تبادل داده. مثلا من میخواستم ماژول nRF24L01 رو بهش وصل کنم و دیتا ارسال کنم تراشه استفاده شده توی این برد(h618) اگه اشتباه نکنم 4 تا SPI داره ولی باتوجه به بردمون فقط دوتاش قابل استفاده هست. درواقع SPI0اش به یه حافظه Flash وصل شده و SPI1اش هم به یپنهدر روی برد سیمکشی شده و در دسترس ما هست. مشکلی که وجود داره اینه که ایمیج armbian موجود برای این برد، SPI1 رو کلا فعال نکرده بطور پیشفرض و حتی با دستور armbian-config و فعال کردن device tree overlayاش باز هم کار نمیکنه. با یه مقدار سرچ توی نت به این نتیجه میرسیم که pinctrl برای SPI1 توی دیوایستری درست تعریف نمیشه. توی عکسای بالا دوتا SPIای که گفتیم رو نشون دادیم. دقت کنید که spi0 همون spi@5010000 و spi1 هم spi@5011000 میشه. توی دوتا از عکسهای بالا مقادیر پیشفرض SPIها نشون داده شدن و توی عکس سوم هم overlayای که روی spi1 اعمال میشه و عملا spi1 رو جایگزین میکنه. آورده شده. همونطور که میبینید توی spi1 هیچوقت pinctl تعریف نشده و مشکل دقیقا همینجاست. اما pinctrl توی spi0 دوتا عددن اینا چین؟ این دوتا عدد phandle یا سادهتر بگیم پوینتر هستن. کافیه دنبال آیدی 0x1f و 0x20 بگردیم تا به نودهای زیر برسیم: spi0-pins { pins = "PC0\0PC2\0PC4\0"; function = "spi0"; phandle=<0x1f>; }; spi0-cs-pin { pins = "PC3"; function = "spi0"; phandle = <0x20>; }; خب پس میبنیم که باید اولین عدد توی pinctrl-0 پوینتر به نود spi1-pins و دومین عدد هم پوینتر به نود spi1-cs1-pin باشه. حالا میتونیم به سادگی overlay یا حتی خود دیوایستری اصلی رو patch کنیم و برد رو ریبوت کنیم. اینجوری spi1 راه میوفته! #EmbeddedLinux
видео или голосовое, без подписи
видео или голосовое, без подписи
داستان این عکسها رو توی پست بعد میگم