الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

سلسلة التجارب - التجربة الخامسة

مغلق
بدأه Adel Khayata في 15 أغسطس 2001 · 6 رد · 789 مشاهدة · في المواضيع والدروس
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم.

فكرة هذه التجربة هي كيفية مشاركة المعلومات بين برنامجين :)

و قد كتبت هذه التجربة بسبب سؤال وضع في هذا المنتدى لذلك أردت وضع مثال عن كيفية عمل ذلك في Visual C++:)

أولا هذه صورة للبرنامجين:

SharedMemoryPic.jpg

طبعا يوجد برنامجين الاول ( و اسمه Send ) يقوم بارسال البيانات إىل البرنامج الثاني ( و اسمه Recv ).

طبيعة البيانات التي يقوم البرنامج Send بارسالها هي احداثيات الماوس أثناء حركتها و يقوم البرنامج الثاني بعرض هذه الاحداثيات أي قمت بعملية نقل معلومات الاحداثيات من البرنامج الأول و عرضها في البرنامج الثاني.

فكرة البرنامجين بسيطة و تعتمد في أساسها على إنشاء منطقة ذاكرة مشتركة بين البرنامجين بحيث يستطيع البرنامجين التعامل معها و هذه الطريقة تسمى Memory mapped file و لاستخدام هذه الطريقة نستخدم أربعة توابع API و هي :

التابع الأولو هو من أجل إنشاء الذاكرة المشتركة:

HANDLE CreateFileMapping(
  HANDLE hFile,                       // handle to file
  LPSECURITY_ATTRIBUTES lpAttributes, // security
  DWORD flProtect,                    // protection
  DWORD dwMaximumSizeHigh,            // high-order DWORD of size
  DWORD dwMaximumSizeLow,             // low-order DWORD of size
  LPCTSTR lpName                      // object name
);

البارامتر الأول نمرر له القيمة INVALID_HANDLE_VALUE و التي تحدد أننا نريد إنشاء Memory mapped file.

البارامتر الثاني له علاقة بال Security و إذا كان ممكن أن نورث هذه المنطقة إلى الأبناء.

البارامتر الثالث يحدد فيما إذا كنا نريد إنشاء المنطقة من أجل القراءة أو الكتابة أو مع بعضهما.

البارامترين الرابع و الخامس يحددان حجم هذه الذاكرة.

البارامتر السادس يحدد اسم هذه الذاكرة.

التابع الثاني و يستخدم لفتح ( الحصول على Handle ) الذاكرة المشتركة:

HANDLE OpenFileMapping(
  DWORD dwDesiredAccess,  // access mode
  BOOL bInheritHandle,    // inherit flag
  LPCTSTR lpName          // object name
);

البارامتر الأول وظيفته مثل البارامتر الثالث في التابع السابق.

البارامتر الثاني وظيفته مثل البارامتر الثاني في التابع السابق.

البارامتر الثالث يحدد اسم الذاكرة المشتركة المراد فتحهاو طبعا يتم استخدام أحد التابعين في أحد البرنامجين و يتم استخدام التابع الثاني في البرنامج الآخر أي يتم إنشاء الذاكرة في برنامج , و يتم فتح هذه الذاكرة في البرنامج الآخر.

التابع الثالث و وظيفته عمل Map لهذه الذاكرة ضمن ذاكرة البرنامج أي عملية ربط ذاكرة البرنامج مع الذاكرة المشتركة:

LPVOID MapViewOfFile(
  HANDLE hFileMappingObject,   // handle to file-mapping object
  DWORD dwDesiredAccess,       // access mode
  DWORD dwFileOffsetHigh,      // high-order DWORD of offset
  DWORD dwFileOffsetLow,       // low-order DWORD of offset
  SIZE_T dwNumberOfBytesToMap  // number of bytes to map
);

البارامتر الاول هو ال Handle الذي تعاد قيمته من التابعين الأول و الثاني.

البارامتر الثاني مثل البارامتر الثالث في التابع الأول.

البارامترات الثالث و الرابع و الخامس يحددون المنطقة التي سيتم عمل عملية Map لها.

التابع الرابع ووظيفته إغلاق الذاكرة المشتركة:

BOOL CloseHandle(
  HANDLE hObject   // handle to object
);

ليس هناك أوامر لارسال المعلومات بين البرنامجين و لكن البرنامج المرسل يقوم بوضع المعلومات في الذاكرة المشتركة و تصبح مسؤولية البرنامج المستقبل ان يفحص وجود بيانات جديدة في هذه الذاكرة .

شيفرة البرنامجين يمكن الحصول عليها من الوصلة التالية:

http://arabteam.nicmatic.com/adel/MemoryMa...MappedFiles.zip

#2

السلام عليكم صديقي عادل ...

بصراحة مشاركاتك هذه أكيد يجب أن تخلد في الموقع ..

الفكرة التي طرحتها هي أحد الطرق في مشاركة مساحة في الذاكرة بين عدة طرق آخرى وهي الأفضل .. ولكن حبيت أن أضيف من بعض الأساليب الأخرى التي يمكن أن تستخدم ..

وعلى فكرة الطريقة التي ذكرتها ممكن استخدامها عندما تحتاج إلى ارسال رسالة إلى process آخر وهذه الرسالة تحتاج إلى مؤشر. وأحد التطبيقات التي رأيتها والتي تستخدم هذه الطريقة هي معرفة مواقع الأيقونات على سطح المكتب بالاحداثيات x و y للشاشة .

أولا بالنسبة للبرنامج السابق طبعا ممكن أيضا استخدام الرسائل فيه أي يقوم البرنامج الأول بارسال رسالة إلى البرنامج الثاني ويضع بارامارته في الرسالة أي في lParam أو wParam .. وهي حوالي 32 بت للواحدة وهي تكفي بشكل عام من أجل أكثر الأغراض ... (ولكن حذاري من ارسال رسالة إلى process آخر تحمل مؤشرات لأن هذه المؤشرات سوف تؤشر إلى موقع آخر في الذاكرة) .

طبعا الرسالة يتم تعريفها من قبل المبرمج كالتالي :

#define MY_MSG     WM_USER + 1

لأنه يجب أن تكون رسائل المستخدم تبدأ من WM_USER وأنت طالع حتى لا تتخربط مع رسائل الويندوز .

والطريقة الثانية في مشاركة منطقة في الذاكرة بين برنامجين هي خاصية في مكتبات الربط الديناميكي . وهي أنه يمكن ان يتم حجز متحول في ال DLL في منطقة segment هذه المنطقة تعطى لها خاصية sharing .. وبالتالي أي برنامج يقوم بتحميل هذه المكتبة فإن منطقة ال sharing يتم الوصول لها وتعديلها من جميع البرامج . طبعا هذه الطريقة ليست عمليه مثل تلك . ولكنها يمكن أن تعطي فكرة ..

طبعا كيفية عمل ذلك وهو كالتالي :

  • تسمية المقطع مع حجز قيم المتحولات بداخله في منطقة الglobal في ملف ال dll كالتالي :
    #pragma data_seg(".shdata")
          char array[10];
          WORD value;
    #pragma data_seg()


  • الخطوة الثانية وهي اعطاء خصائص هذه المنطقة من الملف أو الذاكرة على أن تكون sharing وهي تتم بطريقتين .
    الأولى : وهي تتم داخل ملف ال DEF تبع مكتبة ال DLL حيث يتم كتابة :
    SECTIONS
         .shdata   READ WRITE SHARED


    الثانية وهي تتم عن طريق اضافة خيار للlinker من خيارات المشروع أو ال setting من قائمة project ، ثم اذهب إلى الصفحة Link ومنه أضف مايلي في مربع النص Project Obtions:

    /SECTION:.shdata,RWS


وهذا ماعندي .. :)

Coding on the Cloud and for the Cloud!

My Blog

#3

السلام عليكم.

و الله مداخلة حلوة يا هاني:)

أنا كنت بدي أستخدم الطريقة الاولى اللي ذكرتها بس قلت ما بدي أعقد البرنامج:) بس الفكرة الثانية اللي ذكرتها جديدة و لا أعرفها و الله يعطيك العافية

مع التحيات.

#4

أشكرك يا الأخ عادل

ولك تحياتي

#5

اخي عادل

والله المفروض هذي التجارب تكتب في مكان خاص بها .

الله يكثر من امثالك

ولكن عندي ملاحظة يا ليت تتقبلها بروح رياضية

مجرد راي خاص

يا ليت انك تخلي ما بين كل تجربة والاخرى يومين او ثلاثة . قولي ليش .

عشاني انا وبعض الدارسين لهذه اللغة لما اكون اقرا تجربة من تجاربك واكون حاط في بالي اني هذي اخر تجربة كتبتها يكون فهم التجربة فهم متقن وكامل .

لكن لما تكون في تجارب ثانية كتبتها وانا لسه ما خلصت التجارب السابقة يكون في ضغط نفسي . بحيث اني ابغى اخلص التجربة بسرعة عشان اروح للي بعدها. وما يخفى عليك احنا تونا مبتدئين والفهم علينا صعب في هذي اللغة .يعني هذي اللغة صعبة على المحترفين فما بالك علينا احنا هذا مجرد امر معنوي

ارجو انك تتقبلها بروح رياضية لان هذا مجرد راي شخصي .

اخوك عبدالرحمن .

#6

السلام عليكم.

أخي عبد الرحمن مافي مشكلة يمكنك أن تسجل أي ملاحظةو بالعكس أنا أستفيد من ملاحظاتكم إن كانت في البرامج التي أكتبها أو بشكل عام:)

بالنسبة لسلسلة التجارب سنحاول أن نضع لها قسم خاص بحيث تكون مؤرشفة و على فكرة يمكنكم أيضا المشاركة بأي تجارب تعرفونها :)

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

أرجو أن تكون قد فهمت وجهة نظري:)

و مثل ما قلتلك يمكنك أن تسجل أية ملاحظات:)

مع التحيات.

#7

قديم - مفيد جدًا

هذا الموضوع مغلق.

مواضيع مشابهة