سؤال
أحاول السماح بعمليات مختلفة للتواصل باستخدام تعيين الذاكرة نفس الملف. ومع ذلك، أواجه بعض المشاكل مع هذا. لدي شعور يجب أن أفعل ذلك بالطريقة التي أستخدمها، ثم استدعاء Open () ومرافقة واصف الملف الخاص بي إلى MMAP.
هنا هو رمزي، هل يمكنك أن ترى أي شيء خاطئ في ذلك؟
كود الكائن 1:
16 FILE* temp = fopen(theSharedFileName, "w");
17 fseek(temp, fileSize-1, SEEK_SET);
18 fprintf(temp, "0"); // make the file a certain size
19 fseek(temp, 0, SEEK_CUR);
20
21 int sharedFileName = fileno(temp);
...
31 sharedArea = (MyStruct*)mmap(0, fileSize,
32 PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED, sharedFileName, 0);
يمكنني استخدام وضع الملفات "W" لأن الكائن 1 لن يتم إجراؤه مرة واحدة فقط وأريده إعادة تعيين أي بيانات موجودة مسبقا.
كود كائن 2:
130 FILE* tempFile = fopen(sharedFileName, "a");
131 int theFile = fileno(tempFile);
...
135 sharedArea = (MyStruct*)mmap(NULL, fileSize,
136 PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED, theFile, 0);
المحلول
بعض القضايا:
- تجنب خلط I / O رفيع المستوى (FOPEN ()، FSEEK ()) وبعض التشغيل المنخفض المستوى مثل mmap (). على الرغم من أنه يمكنك الحصول على واصف الملفات منخفضة المستوى باستخدام Fileno ()، فإن هذا يشبه أخذ أطول طريق للوصول إلى نفس المكان. أيضا، فقط باستخدام MMAP () يكسر التوافق خارج BSD و Posix، لذلك لا تحصل على أي شيء باستخدام وظائف CI / O القياسية. مجرد استخدام فتح () و lseek () مباشرة.
- لا معنى له استخدام الدفق التنسيقي I / O (FPRINTF ()) في نفس الملف الذي توجد فيه رسم خرائط الذاكرة. عندما تقوم بالذاكرة خريطة الذاكرة، فأنت تخبر ضمنيا النظام الذي ستستخدمه كبيانات وصول عشوائي (فهرسة مباشر). FPRINTF () مخصص لإخراج الدفق، وعادة ما تستخدمه للوصول المتسلسل. في الواقع، رغم أنه ممكن، فمن غير المعتاد أن نرى FPRINTF () و FSEEK () في نفس الوصف (هذا غير محمول، ولكن بسبب العنصر السابق، أنا لا أفكر في إمكانية النقل).
- يجب أن تتطابق الحماية من حماية الملفات المفتوحة. منذ أن تمر "W" إلى FOPEN ()، و
PROT_READ | PROT_WRITE | PROT_EXEC
إلى MMP ()، أنت تنتهك هذا التقييد. هذا يسلط الضوء أيضا على سبب عدم خلط I / O رفيع المستوى مع تعيين الذاكرة: كيف تضمن ذلكfopen(...,"w")
سيتم فتح الملف مع الأعلام الصحيحة؟ من المفترض أن يكون هذا "تفاصيل التنفيذ" لمكتبة C. إذا كنت ترغب في تعيين ملف في الذاكرة مع أذونات القراءة والكتابة، يجب عليك استخدام المستوى المنخفضopen(theSharedFileName, O_RDWR)
لفتح الملف. - لا استعمال
PROT_WRITE
وPROT_EXEC
سويا او معا. انها ليست المحمولة و إنه مخاطر أمنية. أقرأ عن W ^ X. و حماية الفضاء القابلة للتنفيذ.
نصائح أخرى
كما قال آخرون، لا تستخدم fopen () والأصدقاء لهذا الغرض.
قد يكون جزء من المشكلة التي تعاني من تواجهها بسبب حقيقة أن FPRINTF () يمكن أن يكون لديك مخازن دفقية، لذلك قد لا يغير الملف بالفعل، وبالتالي تكون مرئية للعملية الأخرى عند المتوقع. يمكنك إضافة fflush ()، ولكن القراءة () والكتابة () لا تفعل أي تخزين مؤقت لمستوى التطبيق، وهو جزء من سبب وجودهم أكثر ملاءمة.