P I N TO S - P RO C E S S E R O C H T R Å DA R
En kodstudie i hur Pintos hanterar processer och trådar.
marhe414, sebto088, timan976, joncr042, joakv409
P RO C E S S E R O C H T R Å DA R
programmet Word vill man ju kunna skriva
samtidigt som rättstavningsprogrammet körs i
bakgrunden. Detta styrs med flera trådar.
Detta dokument kommer att ge en
övergripande syn av Pintos operativsystem och
mer specifikt hur operativsystemet hanterar och
sköter processer samt trådar. Pintos kommer att
jämföras mot boken Operating System
C o n c e p t s s o m b e s k r i ve r h u r v a n l i g a
operativsystem är uppbyggda för att ge
perspektiv på det som Pintos gör speciellt.
Vidare kommer vi även reflektera över hur
Pintos kan förbättras och vilka ändringar som
kan göras för att skapa denna förbättring.
För varje tråd behöver man även där ha koll på
viss information. Denna information sparas ner i
ett så kallat Thread Control Block.
Data som skulle kunna sparas i denna är frame
pointer, stack pointer, CPU flags och nästa
instruktion att utföra.
I Pintos hittar man denna information i
datastrukturen intr_frame som ligger i threads/
interrupt.h.
PCB
Schemaläggning
För varje process som skapas i ett
operativsystem kan det vara bra att ha koll på
viss information. Denna information sparar man
ner i ett så kallat Process Control Block, eller Task
Control Block som det även kallas.
I Pintos används First Come First Serve Roundrobin algoritmen för schemaläggning. Detta
innebär att trådar plockas från ready-kön i den
ordning de kom in men att en tråd endast får
exekver a i ett visst antal ticks innan
schemaläggaren tvingar ett trådbyte. Antalet
ticks som en tråd får exekvera i skiljer sig från
operativsystem till operativsystem, men i Pintos
är det satt till 4 ticks. Då det i Pintos går 100
ticks per sekund innebär det att 4 ticks är lika
med ungefär 40 millisekunder.
I ett vanligt Process Control Block kan man finna
data såsom process state, program counter,
CPU registers, CPU-scheduling, Memor ymanagement infor mation, Accounting
information samt open files.
I Pintos finns det endast en tråd per process så
därför har man valt att lägga den väsentligaste
informationen från ett PCB i datastrukturen
thread. Denna datastruktur finns i threads/
thread.c eftersom det inte finns någon
datastruktur i userprog/process.c för att göra
detta. Man har valt att lägga information såsom
thread ID (som är exakt samma som process
ID), thread state, stack pointer, priority, list of
open files och page director y i denna
datastruktur. Som man kan se stämmer många
av dessa överens med de olika delarna som
finns i ett vanligt PCB.
Till skillnad från andra operativsystem använder
sig Pintos av endast en kö för att hålla reda på
trådar. Denna kö benämns ready-kön och måste
såklart implementeras på något sätt; i Pintos
används en enkellänkad lista, deklarerad i
thread.c:25:
static struct list ready_list;
Denna lista lagrar instanser av struct thread
(indirekt genom struct list_elem) vilka
representerar trådar som är redo att exekvera.
Trådar i den här kön har alltid statusen
THREAD_READY.
Andra statusar en tråd kan ha är
THREAD_BLOCKED , THREAD_RUNNING , och
THREAD_DYING.
TCB
Varför skapar man en så kallad "tråd" för och
inte lägger allt detta i processen? De har ju trots
allt samma ID.
Jo, för i de flesta operativsystemen vill man
kunna köra flera trådar för varje process. I t.ex.
2
Figur 1. Olika states en tråd kan befinna sig i samt vilka funktioner som påverkar statet.
Som man ser i figuren ovan finns det tre
funktioner som förflyttar en tråd till ready-kön:
och vise versa. När de i boken t.ex. lägger in en
process i en schema kö lägger vi in en tråd i kön.
• thread_create,
Om man öppnar thread.h filen och undersöker
structen för hur en tråd är uppbyggd märker
man snart att flera variabler som ska tillhöra en
process tillhör själva tråden. Den som sticker ut
mest är:
vars uppgift är att skapa en
ny tråd. Använder sig utav thread_unblock
för att göra förflyttningen då en tråd alltid
börjar sin livscykel som blockerad.
som förflyttar en f.d
blockerad tråd till ready-kön.
• thread_unblock
enum thread_status status;
vilket är något man ofta brukar ha för en
process.
sköter preemption, vilket
innebär att den aktiva tråden (som kan fås via
thread_current) tvingas ge upp CPU:n för
att andra trådar skall få en chans att exekvera.
• thread_yield
Tråden saknar även vem dess förälder är och
vilka barn den bringat till liv i systemet, medan
en process har dessa variabler. Detta kan ses
som en allvarlig brist då man i boken beskriver
att man bygger upp processer i en form av
processträd. I det fallet skulle barnprocesser
avslutas i samband med att föräldraprocessen
avslutas.
En annan funktion som är värd att nämna är
schedule. Denna funktion, tillsammans med
schedule_tail, tar en tråd från ready-kön och
gör den till den aktiva tråden som exekverar.
schedule funktionen använder sig utav
next_thread_to_run för att välja en tråd från
ready-kön, vilken helt enkelt tar den första
tråden i kön (kom ihåg att Pintos använder sig
utav FCFS Round-robin).
Beroende på hur man utför t labben för
filhantering så sparar man en öppen fil-lista i
tråden eller ej. Jag valde att spara detta i tråden
vilket resulterar i att tråden mer påminner om
en process än en tråd. Då de i boken tar upp att
man öppnar filer för en process inte för själva
tråden.
Trådars relation till processer
Trådar och processer är "ett" i Pintos medan i
boken så är de delade, vilket har resulterat i att
mycket av koden är hopvir ad och
funktionaliteter hos processer finns hos trådar
3
Slår man upp process_wait funktionen i
process.c så finner man snart att den arbetar
direkt med den nuvarande tråden och inte en
nuvarande process. Det finns inte heller någon
struct för en process i Pintos vilket betyder att
processer är något abstrakt, de finns där men
ändå inte. Man har dem men man lagrar
informationen i respektive tråd.
operativsystem (mer info se ovan) så initieras
tråden lite speciellt. När en tråd skapas så byggs
den ihop blockerad för att sedan läggas redo sist
i ready kön, vilket är vad thread_create
funktionen utför. thread_unblock tar bort
blockeringen från tråden och lägger den i ready
kön.
Sammanfattning
Process creation som finns förklarat i boken om
hur man skapar en process finns inte som
funktion i process.h, istället måste vi gå in i
thread.h och ser snart att skapandet av en tråd
påminner mer om skapandet av en process än
en tråd.
Den största skillnaden mellan implementationen
av processer och trådar i pintos och moderna
operativsystem är att pintos mer eller mindre
slagit ihop processer och trådar till en entitet. I
ett modernt operativsystem är processen en
egen datastruktur och implementerar ett eget
PCB. Sedan har processen en eller flera trådar,
oftast enligt one-to-one -modellen där varje
user-tråd har en motsvarande kerneltråd och
kan på så sätt blockera medan de andra
kerneltrådarna och motsvarande user-trådar kan
fortsätta att exekvera. För att göra en sådan
implementation i pintos skulle processen behöva
vara en egen struct istället för att bara
implementera en tråd. Tråd-structen skulle
behöva skilja på user och kernel-trådar för att
kunna implementera one-to-one modellen.
PCB, som just nu är implementerad i tråden,
skulle behöva flyttas till processens struct. TCB
skulle dock kunna ligga kvar på ett liknande sätt i
tråd-structen. Process-structen skulle dessutom
behöva implementera en lista för att kunna ha
fler än en tråd.
Process termination som kallas process_exit i
Pintos är tom och utför inget. Vi får röra oss till
thread.h där vi kan se att thread_exit avslutar
den nuvarande körande tråden, vilket process
termination skulle ha uppnått.
Vi har en bool som bestämmer om vi ska
använda oss utav Round-robin eller multi-level
feedback queue scheduler. Som standard kör vi
Round-robin och har endast hittat
implementation för multi-level feedback queue
scheduler i testfilerna.
Var 100 ms sker en interrupt som avbryter och
kallar på intr_yield_on_return som sparar
den nuvarande trådens arbete och kallar på
nästa tråd med hjälp av next_thread_to_run.
Finns det ingen tråd i ready kön returneras
idle_thread. Skulle en tråd avslutas i förtid
körs thread_exit som i sin tur kallar på
schedule för att hämta nästa tråd till
exekvering.
Källor
1. http://www.scs.stanford.edu/12au-cs140/
notes/l2.pdf [Hämtad 2013-02-21]
Som tidigare förklarat så är en process
egentligen ganska irrelevant och gör inte så
mycket utan det är själva tråden som skapar och
lagrar det mest vitala för vad en process bör
innehålla. Det finns inte så många större
skillnader på den Pintos gör vid skapandet av
dessa trådar gentemot vad boken förklarar.
Dock finns det några saker som inte görs som
är värt att nämna. Förutom att trådarna i Pintos
inte bygger trädstrukturer med fler childprocesser som är standard i nästan alla
2. Silberschatz, A., Galvin, P.B. och Gagne G.
Operating System Concepts 8th Edition
International Student Version (2010)
3. Filer från operativsystemet Pintos:
• threads/thread.{h,c}
• userprog/process.{h,c}
• threads/interrupt.h
4