القراء مثلك يساعدون في دعم MUO. عند إجراء عملية شراء باستخدام الروابط الموجودة على موقعنا ، فقد نربح عمولة تابعة.

تحدث حالة السباق عندما يجب أن تحدث عمليتان بترتيب معين ، ولكن يمكن تشغيلهما بترتيب معاكس.

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

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

كيف يقوم المعالج بتبديل العمليات

أنظمة التشغيل الحديثة يمكن تشغيل أكثر من عملية في وقت واحد ، تسمى تعدد المهام. عندما تنظر إلى هذه العملية من حيث دورة تنفيذ وحدة المعالجة المركزية، قد تجد أن تعدد المهام غير موجود حقًا.

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

على سبيل المثال ، تعمل خوارزمية Round Robin ، وهي واحدة من أبسط خوارزميات التحويل ، على النحو التالي:

instagram viewer

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

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

بالمناسبة ، كما يوضح الرسم البياني أعلاه ، تفتقر خوارزمية Round Robin إلى أي تحسين أو معالجة مفاهيم الأولوية. نتيجة لذلك ، إنها طريقة بدائية إلى حد ما ونادرًا ما تستخدم في الأنظمة الحقيقية.

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

مثال على تطبيق الويب وحالة العرق

تحقق من تطبيق Flask البسيط أدناه للتفكير في مثال ملموس لكل ما قرأته حتى الآن. الغرض من هذا التطبيق هو إدارة المعاملات المالية التي ستتم على الويب. احفظ ما يلي في ملف باسم money.py:

من قارورة يستورد قارورة
من flask.ext.sqlalchemy يستورد SQLAlchemy

التطبيق = قارورة (__name__)
app.config ['SQLALCHEMY_DATABASE_URI'] = 'sqlite: ////tmp/test.db'
db = SQLAlchemy (تطبيق)

فصلحساب(ديسيبل. نموذج):
معرف = ديسيبل. العمود (ديسيبل. عدد صحيح ، مفتاح أساسي = حقيقي)
الكمية = ديسيبل. العمود (ديسيبل. خيط(80) ، فريد = حقيقي)

def__فيه__(ذاتي ، عد):
self.amount = المبلغ

def__إعداد__(الذات):
يعود ''٪ self.amount

@ app.route ("/")
defأهلاً():
account = Account.query.get (1) # هناك محفظة واحدة فقط.
يعود "إجمالي المال = {}". تنسيق (account.amount)

@ app.route ("/ إرسال /")
defيرسل(كمية):
account = Account.query.get (1)

لو int (account.amount) يعود "رصيد غير كاف. إعادة تعيين الأموال مع /reset!)"

account.amount = int (account.amount) - المبلغ
db.session.commit ()
يعود "المبلغ المرسل = {}". تنسيق (المبلغ)

@ app.route ("/ إعادة تعيين")
defإعادة ضبط():
account = Account.query.get (1)
account.amount = 5000
db.session.commit ()
يعود "إعادة تعيين الأموال".

لو __name__ == "__main__":
app.secret_key = 'heLLoTHisIsSeCReTKey!'
app.run ()

لتشغيل هذا الرمز ، ستحتاج إلى إنشاء سجل في جدول الحساب ومتابعة المعاملات عبر هذا السجل. كما ترى في الكود ، هذه بيئة اختبار ، لذا فهي تجري معاملات مقابل السجل الأول في الجدول.

من مال يستورد ديسيبل
ديسيبل.create_all()
من مال يستورد حساب
الحساب = الحساب (5000)
ديسيبل.حصة.يضيف(حساب)
ديسيبل.حصة.يقترف()

لقد قمت الآن بإنشاء حساب برصيد 5000 دولار. أخيرًا ، قم بتشغيل كود المصدر أعلاه باستخدام الأمر التالي ، بشرط أن يكون لديك حزم Flask و Flask-SQLAlchemy مثبتة:

الثعبانمال.السنة التحضيرية

إذاً لديك تطبيق الويب Flask الذي يقوم بعملية استخراج بسيطة. يمكن لهذا التطبيق إجراء العمليات التالية باستخدام روابط طلب GET. نظرًا لأن Flask يعمل على منفذ 5000 افتراضيًا ، فإن العنوان الذي تصل إليه هو 127.0.0.1:5000/. يوفر التطبيق نقاط النهاية التالية:

  • 127.0.0.1:5000/ يعرض الرصيد الحالي.
  • 127.0.0.1:5000/send/{amount} يطرح المبلغ من الحساب.
  • 127.0.0.1:5000/reset يعيد الحساب إلى 5000 دولار.

الآن ، في هذه المرحلة ، يمكنك فحص كيفية حدوث الثغرة الأمنية لحالة السباق.

احتمالية تعرض حالة السباق للخطر

يحتوي تطبيق الويب أعلاه على ثغرة أمنية محتملة في حالة العرق.

تخيل أن لديك 5000 دولار لتبدأ بها وأنشئ طلبي HTTP مختلفين سيرسلان دولارًا واحدًا. لهذا ، يمكنك إرسال طلبي HTTP مختلفين إلى الارتباط 127.0.0.1:5000/send/1. افترض ذلك ، في أقرب وقت خادم الويب يعالج الطلب الأول ، توقف وحدة المعالجة المركزية هذه العملية وتعالج الطلب الثاني. على سبيل المثال ، قد تتوقف العملية الأولى بعد تشغيل سطر التعليمات البرمجية التالي:

account.amount = int(مبلغ الحساب) - المبلغ

قام هذا الرمز بحساب إجمالي جديد ولكنه لم يحفظ السجل في قاعدة البيانات بعد. عندما يبدأ الطلب الثاني ، سيتم إجراء نفس الحساب ، بطرح 1 دولار من القيمة في قاعدة البيانات - 5000 دولار - وتخزين النتيجة. عند استئناف العملية الأولى ، ستخزن قيمتها - 4،999 دولارًا - والتي لن تعكس أحدث رصيد للحساب.

لذلك ، تم إكمال طلبين ، ويجب أن يطرح كل منهما دولارًا واحدًا من رصيد الحساب ، مما أدى إلى رصيد جديد قدره 4،998 دولارًا أمريكيًا. ولكن ، بناءً على الترتيب الذي يعالج به خادم الويب ، يمكن أن يكون رصيد الحساب النهائي 4،999 دولارًا.

تخيل أنك ترسل 128 طلبًا لإجراء تحويل بقيمة دولار واحد إلى النظام المستهدف في إطار زمني مدته خمس ثوانٍ. نتيجة لهذه المعاملة ، سيكون كشف الحساب المتوقع 5000 - 128 دولارًا = 4875 دولارًا. ومع ذلك ، نظرًا لحالة السباق ، قد يختلف الرصيد النهائي بين 4،875 دولارًا و 4،999 دولارًا.

يعد المبرمجون أحد أهم مكونات الأمان

في مشروع برمجي ، بصفتك مبرمجًا ، لديك عدد قليل من المسؤوليات. كان المثال أعلاه لتطبيق بسيط لتحويل الأموال. تخيل أنك تعمل في مشروع برمجي يدير حسابًا مصرفيًا أو الواجهة الخلفية لموقع تجارة إلكترونية كبير.

يجب أن تكون على دراية بمثل هذه الثغرات الأمنية حتى يكون البرنامج الذي كتبته لحمايتها خاليًا من الثغرات الأمنية. هذا يتطلب مسؤولية قوية.

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