Läsare som du hjälper till att stödja MUO. När du gör ett köp med hjälp av länkar på vår webbplats kan vi tjäna en affiliate-provision.
Ett racetillstånd uppstår när två operationer måste ske i en specifik ordning, men de kan köras i motsatt ordning.
Till exempel, i en flertrådad applikation kan två separata trådar komma åt en gemensam variabel. Som ett resultat, om en tråd ändrar värdet på variabeln, kan den andra fortfarande använda den äldre versionen och ignorera det senaste värdet. Detta kommer att orsaka oönskade resultat.
För att bättre förstå denna modell skulle det vara bra att undersöka processväxlingsprocessen för processorn noggrant.
Hur en processor växlar processer
Moderna operativsystem kan köra mer än en process samtidigt, så kallad multitasking. När man ser på denna process i termer av CPU: s exekveringscykel, kanske du upptäcker att multitasking egentligen inte existerar.
Istället växlar processorer hela tiden mellan processer för att köra dem samtidigt eller åtminstone agera som om de gör det. CPU: n kan avbryta en process innan den har slutförts och återuppta en annan process. Operativsystemet styr hanteringen av dessa processer.
Till exempel fungerar Round Robin-algoritmen, en av de enklaste växlingsalgoritmerna, enligt följande:
I allmänhet tillåter denna algoritm att varje process körs under mycket små bitar av tid, som operativsystemet bestämmer. Detta kan till exempel vara en period på två mikrosekunder.
CPU: n tar varje process i tur och ordning och kör kommandon som körs i två mikrosekunder. Den fortsätter sedan till nästa process, oavsett om den nuvarande är klar eller inte. Alltså, ur en slutanvändares synvinkel, verkar mer än en process vara igång samtidigt. Men när du tittar bakom kulisserna gör CPU: n fortfarande saker i ordning.
Förresten, som diagrammet ovan visar, saknar Round Robin-algoritmen några optimerings- eller bearbetningsprioritetsuppfattningar. Som ett resultat är det en ganska rudimentär metod som sällan används i riktiga system.
För att förstå allt detta bättre, föreställ dig att två trådar körs. Om trådarna kommer åt en gemensam variabel kan ett rastillstånd uppstå.
Ett exempel på webbapplikation och tävlingsvillkor
Kolla in den enkla Flask-appen nedan för att reflektera över ett konkret exempel på allt du har läst hittills. Syftet med denna applikation är att hantera pengatransaktioner som kommer att ske på webben. Spara följande i en fil med namnet money.py:
från flaska importera Flaska
från flask.ext.sqlalchemy importera SQLAlchemyapp = Kolv (__namn__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'
db = SQLAlchemy (app)klasskonto(db. Modell):
id = db. Kolumn (db. Heltal, primärnyckel = Sann)
belopp = db. Kolumn (db. Sträng(80), unik = Sann)def__i det__(själv, räkna):
själv.belopp = beloppdef__repr__(själv):
lämna tillbaka '' % självbelopp@app.route("/")
defHej():
konto = Account.query.get(1) # Det finns bara en plånbok.
lämna tillbaka "Total Money = {}".format (account.amount)@app.route("/send/")
defskicka(belopp):
konto = Account.query.get(1)om int (account.amount) < summa:
lämna tillbaka "Otillräcklig balans. Återställ pengar med /reset!)"konto.belopp = int (konto.belopp) - belopp
db.session.commit()
lämna tillbaka "Belopp skickat = {}".format (belopp)@app.route("/reset")
defåterställa():
konto = Account.query.get(1)
konto.belopp = 5000
db.session.commit()
lämna tillbaka "Pengar återställs."
om __namn__ == "__main__":
app.secret_key = 'heLLoTHisIsSeCReTKey!'
app.run()
För att köra den här koden måste du skapa en post i kontotabellen och fortsätta transaktionerna över denna post. Som du kan se i koden är detta en testmiljö, så den gör transaktioner mot den första posten i tabellen.
från pengar importera db
db.create_all()
från pengar importera konto
konto = Konto (5000)
db.session.Lägg till(konto)
db.session.begå()
Du har nu skapat ett konto med ett saldo på $5 000. Slutligen, kör ovanstående källkod med följande kommando, förutsatt att du har paketen Flask och Flask-SQLAlchemy installerade:
pytonormpengar.py
Så du har webbapplikationen Flask som gör en enkel extraktionsprocess. Denna applikation kan utföra följande operationer med GET-förfrågningslänkar. Eftersom Flask körs på 5000-porten som standard är adressen du kommer åt den på 127.0.0.1:5000/. Appen tillhandahåller följande slutpunkter:
- 127.0.0.1:5000/ visar aktuellt saldo.
- 127.0.0.1:5000/send/{amount} drar av beloppet från kontot.
- 127.0.0.1:5000/återställning återställer kontot till $5 000.
Nu, i detta skede, kan du undersöka hur sårbarheten för rastillståndet uppstår.
Sannolikhet för en sårbarhet för rastillstånd
Ovanstående webbapplikation innehåller en möjlig sårbarhet för rastillstånd.
Föreställ dig att du har $5 000 att börja med och skapa två olika HTTP-förfrågningar som skickar $1. För detta kan du skicka två olika HTTP-förfrågningar till länken 127.0.0.1:5000/skicka/1. Antag att så snart webbservern behandlar den första begäran, stoppar CPU: n denna process och behandlar den andra begäran. Till exempel kan den första processen stoppas efter att ha kört följande kodrad:
konto.belopp = int(konto.belopp) - belopp
Den här koden har beräknat en ny summa men har ännu inte sparat posten i databasen. När den andra begäran börjar kommer den att utföra samma beräkning, subtrahera $1 från värdet i databasen—$5 000—och lagra resultatet. När den första processen återupptas kommer den att lagra sitt eget värde—$4 999—som inte kommer att återspegla det senaste kontosaldot.
Så två förfrågningar har slutförts, och var och en borde ha subtraherat $1 från kontosaldot, vilket resulterar i ett nytt saldo på $4,998. Men beroende på i vilken ordning webbservern bearbetar dem, kan det slutliga kontosaldot vara $4 999.
Föreställ dig att du skickar 128 förfrågningar om att göra en $1-överföring till målsystemet inom en tidsram på fem sekunder. Som ett resultat av denna transaktion kommer det förväntade kontoutdraget att vara $5 000 - $128 = $4 875. Men på grund av tävlingsförhållandena kan det slutliga saldot variera mellan $4 875 och $4 999.
Programmerare är en av de viktigaste komponenterna i säkerhet
I ett mjukvaruprojekt har du som programmerare en hel del ansvar. Exemplet ovan var för en enkel överföringsapplikation. Föreställ dig att arbeta med ett programvaruprojekt som hanterar ett bankkonto eller backend på en stor e-handelswebbplats.
Du måste vara bekant med sådana sårbarheter så att programmet du har skrivit för att skydda dem är fritt från sårbarheter. Detta kräver ett starkt ansvar.
En sårbarhet för rastillstånd är bara en av dem. Oavsett vilken teknik du använder måste du se upp för sårbarheter i koden du skriver. En av de viktigaste färdigheterna du kan förvärva som programmerare är förtrogenhet med mjukvarusäkerhet.