vfs --- التحكم في نظام الملفات الافتراضي

تحتوي الوحدة vfs على دوال لإنشاء كائنات نظام الملفات وتركيبها/فك تركيبها في نظام الملفات الافتراضي.

تركيب نظام الملفات

توفر بعض المنافذ نظام ملفات افتراضي (VFS) وإمكانية تركيب عدة أنظمة ملفات "حقيقية" ضمن هذا النظام الافتراضي. يمكن تركيب كائنات نظام الملفات إما عند جذر نظام الملفات الافتراضي، أو في دليل فرعي يقع في الجذر. ويتيح ذلك تهيئة ديناميكية ومرنة لنظام الملفات الذي تراه برامج Python. توفر المنافذ التي تمتلك هذه الوظيفة الدالتين mount() وumount()، وربما تنفيذات مختلفة لأنظمة الملفات ممثلة بأصناف VFS.

vfs.mount(fsobj: Any, mount_point: str, *, readonly: bool = False) None

تركيب كائن نظام الملفات fsobj في الموقع داخل نظام الملفات الافتراضي المحدد بسلسلة mount_point. يمكن أن يكون fsobj كائن VFS يمتلك دالة mount()، أو جهاز كتل. وإذا كان جهاز كتل فسيُكتشف نوع نظام الملفات تلقائيًا (يُطلق استثناء إذا لم يُتعرّف على أي نظام ملفات). يمكن أن يكون mount_point هو '/' لتركيب fsobj عند الجذر، أو '/<name>' لتركيبه في دليل فرعي تحت الجذر.

إذا كان readonly هو True فسيُركّب نظام الملفات للقراءة فقط.

أثناء عملية التركيب تُستدعى الدالة mount() على كائن نظام الملفات.

سيُطلق OSError(EPERM) إذا كان mount_point مركّبًا بالفعل.

vfs.mount() List[Tuple[Any, str]]

عند استدعاء mount() بدون وسائط، تُعيد قائمة بالصفوف تمثل جميع نقاط التركيب النشطة.

تكون القائمة المُعادة على الشكل [(fsobj, mount_point), ...].

vfs.umount(mount_point: str | Any) None

فك تركيب نظام ملفات. يمكن أن يكون mount_point سلسلة تسمي موقع التركيب، أو كائن نظام ملفات مركّبًا سابقًا. أثناء عملية فك التركيب تُستدعى الدالة umount() على كائن نظام الملفات.

سيُطلق OSError(EINVAL) إذا لم يُعثر على mount_point.

class vfs.VfsFat(block_dev: AbstractBlockDev)

إنشاء كائن نظام ملفات يستخدم تنسيق نظام الملفات FAT. تُوفَّر مساحة تخزين نظام الملفات FAT بواسطة block_dev. يمكن تركيب الكائنات المنشأة بواسطة هذا المُنشئ باستخدام mount().

static mkfs(block_dev: AbstractBlockDev) None

بناء نظام ملفات FAT على block_dev.

class vfs.VfsRom(buffer: bytes | bytearray | memoryview)

إنشاء كائن نظام ملفات يستخدم تنسيق نظام الملفات للقراءة فقط ROMFS. يجب أن يكون buffer كائنًا يدعم بروتوكول المخزن المؤقت (bytes أو bytearray أو memoryview) ويحتوي على صورة ROMFS صالحة.

يمكن تركيب الكائنات المنشأة بواسطة هذا المُنشئ باستخدام mount().

راجع العمل مع ROMFS للحصول على التفاصيل الكاملة، بما في ذلك كيفية بناء ونشر صور ROMFS باستخدام mpremote.

vfs.rom_ioctl(op: int, *args: Any) Any

واجهة منخفضة المستوى للوصول إلى قسم (أو أقسام) ذاكرة القراءة فقط (ROM) في الجهاز. العمليات المدعومة هي:

الاستدعاء

السلوك

rom_ioctl(1)

إعادة عدد أقسام ROM المتاحة.

rom_ioctl(2, id)

إعادة القسم id على هيئة memoryview.

rom_ioctl(3, id, length)

محو أول length بايت من القسم id استعدادًا للكتابة. يُعيد الحد الأدنى لمحاذاة الكتابة بالبايت.

rom_ioctl(4, id, offset, buf)

كتابة buf إلى القسم id عند البايت offset.

rom_ioctl(5, id)

إنهاء تسلسل كتابة إلى القسم id (يُفرّغ ذاكرات التخزين المؤقت، إلخ).

تُستدعى هذه العمليات عادةً بشكل غير مباشر بواسطة mpremote عند نشر صورة ROMFS؛ ولا تحتاج معظم التطبيقات إلى استدعائها مباشرةً.

class vfs.VfsPosix(root: str | None = None)

إنشاء كائن نظام ملفات يصل إلى نظام ملفات POSIX المضيف. إذا حُدِّد root فينبغي أن يكون مسارًا في نظام الملفات المضيف ليُستخدم جذرًا لكائن VfsPosix. وإلا فسيُستخدم الدليل الحالي لنظام الملفات المضيف.

ملاحظة

VfsPosix متاح فقط على منفذ MicroPython لنظام Unix؛ وهو غير موجود في البرنامج الثابت لـ OpenMV Cam.

أجهزة الكتل

جهاز الكتل هو كائن يُنفّذ بروتوكول الكتل. ويمكّن ذلك الجهاز من دعم أنظمة ملفات MicroPython. ويُمثَّل العتاد الفعلي بصنف يعرّفه المستخدم. الصنف AbstractBlockDev هو قالب لتصميم مثل هذا الصنف: لا يوفر MicroPython هذا الصنف فعليًا، لكن أي صنف جهاز كتل فعلي يجب أن يُنفّذ الدوال الموصوفة أدناه.

عادةً ما يتيح التنفيذ الملموس لهذا الصنف الوصول إلى الوظيفة الشبيهة بالذاكرة لقطعة من العتاد (مثل ذاكرة الفلاش). يمكن تهيئة جهاز كتل إلى أي نظام ملفات مدعوم وتركيبه باستخدام دوال os.

راجع العمل مع أنظمة الملفات للحصول على أمثلة لتنفيذات أجهزة الكتل باستخدام متغيري بروتوكول الكتل الموصوفين أدناه.

الواجهة البسيطة والموسعة

هناك توقيعان متوافقان للدالتين readblocks وwriteblocks (انظر أدناه)، وذلك لدعم مجموعة متنوعة من حالات الاستخدام. قد يُنفّذ جهاز كتل معين أحد الشكلين أو الآخر، أو كليهما في آن واحد. يُشار إلى الشكل الثاني (بوسيط الإزاحة) باسم "الواجهة الموسعة".

تتطلب بعض أنظمة الملفات مزيدًا من التحكم في عمليات الكتابة -- مثلًا، الكتابة في مناطق أقل من حجم الكتلة دون محو -- وتحتاج إلى أن يدعم جهاز الكتل الواجهة الموسعة.

class vfs.AbstractBlockDev

قالب توثيق لبروتوكول جهاز الكتل. لا يكشف MicroPython هذا الصنف فعليًا --- بل يُعرض هنا فقط لتوثيق الدوال التي يجب أن يُنفّذها صنف جهاز الكتل المعرّف من قبل المستخدم. تعود وسائط المُنشئ بالكامل إلى التنفيذ (عادةً أشياء مثل ناقل الفلاش، ودبوس اختيار الشريحة، وحجم القطاع، إلخ).

readblocks(block_num: int, buf: bytearray) None
readblocks(block_num: int, buf: bytearray, offset: int) None

قراءة بايتات من الجهاز إلى buf. يكشف تحميلان زائدان عن الواجهتين البسيطة والموسعة.

الشكل البسيط (readblocks(block_num, buf)): يقرأ كتلًا كاملة بدءًا من فهرس الكتلة block_num. يجب أن يكون len(buf) مضاعفًا لحجم الكتلة، ويكون عدد الكتل المقروءة هو len(buf) // block_size.

الشكل الموسع (readblocks(block_num, buf, offset)): يقرأ len(buf) بايت -- ليس بالضرورة عددًا صحيحًا من الكتل -- بدءًا من البايت offset داخل الكتلة block_num. استخدم هذا الشكل عندما يحتاج نظام الملفات إلى وصول قراءة أقل من حجم الكتلة.

writeblocks(block_num: int, buf: bytes) None
writeblocks(block_num: int, buf: bytes, offset: int) None

كتابة بايتات من buf إلى الجهاز.

الشكل البسيط (writeblocks(block_num, buf)): يكتب كتلًا كاملة بدءًا من فهرس الكتلة block_num. يجب أن يكون len(buf) مضاعفًا لحجم الكتلة، ويكون عدد الكتل المكتوبة هو len(buf) // block_size. ويتحمل التنفيذ مسؤولية محو كل كتلة وجهة أولًا إذا كان العتاد الأساسي يتطلب ذلك.

الشكل الموسع (writeblocks(block_num, buf, offset)): يكتب len(buf) بايت -- ليس بالضرورة عددًا صحيحًا من الكتل -- بدءًا من البايت offset داخل الكتلة block_num. لا يجوز أن تتغير سوى البايتات التي تُكتب؛ ويتحمل المُستدعي مسؤولية ضمان محو الكتل المتأثرة عبر استدعاء سابق لـ ioctl(6, block_num). ويجب على تنفيذات هذا الشكل ألا تمحو أبدًا كتلة بشكل ضمني، حتى عندما يكون offset صفرًا.

ioctl(op: int, arg: int) int | None

التحكم في جهاز الكتل والاستعلام عن معاملاته. تُعطى العملية المراد تنفيذها بواسطة op وهي أحد الأعداد الصحيحة التالية:

  • 1 -- تهيئة الجهاز (arg غير مستخدم)

  • 2 -- إيقاف تشغيل الجهاز (arg غير مستخدم)

  • 3 -- مزامنة الجهاز (arg غير مستخدم)

  • 4 -- الحصول على عدد الكتل، وينبغي أن يُعيد عددًا صحيحًا (arg غير مستخدم)

  • 5 -- الحصول على عدد البايتات في الكتلة، وينبغي أن يُعيد عددًا صحيحًا، أو None وفي هذه الحالة تُستخدم القيمة الافتراضية 512 (arg غير مستخدم)

  • 6 -- محو كتلة، arg هو رقم الكتلة المراد محوها

كحد أدنى يجب اعتراض ioctl(4, ...)؛ وتتطلب أنظمة الملفات التي تستخدم الواجهة الموسعة إضافةً إلى ذلك ioctl(6, ...). أما الحاجة إلى العمليات الأخرى فتعتمد على العتاد.

قبل أي استدعاء لـ writeblocks(block, ...) يُصدر نظام ملفات يستخدم الواجهة الموسعة ioctl(6, block) ليتمكن المشغّل من محو الكتلة أولًا إذا كان العتاد يتطلب ذلك. ويمكن لمشغّل بدلًا من ذلك أن يعترض ioctl(6, block) ويُعيد 0 (نجاح)، متحملًا بنفسه مسؤولية اكتشاف متى يكون المحو لازمًا.

ما لم يُذكر خلاف ذلك يمكن لـ ioctl(op, arg) أن يُعيد None. وبالتالي يمكن لأي تنفيذ تجاهل القيم غير المستخدمة لـ op. وحيثما يُعترض op، تكون القيمة المُعادة للعمليتين 4 و5 كما هو مفصّل أعلاه. أما العمليات الأخرى فينبغي أن تُعيد 0 عند النجاح وقيمة غير صفرية عند الفشل، حيث تكون القيمة المُعادة رمز خطأ OSError (errno).