محاولة لإنشاء نظام تشغيل في Rust for Raspberry Pi 3. نظرًا لقيود الوقت ، فقد أعطت الأولوية للحصول على شيء يعمل بدلاً من تجربة أفكار جديدة ، لذلك الآن هو نظام تشغيل متجانس مع واجهة برمجة تطبيقات شبيهة بـ UNIX ، لكنني قد أغير ذلك في المستقبل. لقد قمت بنسخ ما فعلته إلى حد كبير من أجل OS Gloworm OS المكتوب في C.
في الوقت الحالي ، لديها دعم للذاكرة الافتراضية ، مع تخصيص الصفحة عند الطلب ، ولكن لا يوجد دعم حتى الآن لتبديل الذاكرة على القرص. يحتوي على نظام ملفات افتراضية مع دعم لنظام ملفات Ext2 ، وكذلك بعض أنظمة الملفات في الذاكرة. وهو يدعم عمليات متعددة مع تبديل السياق الناتج عن مؤقت النظام ، لكنه لا يدعم بعد عدة مؤشرات ترابط.
حاليًا ، لا يوجد سوى برنامج تشغيل وحدة تحكم (نظام فرعي TTY) وبرنامج تشغيل بطاقة SD/EMMC (النظام الفرعي للجهاز). يوفر النظام الفرعي لبرنامج التشغيل block bufcache للكتل ذاكرة التخزين المؤقت قراءة من القرص بواسطة نظام الملفات. يتم وضع علامة على الكتل المستعارة على أنها قابلة للتغيير وسيتم كتابتها مرة أخرى في التزام الكتلة التالي. لم يتم اختبار دعم كتابة Ext2 جيدًا بعد ، لذلك يتم تعطيل الالتزام في الوقت الحالي.
يمكن كتابة التطبيقات في الصدأ وتجميعها مع المكتبات المضمنة ، والتي تستخدم تعليمات AARCH64 SVC لتنفيذ مكالمات النظام إلى نظام التشغيل. وهي تدعم حاليًا عمليات الملفات الأساسية ، وكذلك exit fork و exec . يمكن لنظام التشغيل تحميل ثنائيات ELF التي تنتجها CARGO كتطبيقات وتشغيلها. يتوفر برنامج shell بسيط (الذي أطلقته kernel بعد التهيئة) و ls Command ، ولكنه فقط في مرحلة إثبات المفهوم.
يتكون نظام التشغيل من نواة وبعض التطبيقات التي يتم تجميعها جميعها بشكل منفصل. يمكن تحميل التطبيقات في قسم Ext2 ، والتي يمكن قراءتها بواسطة kernel ، ولكن يجب تحميل النواة بشكل منفصل ، لذلك لا يتم تضمينها في الصورة.
عادة ، عندما يبحث حذاء Raspberry Pi ، عن قسم الدهون على بطاقة microSD التي تحتوي على ملف kernel8.img ، الذي يتم تحميله بعد ذلك على العنوان 0x80000 وتشغيله. بمجرد تشغيل kernel ، يمكنه بعد ذلك تركيب أي أقسام أخرى لاستخدامها كنظام ملفات الجذر. عند التشغيل في QEMU ، يتم تمرير صورة kernel على سطر الأوامر ، إلى جانب اسم ملف صورة القرص التي تحتوي على قسم Ext2.
يتم توفير makefile في جذر المشروع لبناء صورة قرص ext2. لتسهيل اختبار الكود في QEMU أو على الأجهزة ، فإنه ينشئ صورة قرص تبدو مثل بطاقة microSD (أي قسم الدهون بالإضافة إلى قسم Ext2). عند استخدام QEMU ، يتم تجاهل قسم الدهون.
لإنشاء صورة ، من تشغيل كمبيوتر Linux:
make create-image
make load-image سيؤدي ذلك إلى إنشاء ملف صورة 4 جيجابايت جديد ، واستخدم mkfs.ext2 لإنشاء نظام ملفات جديد بداخله ، وقم بتثبيته كجهاز استرجاع في <project>/build ، ثم تجميع التطبيقات وتحميلها فيه. كما يقوم بنسخ جدول أقسام مشفر في الصورة ، والذي يكرر الأقسام المستخدمة من قبل الأجهزة.
بمجرد إنشاء الصورة ، يمكن تجميع النواة وتشغيلها في QEMU ، باستخدام:
cd config/raspberrypi3/
make
./qemu.sh يتطلب الركض على Raspberry Pi حاليًا وحدة تحكم التسلسلية USB. أنا أستخدم برنامج Miniload من البرنامج التعليمي Rust Raspberry Pi OS لتحميل kernel على المنفذ التسلسلي. قد يكون من الممكن وضع صورة kernel المترجمة ( ruxpin.img ) في قسم التمهيد للملف الذي تم إنشاؤه واكتبه على القرص ، لكنني لم أختبر ذلك بعد.
تم نسخ الإخراج التالي من وحدة التحكم عند التشغيل في QEMU. لديها الكثير من رسائل التصحيح لإظهار ما يجري. يبدأ بإعداد كومة kernel وذاكرة الصفحة ، ويقوم بتسجيل أنواع نظام الملفات ، وتهيئة برامج تشغيل الجهاز ، وتركيب قسم الجذر Ext2. يقوم بعد ذلك بإجراء عدد من الاختبارات للتحقق من وظائف نظام الملفات الأساسية ، تليها إطلاق العملية الأولى (shell). ثم يتم كتابة الأمر ، معروضًا بين "<>" ، الذي يطلق برنامج ls ، يطبع قائمة بالملفات والأدلة في / ، ثم يخرج مرة أخرى إلى موجه shell.
starting kernel...
kernel heap: using 0x200000, size 14MiB
virtual memory: using region at PhysicalAddress(0x1000000), size 240 MiB, pages 61438
interrupts: initializing generic arm interrupt controller
fs: registering filesystem tmpfs
fs: registering filesystem devfs
fs: registering filesystem ext2
console: initializing
sd: initializing
sd: found partition 0 at 2000, 256 MiB
sd: found partition 1 at 82000, 740 MiB
fs: mounting ext2 at /, device Some(DeviceID(0, 2))
ext2: magic number ef53, block size 4096
ext2: total blocks 982016, total inodes 245760, unallocated blocks: 963991, unallocated inodes: 245742
ext2: features compat: 38, ro: 3, incompat: 2
ext2: allocating inode 13
fs: mounting devfs at /dev, device None
ext2: looking for "dev", found inode 13
Running some hardcoded tests before completing the startup
Mounting the tmpfs filesystem (simple in-memory file system)
ext2: allocating inode 14
fs: mounting tmpfs at /tmp, device None
ext2: looking for "tmp", found inode 14
Creating a directory and a file inside of it
ext2: allocating inode 15
ext2: looking for "testdir", found inode 15
ext2: allocating inode 16
ext2: allocating block 761 in group 0
ext2: allocating block 762 in group 0
ext2: writing to block 762
Read file 14: This is a test
Opening the console device file and writing to it
ext2: looking for "dev", found inode 13
the device file can write
Opening the testapp binary through the vfs interface and reading some data
ext2: looking for "bin", found inode 32769
ext2: looking for "testapp", found inode 32770
read in 1024 bytes
0xffff00000007f790: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
0xffff00000007f7a0: 02 00 b7 00 01 00 00 00 70 29 21 00 00 00 00 00
0xffff00000007f7b0: 40 00 00 00 00 00 00 00 d0 c8 0d 00 00 00 00 00
0xffff00000007f7c0: 00 00 00 00 40 00 38 00 04 00 40 00 10 00 0e 00
0xffff00000007f7d0: 06 00 00 00 04 00 00 00 40 00 00 00 00 00 00 00
0xffff00000007f7e0: 40 00 20 00 00 00 00 00 40 00 20 00 00 00 00 00
0xffff00000007f7f0: e0 00 00 00 00 00 00 00 e0 00 00 00 00 00 00 00
0xffff00000007f800: 08 00 00 00 00 00 00 00 01 00 00 00 04 00 00 00
0xffff00000007f810: 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 00
0xffff00000007f820: 00 00 20 00 00 00 00 00 60 09 00 00 00 00 00 00
0xffff00000007f830: 60 09 00 00 00 00 00 00 00 00 01 00 00 00 00 00
0xffff00000007f840: 01 00 00 00 05 00 00 00 60 09 00 00 00 00 00 00
0xffff00000007f850: 60 09 21 00 00 00 00 00 60 09 21 00 00 00 00 00
0xffff00000007f860: d8 31 00 00 00 00 00 00 d8 31 00 00 00 00 00 00
0xffff00000007f870: 00 00 01 00 00 00 00 00 51 e5 74 64 06 00 00 00
0xffff00000007f880: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0xffff00000007f890: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0xffff00000007f8a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0xffff00000007f8b0: 63 61 6c 6c 65 64 20 60 52 65 73 75 6c 74 3a 3a
0xffff00000007f8c0: 75 6e 77 72 61 70 28 29 60 20 6f 6e 20 61 6e 20
0xffff00000007f8d0: 60 45 72 72 60 20 76 61 6c 75 65 00 00 00 00 00
0xffff00000007f8e0: 60 09 21 00 00 00 00 00 08 00 00 00 00 00 00 00
0xffff00000007f8f0: 08 00 00 00 00 00 00 00 20 10 21 00 00 00 00 00
0xffff00000007f900: 60 09 21 00 00 00 00 00 00 00 00 00 00 00 00 00
0xffff00000007f910: 01 00 00 00 00 00 00 00 94 28 21 00 00 00 00 00
0xffff00000007f920: 61 20 72 65 61 6c 6c 79 20 63 6f 6f 6c 20 6d 65
0xffff00000007f930: 73 73 61 67 65 20 74 68 61 74 20 49 27 64 20 6c
0xffff00000007f940: 69 6b 65 20 74 6f 20 73 65 65 00 00 00 00 00 00
0xffff00000007f950: 90 01 20 00 00 00 00 00 2a 00 00 00 00 00 00 00
0xffff00000007f960: 73 72 63 2f 6d 61 69 6e 2e 72 73 00 00 00 00 00
0xffff00000007f970: d0 01 20 00 00 00 00 00 0b 00 00 00 00 00 00 00
0xffff00000007f980: 0c 00 00 00 05 00 00 00 0a 2f 6d 6e 74 2f 74 65
0xffff00000007f990: 73 74 32 00 00 00 00 00 d0 01 20 00 00 00 00 00
0xffff00000007f9a0: 0b 00 00 00 00 00 00 00 0e 00 00 00 51 00 00 00
0xffff00000007f9b0: d0 01 20 00 00 00 00 00 0b 00 00 00 00 00 00 00
0xffff00000007f9c0: 10 00 00 00 28 00 00 00 d0 01 20 00 00 00 00 00
0xffff00000007f9d0: 0b 00 00 00 00 00 00 00 11 00 00 00 19 00 00 00
0xffff00000007f9e0: d0 01 20 00 00 00 00 00 0b 00 00 00 00 00 00 00
0xffff00000007f9f0: 11 00 00 00 2a 00 00 00 d0 01 20 00 00 00 00 00
0xffff00000007fa00: 0b 00 00 00 00 00 00 00 12 00 00 00 11 00 00 00
0xffff00000007fa10: d0 01 20 00 00 00 00 00 0b 00 00 00 00 00 00 00
0xffff00000007fa20: 17 00 00 00 38 00 00 00 d0 01 20 00 00 00 00 00
0xffff00000007fa30: 0b 00 00 00 00 00 00 00 1a 00 00 00 10 00 00 00
0xffff00000007fa40: 72 65 61 64 20 69 6e 20 00 00 00 00 20 00 00 00
0xffff00000007fa50: 4e 6f 74 41 46 69 6c 65 d0 01 20 00 00 00 00 00
0xffff00000007fa60: 0b 00 00 00 00 00 00 00 1c 00 00 00 31 00 00 00
0xffff00000007fa70: d0 01 20 00 00 00 00 00 0b 00 00 00 00 00 00 00
0xffff00000007fa80: 1d 00 00 00 31 00 00 00 64 6f 6e 65 00 00 00 00
0xffff00000007fa90: f8 02 20 00 00 00 00 00 04 00 00 00 00 00 00 00
0xffff00000007faa0: d0 01 20 00 00 00 00 00 0b 00 00 00 00 00 00 00
0xffff00000007fab0: 2d 00 00 00 05 00 00 00 65 78 65 63 75 74 69 6e
0xffff00000007fac0: 67 20 73 65 6c 66 00 00 28 03 20 00 00 00 00 00
0xffff00000007fad0: 0e 00 00 00 00 00 00 00 d0 01 20 00 00 00 00 00
0xffff00000007fae0: 0b 00 00 00 00 00 00 00 24 00 00 00 15 00 00 00
0xffff00000007faf0: 46 69 6c 65 53 69 7a 65 54 6f 6f 4c 61 72 67 65
0xffff00000007fb00: 4e 6f 53 75 63 68 46 69 6c 65 73 79 73 74 65 6d
0xffff00000007fb10: 2f 6d 6e 74 2f 62 69 6e 2f 74 65 73 74 61 70 70
0xffff00000007fb20: 54 6f 6f 4d 61 6e 79 46 69 6c 65 73 4f 70 65 6e
0xffff00000007fb30: 72 61 6e 67 65 20 65 6e 64 20 69 6e 64 65 78 20
0xffff00000007fb40: 50 0e 21 00 00 00 00 00 08 00 00 00 00 00 00 00
0xffff00000007fb50: 08 00 00 00 00 00 00 00 90 0f 21 00 00 00 00 00
0xffff00000007fb60: 60 0e 21 00 00 00 00 00 50 0f 21 00 00 00 00 00
0xffff00000007fb70: 00 05 0a 0f 14 19 1e 23 28 2d 32 37 3c 41 46 4b
0xffff00000007fb80: 50 55 5a 5f 64 69 6e 73 78 7d 82 87 8c 91 63 61
Opening a new file and writing some data into it
ext2: allocating inode 17
ext2: allocating block 763 in group 0
ext2: writing to block 763
Reading back the data written previously
ext2: looking for "test2", found inode 17
0xffff00000007fba0: 74 68 69 73 20 69 73 20 73 6f 6d 65 20 74 65 73
0xffff00000007fbb0: 74 20 64 61 74 61 00 00 00 00 00 00 00 00 00 00
0xffff00000007fbc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0xffff00000007fbd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0xffff00000007fbe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0xffff00000007fbf0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0xffff00000007fc00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0xffff00000007fc10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Printing the contents of the root directory (ext2 mount)
reading dir . with inode 2
reading dir .. with inode 2
reading dir lost+found with inode 11
reading dir bin with inode 32769
reading dir test with inode 12
reading dir dev with inode 13
reading dir tmp with inode 14
reading dir testdir with inode 15
reading dir test2 with inode 17
Finished tests
loading the first processs (/bin/sh) from elf binary file
ext2: looking for "bin", found inode 32769
ext2: looking for "sh", found inode 32772
program segment 0: 6 4 offset: 40 v:200040 p:200040 size: e0
program segment 1: 1 4 offset: 0 v:200000 p:200000 size: 1870
program segment 2: 1 5 offset: 1870 v:211870 p:211870 size: 53c8
program segment 3: 6474e551 6 offset: 0 v:0 p:0 size: 0
ext2: looking for "dev", found inode 13
timer: initializing generic arm timer to trigger context switch
kernel initialization complete
scheduler: starting multitasking
Instruction or Data Abort caused by Access Flag at address 215a70 (allocating new page)
Instruction or Data Abort caused by Access Flag at address fffffff0 (allocating new page)
Instruction or Data Abort caused by Access Flag at address 21337c (allocating new page)
Instruction or Data Abort caused by Access Flag at address 212190 (allocating new page)
Starting shell...
Instruction or Data Abort caused by Access Flag at address 216c34 (allocating new page)
% <typing in ls>
Instruction or Data Abort caused by Access Flag at address 2140e8 (allocating new page)
executing /bin/ls
child pid is 3
clearing old process space
executing a new process
ext2: looking for "bin", found inode 32769
ext2: looking for "ls", found inode 32774
program segment 0: 6 4 offset: 40 v:200040 p:200040 size: e0
program segment 1: 1 4 offset: 0 v:200000 p:200000 size: 730
program segment 2: 1 5 offset: 730 v:210730 p:210730 size: 2cb8
program segment 3: 6474e551 6 offset: 0 v:0 p:0 size: 0
ext2: looking for "dev", found inode 13
Instruction or Data Abort caused by Access Flag at address 212220 (allocating new page)
Instruction or Data Abort caused by Access Flag at address fffffff0 (allocating new page)
ext2: looking for ".", found inode 2
Instruction or Data Abort caused by Access Flag at address 2133e4 (allocating new page)
Instruction or Data Abort caused by Access Flag at address 2110e4 (allocating new page)
.
..
lost+found
bin
test
dev
tmp
testdir
test2
Exiting process 3
%