Читаоци попут вас помажу у подршци МУО. Када обавите куповину користећи везе на нашем сајту, можда ћемо зарадити провизију за партнере.

Услов трке настаје када се две операције морају одвијати у одређеном редоследу, али се могу одвијати у супротном редоследу.

На пример, у апликацији са више нити, две одвојене нити могу приступити заједничкој променљивој. Као резултат тога, ако једна нит промени вредност променљиве, друга може и даље користити старију верзију, игноришући најновију вредност. Ово ће изазвати нежељене резултате.

Да бисмо боље разумели овај модел, било би добро да пажљиво испитамо процес промене процеса процесора.

Како процесор мења процесе

Савремени оперативни системи може покренути више од једног процеса истовремено, што се назива мултитаскинг. Када погледате овај процес у смислу Циклус извршавања ЦПУ-а, можда ћете открити да мултитаскинг заправо не постоји.

Уместо тога, процесори се стално пребацују између процеса да би их истовремено покренули или се бар понашали као да то раде. ЦПУ може прекинути процес пре него што је завршен и наставити други процес. Оперативни систем контролише управљање овим процесима.

instagram viewer

На пример, Роунд Робин алгоритам, један од најједноставнијих алгоритама за пребацивање, функционише на следећи начин:

Уопштено говорећи, овај алгоритам омогућава да се сваки процес изводи током веома малих делова времена, како то одреди оперативни систем. На пример, ово може бити период од две микросекунде.

ЦПУ редом преузима сваки процес и извршава команде које ће се изводити две микросекунде. Затим се наставља на следећи процес, без обзира да ли је тренутни завршен или не. Дакле, са тачке гледишта крајњег корисника, чини се да више од једног процеса ради истовремено. Међутим, када погледате иза кулиса, ЦПУ и даље ради ствари по реду.

Узгред, као што показује горњи дијаграм, Роунд Робин алгоритам нема појмове о оптимизацији или приоритету обраде. Као резултат тога, то је прилично рудиментарна метода која се ретко користи у стварним системима.

Сада, да бисте боље разумели све ово, замислите да се покрећу две нити. Ако нити приступају заједничкој променљивој, може се појавити услов трке.

Пример веб апликације и услова за трку

Погледајте једноставну апликацију Фласк у наставку да размислите о конкретном примеру свега што сте до сада прочитали. Сврха ове апликације је управљање новчаним трансакцијама које ће се одвијати на вебу. Сачувајте следеће у датотеци под називом новац.пи:

из пљоска увоз Фласк
из фласк.ект.склалцхеми увоз СКЛАлцхеми

апп = Фласк (__наме__)
апп.цонфиг['СКЛАЛЦХЕМИ_ДАТАБАСЕ_УРИ'] = 'склите:////тмп/тест.дб'
дб = СКЛАлцхеми (апликација)

класаРачун(дб. модел):
ид = дб. Колона (дб. Цео број, примарни_кључ = Истина)
износ = дб. Колона (дб. Низ(80), јединствено = Истина)

деф__у томе__(сам, броји):
само.износ = износ

деф__репр__(сам):
повратак '' % селф.амоунт

@апп.роуте("/")
дефЗдраво():
налог = Аццоунт.куери.гет(1) # Постоји само један новчаник.
повратак "Тотал Монеи = {}".формат (аццоунт.амоунт)

@апп.роуте("/сенд/")
дефпослати(износ):
налог = Аццоунт.куери.гет(1)

ако инт (аццоунт.амоунт) < износ:
повратак „Недовољна равнотежа. Ресетујте новац са /reset!)"

аццоунт.амоунт = инт (аццоунт.амоунт) - износ
дб.сессион.цоммит()
повратак "Износ послат = {}".формат (износ)

@апп.роуте("/ресет")
дефресетовати():
налог = Аццоунт.куери.гет(1)
аццоунт.амоунт = 5000
дб.сессион.цоммит()
повратак „Ресетовање новца“.

ако __наме__ == "__маин__":
апп.сецрет_кеи = 'хеЛЛоТХисИсСеЦРеТКеи!'
апп.рун()

Да бисте покренули овај код, мораћете да креирате запис у табели рачуна и наставите трансакције преко овог записа. Као што видите у коду, ово је тестно окружење, тако да врши трансакције према првом запису у табели.

из новац увоз дб
дб.цреате_алл()
из новац увоз Рачун
налог = Рачун (5000)
дб.седница.додати(рачун)
дб.седница.урадити()

Сада сте креирали налог са стањем од 5.000 УСД. Коначно, покрените горњи изворни код користећи следећу команду, под условом да имате инсталиране пакете Фласк и Фласк-СКЛАлцхеми:

питхонновац.пи

Дакле, имате веб апликацију Фласк која ради једноставан процес екстракције. Ова апликација може да изврши следеће операције са ГЕТ везама захтева. Пошто Фласк подразумевано ради на порту 5000, адреса на којој му приступате је 127.0.0.1:5000/. Апликација пружа следеће крајње тачке:

  • 127.0.0.1:5000/ приказује тренутно стање.
  • 127.0.0.1:5000/сенд/{амоунт} одузима износ са рачуна.
  • 127.0.0.1:5000/ресет ресетује рачун на 5.000 долара.

Сада, у овој фази, можете испитати како се јавља рањивост услова трке.

Вероватноћа рањивости услова расе

Горе наведена веб апликација садржи могућу рањивост услова трке.

Замислите да имате 5.000 УСД за почетак и креирајте два различита ХТТП захтева који ће послати 1 УСД. За ово можете послати два различита ХТТП захтева на везу 127.0.0.1:5000/сенд/1. Претпоставимо да, чим веб сервера обрађује први захтев, ЦПУ зауставља овај процес и обрађује други захтев. На пример, први процес може да се заустави након покретања следеће линије кода:

аццоунт.амоунт = инт(рачун.износ) - износ

Овај код је израчунао нови укупан износ, али још увек није сачувао запис у бази података. Када започне други захтев, извршиће исти прорачун, одузимајући 1 УСД од вредности у бази података — 5.000 УСД — и чувајући резултат. Када се први процес настави, он ће ускладиштити сопствену вредност — 4.999 УСД — која неће одражавати најновије стање на рачуну.

Дакле, два захтева су завршена и сваки је требало да одузме 1 долар од стања на рачуну, што је резултирало новим стањем од 4,998 долара. Али, у зависности од редоследа којим их веб сервер обрађује, коначно стање на рачуну може бити 4.999 долара.

Замислите да пошаљете 128 захтева за трансфер од 1 долара циљном систему у временском оквиру од пет секунди. Као резултат ове трансакције, очекивани извод ће бити 5.000 УСД - 128 УСД = 4.875 УСД. Међутим, због услова трке, коначни салдо може варирати између 4.875 и 4.999 долара.

Програмери су једна од најважнијих компоненти безбедности

У софтверском пројекту, као програмер, имате доста одговорности. Горњи пример је био за једноставну апликацију за трансфер новца. Замислите да радите на софтверском пројекту који управља банковним рачуном или позадином великог сајта за е-трговину.

Морате бити упознати са таквим рањивостима тако да програм који сте написали да их заштити не буде рањивости. Ово захтева велику одговорност.

Рањивост стања расе је само једна од њих. Без обзира коју технологију користите, морате пазити на рањивости у коду који пишете. Једна од најважнијих вештина које можете стећи као програмер је познавање софтверске безбедности.