كيفية مطابقة مسار جهاز Linux مع اسم محرك أقراص Windows؟

StackOverflow https://stackoverflow.com/questions/18959

  •  09-06-2019
  •  | 
  •  

سؤال

أنا أكتب تطبيقًا يقوم في مرحلة ما بتنفيذ عمليات قرص منخفضة المستوى في بيئة Linux.يتكون التطبيق في الواقع من جزأين، أحدهما يعمل على نظام Windows ويتفاعل مع المستخدم والآخر عبارة عن جزء من نظام التشغيل Linux يتم تشغيله من قرص حي.يقوم المستخدم باختيار أحرف محركات أقراص Windows ثم يقوم جزء Linux بتنفيذ الإجراءات مع الأقسام المقابلة.تكمن المشكلة في العثور على تطابق بين حرف محرك أقراص Windows (مثل C:) واسم جهاز Linux (مثل /dev/sda1).هذا هو الحل الحالي الذي أصنفه على أنه قبيح:

  • تخزين معلومات الأقسام (أيحرف محرك الأقراص وعدد الكتل والرقم التسلسلي لمحرك الأقراص وما إلى ذلك) في Windows في مكان محدد مسبقًا (أيجذر قسم النظام).

  • اقرأ قائمة الأقسام من /proc/partitions.احصل فقط على تلك الأقسام التي تحتوي على أرقام رئيسية لمحركات الأقراص الثابتة SCSI أو IDE وأرقام ثانوية تحددها على أنها أقسام حقيقية وليس الأقراص بأكملها.

  • حاول تركيب كل منها باستخدام أنظمة الملفات ntfs أو vfat.تحقق مما إذا كان القسم المثبت يحتوي على المعلومات المخزنة بواسطة تطبيق Windows.

  • عند العثور على المعلومات المطلوبة المكتوبة بواسطة تطبيق Windows، قم بإجراء المطابقة الفعلية.لكل قسم موجود في /proc/partitions يحصل على الرقم التسلسلي لمحرك الأقراص (عبر HDIO_GET_IDENTITY syscall)، وعدد الكتل (من /proc/partitions) وإزاحة محرك الأقراص (/sys/blocks/drive_path/partition_name/start)، قارن ذلك بنظام Windows المعلومات وإذا تطابقت - قم بتخزين حرف محرك أقراص Windows مع اسم جهاز Linux.

هناك مشكلتان في هذا المخطط:

  • هذا قبيح.إن كتابة البيانات في Windows ثم قراءتها في Linux يجعل الاختبار كابوسًا.

  • تتم مقارنة الرقم الرئيسي لجهاز Linux فقط بأجهزة IDE أو SCSI.من المحتمل أن يفشل هذا، أي.على أقراص USB أو FireWire.من الممكن إضافة هذه الأنواع من الأقراص، ولكن يبدو أن قصر التطبيق على مجموعة فرعية معروفة فقط من الأجهزة المحتملة فكرة سيئة إلى حد ما.

  • يبدو أن HDIO_GET_IDENTITY يعمل فقط على محركات أقراص IDE وSATA.

  • /sys/block hack قد لا يعمل على محركات أقراص أخرى غير IDE أو SATA.

هل هناك أي أفكار حول كيفية تحسين هذا المخطط؟ربما هناك طريقة أخرى لتحديد أسماء النوافذ دون كتابة كافة البيانات في تطبيق ويندوز؟

ملاحظة.لغة التطبيق هي C++.لا أستطيع تغيير هذا.

هل كانت مفيدة؟

المحلول

تحتوي الأقسام على UUIDs المرتبطة بها.لا أعرف كيفية العثور عليها في Windows ولكن في Linux يمكنك العثور على UUID لكل قسم باستخدام:

جهاز Sudo vol_id -u (على سبيل المثال/ديف/sda1)

إذا كانت هناك وظيفة مكافئة في Windows، فيمكنك ببساطة تخزين UUIDs لأي قسم يختارونه، ثم التكرار عبر جميع الأقسام المعروفة في Linux ومطابقة UUIDs.

يحرر: قد يكون هذا أمرًا خاصًا بنظام التشغيل Linux فقط، وقد يكون على وجه الخصوص الأداة volid التي تولد هذه البيانات من شيء ما (بدلاً من قراءة البيانات التعريفية لمحرك الأقراص).بعد قولي هذا، لا يوجد ما يمنعك من الحصول على مصدر volid والتحقق من ما يفعله.

نصائح أخرى

تحتوي الأقسام على UUIDs المرتبطة بها

معرفتي بهذا الأمر ضحلة جدًا، لكنني اعتقدت أن هذا ينطبق فقط على الأقراص المنسقة باستخدام أقسام GPT (جدول تقسيم الدليل)، بدلاً من تنسيق MBR ذي النمط القديم الذي لا يزال 99٪ من العالم عالقًا به؟

معرفتي بهذا الضحلة للغاية ، لكنني اعتقدت أن هذا صحيح فقط بالنسبة للأقراص المنسقة مع أقسام GPT (جدول التقسيم GUD) ، بدلاً من تنسيق MBR القديم الذي لا يزال 99 ٪ من العالم عالقًا؟

لا يبدو الأمر وكأنه مبتذلة لمستخدم Linux ولكنه يعمل بالنسبة لي ..أستخدمه مع أقسام NTFS ولم أواجه أي مشاكل.كما قلت في تعديلي، قد يكون vol_id هو من ينشئها بنفسه.إذا كان الأمر كذلك، فلن يكون هناك اعتماد على أي تنسيق قسم معين، الأمر الذي سيكون منتفخًا.

تحتوي الأقسام على UUIDs المرتبطة بها.لا أعرف كيفية العثور عليها في Windows ولكن في Linux يمكنك العثور على UUID لكل قسم باستخدام:

جهاز Sudo vol_id -u (على سبيل المثال/ديف/sda1)

إذا كانت هناك وظيفة مكافئة في Windows، فيمكنك ببساطة تخزين UUIDs لأي قسم يختارونه، ثم التكرار عبر جميع الأقسام المعروفة في Linux ومطابقة UUIDs.

هذه نقطة جيدة، شكرا لك!لقد بحثت في مصادر vol_id (جزء من udev tarball) ويبدو أنه بالنسبة لـ FAT(32) وNTFS يقوم بإنشاء UUUD باستخدام الرقم التسلسلي لوحدة التخزين الذي تتم قراءته من الموقع المحدد مسبقًا على القسم.وبما أنني لا أتوقع أي شيء آخر غير Fat32 وntfs، فإنني أعتبر استخدام هذه المعلومات كمعرف قسم.

تحتاج إما إلى وضع علامة على محرك الأقراص بطريقة ما (على سبيل المثال.اكتب ملفًا وما إلى ذلك)، أو ابحث عن معرف مرتبط فقط بمحرك الأقراص المحدد هذا.

من الصعب جدًا، بل من المستحيل تقريبًا معرفة الحرف الذي سيعينه Windows لقسم محرك أقراص معين، دون تشغيل Windows فعليًا.وذلك لأن Windows يربط دائمًا محرك الأقراص الذي يتم تشغيله منه بـ C:.والذي يمكن أن يكون أي محرك أقراص، إذا كان لديك أكثر من نظام تشغيل مثبت.يسمح لك Windows أيضًا باختيار حرف محرك الأقراص الذي سيحاول تجربته أولاً لقسم معين، مما يسبب المزيد من المشكلات.

سيكون تنفيذ عناصر واجهة المستخدم الرسومية داخل Linux أسهل بكثير من تجربة حل Window/Linux المختلط هذا.أنا لا أقول لا تحاول ذلك بهذه الطريقة، ما أقوله هو أن هناك الكثير من المخاطر المحتملة مع هذا النهج.أنا متأكد من أنني لا أعرف حتى عنهم جميعًا.

هناك خيار آخر يتمثل في معرفة ما إذا كان بإمكانك فعلًا القيام بجزء Linux داخل Windows.إذا كنت مبرمجًا جيدًا لنظام Windows، فيمكنك بالفعل الوصول إلى نظام الملفات الخام.من المحتمل أن يكون هناك العديد من المخاطر في هذا الأسلوب، لأن Windows سيتم تشغيله أثناء تشغيل كل هذا.

لذا، لإعادة التكرار، سأرى ما إذا كان بإمكانك القيام بكل شيء من داخل Linux، إذا استطعت.الأمر أبسط كثيرًا على المدى الطويل.

في نظام التشغيل Windows، يمكنك قراءة "الرقم التسلسلي لوحدة تخزين NTFS" والذي يتوافق مع UUID في Linux.

إمكانيات الحصول على "NTFS Volume Serial" من شبابيك:

  • سطر الأوامر منذ XP: fsutil.exe fsinfo ntfsinfo C:

  • تحت ج ++

    HANDLE fileHandle = CreateFile(L"\\\\.\\C:", // or use syntax "\\?\Volume{GUID}" 
                                   GENERIC_READ,
                                   FILE_SHARE_READ|FILE_SHARE_WRITE,
                                   NULL,
                                   OPEN_EXISTING,
                                   NULL,
                                   NULL);
    DWORD i;
    NTFS_VOLUME_DATA_BUFFER ntfsInfo;
    DeviceIoControl(fileHandle, 
                    FSCTL_GET_NTFS_VOLUME_DATA, 
                    NULL, 
                    0, 
                    &ntfsInfo,
                    sizeof(ntfsInfo), 
                    &i, 
                    NULL));
    cout << "UUID is " << std::hex << ntfsInfo.VolumeSerialNumber.HighPart << std::hex << ntfsInfo.VolumeSerialNumber.LowPart << endl;
    

إمكانيات الحصول على UUID تحت لينكس:

  • ls -l /dev/disk/by-uuid
  • ls -l /dev/disk/by-label
  • blkid /dev/sda1
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top