Homework 2
Homework 2
ﺗﻤﺎرﯾﻦ ﺗﺌﻮری
.۱در زﻣﯿﻨﻪ ﻣﺎﺷﯿﻦﻫﺎی ﻣﺠﺎزی ،ﺗﻔﺎوتﻫﺎی اﺻﻠﯽ full virtualizationو para-virtualizationرا ﺗﻮﺿﯿﺢ دﻫﯿﺪ .ﻫﻤﭽﻨﯿﻦ
ﭼﺎﻟﺶﻫﺎﯾﯽ ﮐﻪ در ﺳﺎﻣﺎﻧﻪﻫﺎی ﻧﺎﻫﻤﮕﻮن ﮐﻪ از ﻫﺮ دو روش ﻣﺠﺎزیﺳﺎزی اﺳﺘﻔﺎده ﻣﯽﮐﻨﻨﺪ را ﺷﺮح دﻫﯿﺪ و درﺑﺎره روشﻫﺎﯾﯽ
ﮐﻪ ﺑﺮای ﺗﺨﺼﯿﺺ ﻣﻨﺎﺑﻊ و ﺗﻐﯿﯿﺮ ﻣﻨﺎﺑﻊ اﺧﺘﺼﺎص ﯾﺎﻓﺘﻪ در ﭼﻨﯿﻦ ﺳﺎﻣﺎﻧﻪﻫﺎﯾﯽ وﺟﻮد دارد ﺑﺤﺚ ﮐﻨﯿﺪ.
.۲ﺑﻪ ﺳﻮاﻻت زﯾﺮ ﮐﻪ در ﻣﻮرد APIﻫﺎی ﻟﯿﻨﻮﮐﺲ ﻫﺴﺘﻨﺪ ﺑﻪ ﻃﻮر ﻣﺨﺘﺼﺮ ﭘﺎﺳﺦ دﻫﯿﺪ.
آ( در ﭼﻪ ﺳﻨﺎرﯾﻮﻫﺎﯾﯽ اﺳﺘﻔﺎده از )( mmapﺑﻪ ﺟﺎی )( mallocﻣﻨﺎﺳﺐﺗﺮ اﺳﺖ؟
ب( ﭼﺮا )( epollدر ﻣﻘﺎﯾﺴﻪ ﺑﺎ )( selectو )( pollﮐﺎرآﻣﺪﺗﺮ اﺳﺖ؟
ج( ﭼﻪ ﺗﻔﺎوتﻫﺎی اﺻﻠﯽ ﺑﯿﻦ ﺳﯿﺴﺘﻢﮐﺎلﻫﺎی )( readو )( mmapوﺟﻮد دارد؟
.۳در دﻧﯿﺎی اﻣﺮوزی ،ﺑﺴﯿﺎری از ﻣﺮدم و ﺑﺮﻧﺎﻣﻪﻧﻮﯾﺴﺎن ﺑﻪ دﻧﺒﺎل ﺧﺮﯾﺪ ﺳﺮور ﻣﺠﺎزی ﺷﺨﺼﯽ ۱ﻫﺴﺘﻨﺪ VPS .ﻫﺎ ﻣﻌﻤﻮﻻ ﻣﺎﺷﯿﻦﻫﺎﯾﯽ
ﻣﺠﺎزی ﻫﺴﺘﻨﺪ ﮐﻪ ﺑﺮروی ﯾﮏ ﺳﺮور ﻗﺪرﺗﻤﻨﺪ درﺣﺎل اﺟﺮا ﺷﺪن ﻫﺴﺘﻨﺪ ﮐﻪ از اﯾﻨﺘﺮﻧﺖ ﻗﺎﺑﻞ دﺳﺘﺮﺳﯽ ﻫﺴﺘﻨﺪ .ﯾﮑﯽ از ﭘﺎراﻣﺘﺮﻫﺎﯾﯽ
ﮐﻪ زﻣﺎن ﺧﺮﯾﺪ ﺳﺮور ﺑﺎﯾﺪ ﺑﻪ آن ﺗﻮﺟﻪ ﮐﺮد ،ﻣﺪل ﻣﺠﺎزیﺳﺎزی ۲اﺳﺖ .ﺳﻪ ﻣﺪل ﻣﺠﺎزیﺳﺎزی ﻣﻌﺮوف وﺟﻮد دارد:
ESXi - OpenVZ - KVM
ﺑﺎﯾﻨﺮیﻫﺎ در ﻣﻬﻨﺪﺳﯽ ﻣﻌﮑﻮس اﺳﺘﻔﺎده ﻣﯽﺷﻮد .اﯾﻦ اﺑﺰار از ﻃﺮﯾﻖ ﺗﺠﺰﯾﻪ ﮐﺪ ﻣﺎﺷﯿﻦ ﺑﻪ ﻣﺎ ﮐﻤﮏ ﻣﯽﮐﻨﺪ ﺗﺎ ﻓﻬﻢ ﺑﻬﺘﺮی از ﻧﺤﻮه
ﻋﻤﻠﮑﺮد ﺑﺮﻧﺎﻣﻪ داﺷﺘﻪ ﺑﺎﺷﯿﻢ.
آ( ﺣﺎل ﺑﺮﻧﺎﻣﻪ زﯾﺮ ﺑﻪ ﮐﻤﮏ اﯾﻦ اﺑﺰار ﺑﺪﺳﺖ آﻣﺪه اﺳﺖ ﮐﻪ ﯾﮏ ﻓﺮاﺧﻮاﻧﯽ ﺳﯿﺴﺘﻤﯽ را ﻧﺸﺎن ﻣﯽدﻫﺪ ﮐﻪ ﺻﺮﻓﺎ ﺑﺎﯾﺖﮐﺪ آن
را دارﯾﻢ .ﺑﺎ ﺗﻮﺟﻪ ﺑﻪ ﺗﻮاﺑﻌﯽ ﮐﻪ ﺻﺪا زده ﺷﺪه و ﺑﯿﺎن ﻋﻤﻠﮑﺮد ﻫﺮ ﯾﮏ از ﺗﻮاﺑﻊ ﺳﯿﺴﺘﻤﯽ ﺣﺪس ﺑﺰﻧﯿﺪ ﮐﻪ اﯾﻦ ﻓﺮﺧﻮاﻧﯽ
ﺳﯿﺴﺘﻤﯽ ﭼﻪ ﺑﻮده اﺳﺖ.
ب( اﺣﺘﻤﺎﻻ ﺗﺎ اﻻن در ﺑﺮﺧﯽ از دروس دﯾﺪهاﯾﺪ ﮐﻪ ﺑﺮﺧﯽ ﻧﺮماﻓﺰارﻫﺎ ﻣﺎﻧﻨﺪ Protuesﻓﻘﻂ روی وﯾﻨﺪوز اﺟﺮا ﻣﯽﺷﻮﻧﺪ .ﯾﮏ
ﺳﺮی راه وﺟﻮد دارد ﮐﻪ ﻣﯽﺗﻮان اﯾﻦ ﻧﺮماﻓﺰارﻫﺎ را روی ﺳﯿﺴﺘﻢﻋﺎﻣﻞﻫﺎی دﯾﮕﺮ ﻣﺜﻞ Linuxاﺟﺮا ﮐﺮد .ﺗﺤﻘﯿﻖ ﮐﻨﯿﺪ
ﮐﻪ اﯾﻦ ﻧﺮماﻓﺰارﻫﺎ ﭼﮕﻮﻧﻪ ﺑﺎ ﻣﻌﻤﺎری ﺳﯿﺴﺘﻢﻋﺎﻣﻞ دﯾﮕﺮ اﺧﺖ ﻣﯽﺷﻮﻧﺪ و از ﻓﺮاﺧﻮاﻧﯽﻫﺎی ﺳﯿﺴﺘﻢﻋﺎﻣﻞ ﺟﺪﯾﺪ اﺳﺘﻔﺎده
ﻣﯽﮐﻨﻨﺪ .ﻣﯽﺗﻮاﻧﯿﺪ راﺟﻊ ﺑﻪ wineدر ﺳﯿﺴﺘﻢﻋﺎﻣﻞ Linuxﺗﺤﻘﯿﻖ ﮐﻨﯿﺪ.
ج( ﺑﺎ ﺗﻮﺟﻪ ﺑﻪ ﻗﺴﻤﺖ ﻗﺒﻞ ﺑﺮرﺳﯽ ﮐﻨﯿﺪ ﮐﻪ ﯾﮏ وﯾﺮوس ﮐﺎﻣﭙﯿﻮﺗﺮی ﮐﻪ در ﯾﮏ ﻣﺎﺷﯿﻦ ﻣﺠﺎزی اﺟﺮا ﻣﯽﺷﻮد آﯾﺎ ﻣﯽﺗﻮاﻧﺪ در
ﺳﯿﺴﺘﻢﻋﺎﻣﻞ ﻣﯿﺰﺑﺎن ۵ﺧﺮاﺑﮑﺎری اﻧﺠﺎم دﻫﺪ؟
.۵در درس ﺑﺎ ﺳﺎﺧﺘﺎر ۶ﻫﺎی ﻣﺨﺘﻠﻒ ﺳﯿﺴﺘﻢﻋﺎﻣﻞ آﺷﻨﺎ ﺷﺪﯾﺪ .دو ﺳﺎﺧﺘﺎر ﻻﯾﻪای ۷و ﻣﯿﮑﺮوﮐﺮﻧﻞ ۸را درﻧﻈﺮ ﺑﮕﯿﺮﯾﺪ و ﺑﺮ اﺳﺎس
آﻧﻬﺎ ﺑﻪ ﺳﻮاﻻت زﯾﺮ ﭘﺎﺳﺦ دﻫﯿﺪ.
.۱ﻫﺮ دو ﺳﺎﺧﺘﺎر را ﺑﻪ اﺧﺘﺼﺎر ﺗﻮﺿﯿﺢ دﻫﯿﺪ.
.۲در ﻫﺮ ﮐﺪام از ﻣﻮارد زﯾﺮ ﺑﺎ ذﮐﺮ دﻟﯿﻞ ﻣﺸﺨﺺ ﮐﻨﯿﺪ ﮐﻪ اﺳﺘﻔﺎده از ﮐﺪام ﻧﻮع ﺳﯿﺴﺘﻢﻋﺎﻣﻞ ﻣﻨﺎﺳﺐﺗﺮ اﺳﺖ.
آ( ﯾﮏ ﺳﯿﺴﺘﻢ اﯾﻤﻨﯽ-ﺑﺤﺮاﻧﯽ ۹ﻣﺜﻞ ﺳﯿﺴﺘﻢﻫﺎی ﻣﻮرد اﺳﺘﻔﺎده در ﻫﻮاﭘﯿﻤﺎﻫﺎ
ب( ﺳﯿﺴﺘﻢ ﺑﺰرﮔﯽ ﮐﻪ ﻧﯿﺎز ﺑﻪ ﺳﯿﺴﺘﻢﻋﺎﻣﻠﯽ ﺑﺎ ﻫﺴﺘﻪ ﭘﯿﺸﺮﻓﺘﻪ دارد.
ج( ﺳﯿﺴﺘﻤﯽ ﺧﺎصﻣﻨﻈﻮره ﻃﺮاﺣﯽ ﺷﺪه ﺑﺮای ﯾﮏ ﺷﺮﮐﺖ ﮐﻪ اﻣﮑﺎن دارد ﺑﺮ اﺳﺎس ﻧﯿﺎز ﻗﺎﺑﻠﯿﺖﻫﺎی ﻣﺨﺘﻠﻔﯽ ﺑﻪ
ﺳﯿﺴﺘﻢﻋﺎﻣﻞ اﻓﺰوده ﺷﻮد.
د( ﺳﯿﺴﺘﻤﯽ ﮐﻪ ﻻزم اﺳﺖ ﺳﺮوﯾﺲﻫﺎی ﻣﺨﺘﻠﻔﯽ ﺑﻪ ﮐﺎرﺑﺮان ﺑﺴﯿﺎر زﯾﺎدی ﺑﺪﻫﺪ و ﺑﺮﺧﯽ از اﯾﻦ ﮐﺎرﺑﺮان ﻧﯿﺰ ﻣﻤﮑﻦ
اﺳﺖ ﻣﻬﺎﺟﻢ ﺑﺎﺷﻨﺪ و ﯾﺎ ﺳﯿﺴﺘﻢ را ﺑﻪ ﺻﻮرت ﻧﺎﺧﻮاﺳﺘﻪ ﺗﺨﺮﯾﺐ ﮐﻨﻨﺪ.
ه( ﺳﯿﺴﺘﻢﻋﺎﻣﻠﯽ ﮐﻪ ﻻزم اﺳﺖ داﺋﻤﺎ ﻣﻮرد ﺑﺎزرﺳﯽ و رﻓﻊ اﺷﮑﺎل ﻗﺮار ﮔﯿﺮد.
و( ﺷﺮﮐﺘﯽ ﮐﻪ ﺗﯿﻢ ﺑﺰرﮔﯽ در اﺧﺘﯿﺎر دارد و ﻗﺼﺪ دارد ﺳﯿﺴﺘﻢﻋﺎﻣﻞ را ﺗﻮﺳﻌﻪ دﻫﺪ.
ز( ﯾﮏ ﺳﯿﺴﺘﻢ ﻧﻬﻔﺘﻪ ۱۰ﮐﻪ ﺣﺎﻓﻈﻪ ﺑﺴﯿﺎر ﮐﻤﯽ در اﺧﺘﯿﺎر دارد ،اﻣﺎ ﺑﻪ ﺑﺨﺶ ﺑﺴﯿﺎر ﮐﻮﭼﮑﯽ از ﻗﺎﺑﻠﯿﺖﻫﺎی ﺳﯿﺴﺘﻢﻋﺎﻣﻞ
ﻧﯿﺎزﻣﻨﺪ اﺳﺖ.
.۶ﺑﻪ ﺳﻮاﻻت زﯾﺮ در ﻣﻮرد system callﻫﺎ ﭘﺎﺳﺦ دﻫﯿﺪ:
Host OS ۵
Structure ۶
Layered ۷
Microkernel ۸
Safety Critical ۹
Embedded System ۱۰
ﺻﻔﺤﻪ ۳از ۷ درس ﺳﯿﺴﺘﻢﻫﺎی ﻋﺎﻣﻞ
ﻫﻨﮕﺎم ﻓﺮاﺧﻮاﻧﯽ system callروﯾﻪی ﻣﺘﺪاول ﺑﻪ اﯾﻦ ﺷﮑﻞ اﺳﺖ ﮐﻪ اﺑﺘﺪا آرﮔﻮﻣﺎنﻫﺎی داده ﺷﺪه از ﭘﺸﺘﻪی ﮐﺎرﺑﺮ ﺑﻪ آ(
ﭘﺸﺘﻪی ﮐﺮﻧﻞ ﮐﭙﯽ ﻣﯽﺷﻮﻧﺪ ،ﺳﭙﺲ ﺻﺤﺖ آرﮔﻮﻣﺎنﻫﺎی داده ﺷﺪه ﭼﮏ ﻣﯽﺷﻮد .ﭼﺮا ﺗﺮﺗﯿﺐ اﯾﻦ دو ﻣﺮﺣﻠﻪ ﻧﻤﯽﺗﻮاﻧﺪ
ﺑﺮﻋﮑﺲ ﺑﺎﺷﺪ ،ﯾﻌﻨﯽ اﺑﺘﺪا ﺻﺤﺖ ﺑﺮرﺳﯽ ﺷﻮد و ﺳﭙﺲ ﺑﻪ ﭘﺸﺘﻪی ﮐﺮﻧﻞ ﮐﭙﯽﺷﻮﻧﺪ؟
آﯾﺎ راﻫﯽ ﺑﺪون اﺳﺘﻔﺎده از system callوﺟﻮد دارد ﮐﻪ ﮐﺎرﺑﺮ ﺑﺎ دﺳﺘﺮﺳﯽ ﺳﻄﺢ ﮐﺎرﺑﺮ ﮐﺪی ﺑﻨﻮﯾﺴﺪ و اﺟﺮا ﮐﻨﺪ ﮐﻪ ﺳﯿﺴﺘﻢ ب(
را وادار ﺑﻪ اﻧﺘﻘﺎل ﺑﻪ ﺣﺎﻟﺖ ﮐﺮﻧﻞ ﮐﻨﺪ؟ اﮔﺮ ﻧﺪارد ﭼﺮا و اﮔﺮ دارد ﻣﺜﺎل ﺑﺰﻧﯿﺪ.
در اﯾﻦ ﻗﺴﻤﺖ از درس ،ﺑﺎ ارﺗﺒﺎط ﻣﯿﺎن ﺑﺮﻧﺎﻣﻪﻫﺎ آﺷﻨﺎ ﺷﺪﯾﺪ .ﯾﮑﯽ از راهﻫﺎی ارﺗﺒﺎط ﻣﯿﺎن دو ﺑﺮﻧﺎﻣﻪ ﭘﺎﯾﭗ اﺳﺖ ،و ﯾﮏ راه ج(
ﻣﺘﺪاول دﯾﮕﺮ اﺳﺘﻔﺎده از ﯾﮏ ﻓﺎﯾﻞ اﺳﺖ ﮐﻪ دو ﺑﺮﻧﺎﻣﻪ اﻣﮑﺎن دﺳﺘﺮﺳﯽ ﺑﻪ آن را دارﻧﺪ .ﭼﺮا ،از ﻧﻈﺮ ﺳﺨﺖاﻓﺰاری ،راهﺣﻞ
اول ﺳﺮﻋﺖ زﯾﺎدﺗﺮی ﺧﻮاﻫﺪ داﺷﺖ؟
ﺑﺮای اﺟﺮای ﯾﮏ system callﻣﻌﻤﻮﻻ از ﯾﮏ ﺟﺪول اﺳﺘﻔﺎده ﻣﯽﺷﻮد ،ﺑﻪ اﯾﻦ ﺻﻮرت ﮐﻪ در ﺳﻄﺢ ﮐﺎرﺑﺮ ﺷﻤﺎرهی د(
ﻣﺘﻨﺎﻇﺮ ﺑﺎ syscallﻣﺪ ﻧﻈﺮ وارد ﯾﮏ رﺟﯿﺴﺘﺮ ﻣﯽﺷﻮد و ﺑﻌﺪ از اﻧﺘﻘﺎل ﺑﻪ ﺳﻄﺢ ﮐﺮﻧﻞ ،ﺑﺎ ﺑﺮرﺳﯽ ﺷﻤﺎرهی syscall،آدرس
دﺳﺘﻮراﻟﻌﻤﻞﻫﺎﯾﯽ ﮐﻪ ﺑﺎﯾﺪ اﺟﺮا ﺷﻮﻧﺪ ﺑﻪ دﺳﺖ ﻣﯽآﯾﺪ .ﭼﺮا اﯾﻦ روﻧﺪ اﻧﺘﺨﺎب ﺷﺪه اﺳﺖ و در ﺳﻄﺢ ﮐﺎرﺑﺮ ﻣﺴﺘﻘﯿﻤﺎ آدرس
دﺳﺘﻮراﻟﻌﻤﻞﻫﺎی ﻣﺪ ﻧﻈﺮ وارد رﺟﯿﺴﺘﺮ ﻧﻤﯽﺷﻮد؟
.۷ﻫﻤﺎﻧﻄﻮر ﮐﻪ ﻣﯿﺪاﻧﯿﺪ ﯾﮑﯽ از ﺑﺨﺶ ﻫﺎی اﺳﺎﺳﯽ ﻫﺮ ﺳﯿﺴﺘﻢ ﻋﺎﻣﻞ command interpreterآن اﺳﺖ .در اﯾﻦ ﺑﺎره ﺑﻪ ﺳﻮاﻻت
ذﯾﻞ ﭘﺎﺳﺦ دﻫﯿﺪ:
آ( ﻫﺪف از اﯾﺠﺎد و اﺳﺘﻔﺎده از اﯾﻦ ﺑﺨﺶ از ﺳﯿﺴﺘﻢ ﻋﺎﻣﻞ ﭼﯿﺴﺖ؟
ب( ﭼﻪ ﻣﺰﯾﺘﯽ در ﺟﺪاﺳﺎزی ﻣﻔﺴﺮ ﻓﺮﻣﺎن از ﻫﺴﺘﻪ ﺳﯿﺴﺘﻢ ﻋﺎﻣﻞ وﺟﻮد دارد؟
ج( از ﭼﻪ ﻓﺮاﺧﻮاﻧﯽ ﻫﺎی ﺳﯿﺴﺘﻤﯽ ﺑﺎﯾﺪ درد ﻣﻔﺴﺮ ﺳﯿﺴﺘﻢ ﻋﺎﻣﻞ ﺑﺮای اﺟﺮای دﺳﺘﻮرات اﺳﺘﻔﺎده ﮐﺮد؟ آﯾﺎ ﺑﺎ اﺳﺘﻔﺎده از
ﻓﺮاﺧﻮاﻧﯽﻫﺎی ﺳﯿﺴﺘﻤﯽ ﮐﻪ در اﺧﺘﯿﺎر ﺑﺮﻧﺎﻣﻪﻧﻮﯾﺲ ﻗﺮار ﻣﯽﮔﯿﺮد ،ﻣﯽﺗﻮان ﯾﮏ ﻣﻔﺴﺮ ﻓﺮﻣﺎن ﻧﻮﺷﺖ؟
ﺻﻔﺤﻪ ۴از ۷ درس ﺳﯿﺴﺘﻢﻫﺎی ﻋﺎﻣﻞ
ﺗﻤﺎرﯾﻦ ﻋﻤﻠﯽ
در اﯾﻦ ﺗﻤﺮﯾﻦ ﻗﺼﺪ دارﯾﻢ ﺗﺎ ﺗﺎ ﯾﮏ ﻓﺮاﺧﻮاﻧﯽ ﺳﯿﺴﺘﻤﯽ ﺑﻪ xv6اﺿﺎﻓﻪ ﮐﻨﯿﻢ ﮐﻪ ﻣﻨﺠﺮ ﺑﻪ درک ﺑﻬﺘﺮ از ﻧﺤﻮه ﮐﺎرﮐﺮد ﻓﺮاﺧﻮاﻧﯽﻫﺎی
ﺳﯿﺴﺘﻤﯽ و آﺷﻨﺎﯾﯽ ﺑﯿﺸﺘﺮ ﺑﺎ ﻫﺴﺘﻪ xv6ﺧﻮاﻫﺪ ﺷﺪ.
ﭘﯿﺶ از ﺷﺮوع ﺑﺮﻧﺎﻣﻪﻧﻮﯾﺴﯽ ﭘﯿﺸﻨﻬﺎد ﻣﯽﺷﻮد ﻓﺼﻞ دوم ﮐﺘﺎب xv6و ﺑﺨﺶﻫﺎی ۴.۳و ۴.۴ﻓﺼﻞ ﭼﻬﺎرم و ﻫﻤﭽﻨﯿﻦ ﻓﺎﯾﻞﻫﺎی زﯾﺮ را
ﻣﻄﺎﻟﻌﻪ ﮐﻨﯿﺪ:
• stubﻫﺎی ﻓﻀﺎی ﮐﺎرﺑﺮ ﮐﻪ ﻓﺮاﺧﻮاﻧﯽﻫﺎی ﺳﯿﺴﺘﻤﯽ را ﺑﻪ ﻫﺴﺘﻪ ﻣﻨﺘﻘﻞ ﻣﯽﮐﻨﻨﺪ در ﻓﺎﯾﻞ user/usys.Sﻗﺮار دارد ﮐﻪ ﺗﻮﺳﻂ
user/usys.plو ﭘﺲ از اﺟﺮای دﺳﺘﻮر makeﺳﺎﺧﺘﻪ ﻣﯽﺷﻮد .ﺗﻌﺮﯾﻔﺎت ﻧﯿﺰ در ﻓﺎﯾﻞ user/user.hﻗﺮار دارﻧﺪ.
• ﮐﺪﻫﺎی ﻓﻀﺎی ﻫﺴﺘﻪ ﮐﻪ ﯾﮏ ﻓﺮاﺧﻮاﻧﯽ را ﺑﻪ ﺗﺎﺑﻌﯽ ﮐﻪ آن را ﭘﯿﺎدهﺳﺎزی ﮐﺮده اﺳﺖ ﻫﺪاﯾﺖ ﻣﯽﮐﻨﺪ در ﻓﺎﯾﻞﻫﺎی
kernel/syscall.cو kernel/syscall.hﻗﺮار دارﻧﺪ.
• ﮐﺪﻫﺎی ﻣﺮﺗﺒﻂ ﺑﺎ ﭘﺮدازه ﻧﯿﺰ در ﻓﺎﯾﻞﻫﺎی kernel/proc.hو kernel/proc.cﻣﻮﺟﻮد اﺳﺖ.
.۱در ﺑﺴﯿﺎری از ﻣﻮارد اﺳﺘﻔﺎده از دﺳﺘﻮرات ﭼﺎپ ﺑﺮای دﯾﺒﺎگ ﮐﺮدن ﮐﺮﻧﻞ ﮐﺎﻓﯽ اﺳﺖ ،اﻣﺎ در ﺑﻌﻀﯽ ﻣﻮارد اﻣﮑﺎن ﺣﺮﮐﺖ ﮐﺮدن
ﺑﯿﻦ دﺳﺘﻮرات اﺳﻤﺒﻠﯽ ﯾﺎ ﺑﺮرﺳﯽ ﻣﺘﻐﯿﺮﻫﺎی درون ﭘﺸﺘﻪ ﻣﯽﺗﻮاﻧﺪ ﻓﺮاﯾﻨﺪ دﯾﺒﺎگ را ﺑﺮای ﻣﺎ آﺳﺎنﺗﺮ ﮐﻨﺪ.
ﺑﺮای اﯾﻨﮑﻪ ﺑﯿﺸﺘﺮ ﺑﺎ GDBآﺷﻨﺎ ﺷﻮﯾﺪ ،اﺑﺘﺪا دو ﭘﻨﺠﺮه ﺑﺎز ﮐﻨﯿﺪ .در ﭘﻨﺠﺮه اول دﺳﺘﻮر make qemu-gdbرا اﺟﺮا ﮐﻨﯿﺪ و gdb
را در ﭘﻨﺠﺮه دﯾﮕﺮ ﺑﺎز ﮐﻨﯿﺪ .زﻣﺎﻧﯽ ﮐﻪ دو ﭘﻨﺠﺮه را ﺑﺎز ﮐﺮدهاﯾﺪ ،دﺳﺘﻮر ﻣﻘﺎﺑﻞ را در ﭘﻨﺠﺮه gdbاﺟﺮا ﮐﻨﯿﺪ:
(gdb) b syscall
Breakpoint 1 at 0 x80002142 : file kernel / syscall .c, line 243.
(gdb) c
Continuing .
][ Switching to Thread 1.2
دﺳﺘﻮر layoutﭘﻨﺠﺮه را ﺑﻪ دو ﺗﮑﻪ ﺗﻘﺴﯿﻢ ﻣﯽﮐﻨﺪ ﮐﻪ ﻧﺸﺎن ﻣﯽدﻫﺪ gdbدر ﮐﺪام ﺧﻂ از ﺑﺮﻧﺎﻣﻪ ﻗﺮار دارد .دﺳﺘﻮر backtrace
ﺗﺎرﯾﺨﭽﻪ ﺗﻮاﺑﻊ ﺻﺪا زده ﺷﺪه در رﯾﺴﻤﺎن ﻓﻌﻠﯽ را ﻧﺸﺎن ﻣﯽدﻫﺪ .ﺑﺮای آﺷﻨﺎﯾﯽ ﺑﺎ دﺳﺘﻮرات gdbﻣﯽﺗﻮاﻧﯿﺪ ﺑﻪ اﯾﻦ ﻟﯿﻨﮏ ﻣﺮاﺟﻌﻪ
ﮐﻨﯿﺪ.
ﭘﺎﺳﺦ ﺳﻮاﻻت اﯾﻦ ﻗﺴﻤﺖ را در ﻗﺎﻟﺐ ﯾﮏ ﻓﺎﯾﻞ pdfﮐﻪ دارای ﺗﺼﺎوﯾﺮ اﻧﺠﺎم ﻣﺮاﺣﻞ ﺳﻮال اﺳﺖ ،ﺗﻬﯿﻪ ﻧﻤﺎﯾﯿﺪ و در ﺳﺎﻣﺎﻧﻪﻫﺎی
درس اﻓﺰار ﺷﺮﯾﻒ ) (CWو ﮐﻮﺋﺮا ﺑﺎرﮔﺬاری ﻧﻤﺎﯾﯿﺪ.
ﺳﻮال( ﺑﺎ ﺑﺮرﺳﯽ ﺧﺮوﺟﯽ دﺳﺘﻮر backtraceﺑﮕﻮﯾﯿﺪ ﮐﺪام ﺗﺎﺑﻊ syscallرا ﺻﺪا زده اﺳﺖ.
ﭼﻨﺪ ﺑﺎر nرا ﻓﺸﺎر دﻫﯿﺪ ﺗﺎ از ﺧﻂ ;)( proc *p = myprocﻋﺒﻮر ﮐﻨﯿﺪ .ﭘﺲ از ﻋﺒﻮر از اﯾﻦ دﺳﺘﻮر ،ﻋﺒﺎرت p /x *pرا
اﺟﺮا ﮐﻨﯿﺪ .اﯾﻦ دﺳﺘﻮر proc structﭘﺮدازه ﻓﻌﻠﯽ را در ﻫﮕﺰ ﺑﺮای ﻣﺎ ﭼﺎپ ﻣﯽﮐﻨﺪ )ﻓﺎﯾﻞ kernel/proc.hرا ﺑﺒﯿﻨﯿﺪ(.
ﺳﻮال( ﻣﻘﺪار p->trapframe->a7را ﺑﺪﺳﺖ آورﯾﺪ .اﯾﻦ ﻣﻘﺪار ﭼﻪ ﭼﯿﺰی را ﻧﻤﺎﯾﺶ ﻣﯽدﻫﺪ؟ )راﻫﻨﻤﺎﯾﯽ :ﻓﺎﯾﻞ
user/initcode.Sﮐﻪ اوﻟﯿﻦ ﺑﺮﻧﺎﻣﻪ ﮐﺎرﺑﺮ اﺟﺮا ﺷﺪه ﺗﻮﺳﻂ xv6اﺳﺖ را ﺑﺮرﺳﯽ ﮐﻨﯿﺪ(.
ﭘﺮدازه در ﺣﺎل اﺟﺮا در ﺣﺎﻟﺖ ﮐﺮﻧﻞ ﻣﯽﺑﺎﺷﺪ و ﻣﯽﺗﻮاﻧﯿﻢ ﺛﺒﺎتﻫﺎی privilegedﻣﺎﻧﻨﺪ sstatusرا ﭼﺎپ ﮐﻨﯿﻢ )ﺑﺮای ﺗﻮﺿﯿﺤﺎت
ﺑﯿﺸﺘﺮﻣﯽﺗﻮاﻧﯿﺪ ﺑﻪ اﯾﻦ ﻣﺴﺘﻨﺪ ﻣﺮاﺟﻌﻪ ﮐﻨﯿﺪ(:
ﺻﻔﺤﻪ ۵از ۷ درس ﺳﯿﺴﺘﻢﻫﺎی ﻋﺎﻣﻞ
(gdb) p /x $sstatus
hart 2 starting
hart 1 starting
scause 0 x000000000000000d
sepc =0 x000000008000215a stval =0 x0000000000000000
panic: kerneltrap
ﺗﺎﯾﯿﺪ ﮐﻨﯿﺪ ﮐﻪ دﺳﺘﻮر اﺳﻤﺒﻠﯽای ﮐﻪ دﭼﺎر ﺧﻄﺎ ﺷﺪه اﺳﺖ ﺑﺎ دﺳﺘﻮری ﮐﻪ در ﺑﺨﺶ ﻗﺒﻞ ﭘﯿﺪا ﮐﺮدهاﯾﺪ ﯾﮑﺴﺎن اﺳﺖ.
ﺳﻮال( ﭼﺮا ﮐﺮﻧﻞ ﮐﺮش ﻣﯽﮐﻨﺪ؟ آﯾﺎ آدرس 0در ﻓﻀﺎی آدرس ﮐﺮﻧﻞ ﻗﺮار دارد؟ آﯾﺎ ﺟﻮاب ﺷﻤﺎ ﺗﻮﺳﻂ ﻣﻘﺪار scauseدر ﺑﺨﺶﻫﺎی
ﻗﺒﻞ ﺗﺎﯾﯿﺪ ﻣﯽﺷﻮد؟ )ﺑﺮای ﺗﻮﺿﯿﺤﺎت ﺑﯿﺸﺘﺮ راﺟﻊ ﺑﻪ scauseﺑﻪ اﯾﻦ ﻣﺴﺘﻨﺪ ﻣﺮاﺟﻌﻪ ﮐﻨﯿﺪ(
دﻗﺖ ﮐﻨﯿﺪ scauseزﻣﺎﻧﯽ ﮐﻪ ﮐﺮﻧﻞ دﭼﺎر panicﺷﺪ ﺑﻪ ﺻﻮرت ﺧﻮدﮐﺎر ﭼﺎپ ﺷﺪ ،اﻣﺎ در ﺑﻌﻀﯽ از ﻣﻮاﻗﻊ ﺑﻪ اﻃﻼﻋﺎت ﺑﯿﺸﺘﺮی
ﺑﺮای ﭘﯿﺪا ﮐﺮدن دﻟﯿﻞ رخ دادن panicدارﯾﻢ .ﺑﻪ ﻋﻨﻮان ﻣﺜﺎل ﺑﺮای اﯾﻨﮑﻪ ﺑﺪاﻧﯿﻢ ﭼﻪ ﭘﺮدازه ﮐﺎرﺑﺮی زﻣﺎن panicدر ﺣﺎل اﺟﺮا
ﺑﻮد ﻣﯽﺗﻮاﻧﯿﻢ ﻧﺎم ﭘﺮدازه را ﺑﺎ دﺳﺘﻮر ﻣﻘﺎﺑﻞ ﭼﺎپ ﮐﻨﯿﻢ:
(gdb) p p->name
ﺳﻮال( ﻧﺎم ﭘﺮدازهای ﮐﻪ زﻣﺎن panicدر ﺣﺎل اﺟﺮا ﺑﻮد را ﺑﺪﺳﺖ آورﯾﺪ و آﯾﺪی ) (pidآن را ﺑﻨﻮﯾﺴﯿﺪ.
.۲در اﯾﻦ ﺳﻮال ،ﺷﻤﺎ ﯾﮏ ﻓﺮاﺧﻮاﻧﯽ ﺳﯿﺴﺘﻤﯽ ،ﺑﺮای ردﯾﺎﺑﯽ ) (tracingﻓﺮاﺧﻮاﻧﯽﻫﺎی ﺳﯿﺴﺘﻤﯽ ،ﺑﻪ ﮐﺮﻧﻞ اﺿﺎﻓﻪ ﺧﻮاﻫﯿﺪ ﮐﺮد.
ﺷﻤﺎ ﺑﺎﯾﺪ ﯾﮏ ﻓﺮاﺧﻮاﻧﯽ ﺳﯿﺴﺘﻤﯽ ﺟﺪﯾﺪ ﺑﻪ ﻧﺎم traceاﯾﺠﺎد ﮐﻨﯿﺪ ﮐﻪ ﻋﻤﻠﯿﺎت ﮐﻨﺘﺮل ردﯾﺎﺑﯽ ) (tracingرا اﻧﺠﺎم دﻫﺪ .اﯾﻦ
ﻓﺮاﺧﻮاﻧﯽ ﺳﯿﺴﺘﻤﯽ ﯾﮏ آرﮔﻮﻣﺎن ،ﮐﻪ ﺑﯿﺖ ﻫﺎی آن ﻣﺸﺨﺺ ﻣﯽ ﮐﻨﺪ ﮐﻪ ﮐﺪام ﻓﺮاﺧﻮاﻧﯽﻫﺎی ﺳﯿﺴﺘﻢ ﺑﺎﯾﺪ ردﯾﺎﺑﯽ ﺷﻮﻧﺪ ،را
ورودی ﻣﯽﮔﯿﺮد .ﺑﻪ ﻋﻨﻮان ﻣﺜﺎل ،ﺑﺮای ردﯾﺎﺑﯽ ﻓﺮاﺧﻮاﻧﯽ ﺳﯿﺴﺘﻤﯽ ،forkﺑﺮﻧﺎﻣﻪ ) trace(1 << SYS_forkرا ﻓﺮاﺧﻮاﻧﯽ
ﻣﯽﮐﻨﺪ ﮐﻪ در آن SYS_forkﯾﮏ ﺷﻤﺎره syscallاز kernel/syscall.hاﺳﺖ .ﺷﻤﺎ ﺑﺎﯾﺪ ﮐﺪﻫﺎی ﮐﺮﻧﻞ xv6را ﺗﻐﯿﯿﺮ
دﻫﯿﺪ ﺗﺎ وﻗﺘﯽ ﻫﺮ ﻓﺮاﺧﻮاﻧﯽ ﺳﯿﺴﺘﻤﯽ در ﺣﺎل ﺑﺎزﮔﺸﺖ اﺳﺖ ،اﮔﺮ ﺷﻤﺎره ﻓﺮاﺧﻮاﻧﯽ ﺳﯿﺴﺘﻤﯽ در maskﻣﺸﺨﺺ ﺷﺪه ﺑﺎﺷﺪ،
ﯾﮏ ﺧﻂ ﭼﺎپ ﺷﻮد .اﯾﻦ ﺧﻂ ﺑﺎﯾﺪ ﺷﺎﻣﻞ idﻓﺮآﯾﻨﺪ ،ﻧﺎم ﻓﺮاﺧﻮاﻧﯽ ﺳﯿﺴﺘﻤﯽ و ﻣﻘﺪار ﺑﺎزﮔﺸﺖ ﺑﺎﺷﺪ ،اﻣﺎ ﻧﯿﺎز ﻧﯿﺴﺖ آرﮔﻮﻣﺎن ﻫﺎی
ﺻﻔﺤﻪ ۶از ۷ درس ﺳﯿﺴﺘﻢﻫﺎی ﻋﺎﻣﻞ
ﻓﺮاﺧﻮاﻧﯽ ﺳﯿﺴﺘﻤﯽ را ﭼﺎپ ﮐﻨﯿﺪ .ﻓﺮاﺧﻮاﻧﯽ ﺳﯿﺴﺘﻤﯽ traceﺑﺎﯾﺪ ﻋﻤﻠﯿﺎت tracingرا ﺑﺮای ﭘﺮدازه ﻓﺮاﺧﻮاﻧﺪه ﺷﺪه و ﻫﻤﻪی
ﭘﺮدازهﻫﺎی ﻓﺮزﻧﺪ ﮐﻪ ﺗﻮﺳﻂ forkاﯾﺠﺎد ﺷﺪهاﻧﺪ اﻧﺠﺎم دﻫﺪ ،اﻣﺎ ﻧﺒﺎﯾﺪ ﺑﺮ روﻧﺪ اﺟﺮای آنﻫﺎ اﺛﺮی ﺑﮕﺬارد.
ﺧﺮوﺟﯽ ﮐﺪ ﺷﻤﺎ ،ﺑﺎﯾﺪ ﻣﺸﺎﺑﻪ ﺧﺮوﺟﯽ زﯾﺮ ﺑﺎﺷﺪ:
$ trace 32 grep hello README
3: syscall read -> 1023
3: syscall read -> 966
3: syscall read -> 70
3: syscall read -> 0
$
$ trace 2147483647 grep hello README
4: syscall trace -> 0
4: syscall exec -> 3
4: syscall open -> 3
4: syscall read -> 1023
4: syscall read -> 966
4: syscall read -> 70
4: syscall read -> 0
4: syscall close -> 0
$
$ grep hello README
$
$ trace 2 usertests forkforkfork
usertests starting
test forkforkfork : 407: syscall fork -> 408
408: syscall fork -> 409
409: syscall fork -> 410
410: syscall fork -> 411
409: syscall fork -> 412
410: syscall fork -> 413
409: syscall fork -> 414
411: syscall fork -> 415
...
$
در ﻧﻤﻮﻧﻪ اول trace ،ﻓﻘﻂ ﻓﺮاﺧﻮاﻧﯽ ﺳﯿﺴﺘﻤﯽ readرا ﺑﺎ اﺳﺘﻔﺎده از grepردﯾﺎﺑﯽ ﻣﯽ ﮐﻨﺪ ﮐﻪ در آن ۳۲ﻫﻤﺎن SYS_read
ﻣﯽﺑﺎﺷﺪ .در ﻧﻤﻮﻧﻪ دوم trace ،در ﺣﺎﻟﯽ ﮐﻪ ﺗﻤﺎم ﻓﺮاﺧﻮاﻧﯽﻫﺎی ﺳﯿﺴﺘﻢ را ردﯾﺎﺑﯽ ﻣﯽ ﮐﻨﺪ grep ،را ﻧﯿﺰ اﺟﺮا ﻣﯽ ﮐﻨﺪ .در
اﯾﻦ ﺣﺎﻟﺖ ﻋﺪد 2147483647ﻣﻌﺎدل ﺗﻤﺎم ۳۱ﺑﯿﺖ ﭘﺎﯾﯿﻦ اﺳﺖ )ﯾﻌﻨﯽ ﺗﻤﺎﻣﯽ ﻓﺮاﺧﻮاﻧﯽﻫﺎی ﺳﯿﺴﺘﻤﯽ ﻣﻮﺟﻮد در ﻓﺎﯾﻞ
.(kernel/syscall.hدر ﻧﻤﻮﻧﻪ ﺳﻮم ،ﻫﯿﭻ ﺑﺮﻧﺎﻣﻪای ردﮔﯿﺮی ﻧﺸﺪه اﺳﺖ ،ﺑﻨﺎﺑﺮاﯾﻦ ﻫﯿﭻ ﺧﺮوﺟﯽای ﭼﺎپ ﻧﻤﯽﺷﻮد.
در ﻧﻤﻮﻧﻪ ﭼﻬﺎرم ،ﮐﺪ ﺷﻤﺎ ﺑﺎﯾﺪ ﻓﺮاﺧﻮاﻧﯽﻫﺎی SYS_forkﺗﻤﺎم ﭘﺮدازهﻫﺎی اﯾﺠﺎد ﺷﺪه ﺗﻮﺳﻂ ﺑﺮﻧﺎﻣﻪی forkforkforkدر
usertestsرا ردﮔﯿﺮی ﮐﻨﺪ.
ﭼﻨﺪ راﻫﻨﻤﺎﯾﯽ در ﻣﻮرد اﻧﺠﺎم ﺳﻮال:
• اﺑﺘﺪا $U/_traceرا ﺑﻪ UPROGSدر Makefileاﺿﺎﻓﻪ ﮐﻨﯿﺪ.
• دﺳﺘﻮر make qemuرا اﺟﺮا ﮐﻨﯿﺪ .در اداﻣﻪ ﺧﻮاﻫﯿﺪ دﯾﺪ ﮐﻪ ﮐﺎﻣﭙﺎﯾﻠﺮ ﻧﻤﯽ ﺗﻮاﻧﺪ user/trace.cرا ﮐﺎﻣﭙﺎﯾﻞ ﮐﻨﺪ ،زﯾﺮا
stubﻫﺎی ﻓﻀﺎی ﮐﺎرﺑﺮ ﺑﺮای ﻓﺮاﺧﻮاﻧﯽ ﺳﺎﻣﺎﻧﻪ ﻫﻨﻮز وﺟﻮد ﻧﺪارد :ﯾﮏ prototypeﺑﺮای ﻓﺮاﺧﻮاﻧﯽ ﺳﺎﻣﺎﻧﻪ ﺑﻪ user/user.h
اﺿﺎﻓﻪ ﮐﻨﯿﺪ ،ﯾﮏ stubﺑﻪ user/usys.plو ﯾﮏ ﺷﻤﺎره syscallﺑﻪ Makefile .kernel/syscall.hاﺳﮑﺮﯾﭙﺖ
perl user/usys.plرا ﻓﺮاﺧﻮاﻧﺪه و stub ،user/usys.Sﻫﺎی ﻓﺮاﺧﻮاﻧﯽ ﺳﺎﻣﺎﻧﻪ واﻗﻌﯽ را ﺗﻮﻟﯿﺪ ﻣﯽﮐﻨﺪ ،ﮐﻪ
از دﺳﺘﻮر ecallدر اﺳﻤﺒﻠﯽ RISC-Vﺑﺮای اﻧﺘﻘﺎل ﺑﻪ kernelاﺳﺘﻔﺎده ﻣﯽ ﮐﻨﺪ .وﻗﺘﯽ ﺷﻤﺎ ﻣﺸﮑﻼت ﮐﺎﻣﭙﺎﯾﻞ را ﺣﻞ
ﮐﺮدﯾﺪ trace 32 grep hello README ،را اﺟﺮا ﮐﻨﯿﺪ؛ اﯾﻦ دﺳﺘﻮر ﺑﺎ ﺷﮑﺴﺖ ﻣﻮاﺟﻪ ﺧﻮاﻫﺪ ﺷﺪ زﯾﺮا ﺷﻤﺎ ﻫﻨﻮز
ﻓﺮاﺧﻮاﻧﯽ ﺳﺎﻣﺎﻧﻪ را در kernelﭘﯿﺎده ﺳﺎزی ﻧﮑﺮده اﯾﺪ.
• در اداﻣﻪ ﺗﺎﺑﻊ )( sys_traceرا در kernel/sysproc.cاﺿﺎﻓﻪ ﮐﻨﯿﺪ.
ﺻﻔﺤﻪ ۷از ۷ درس ﺳﯿﺴﺘﻢﻫﺎی ﻋﺎﻣﻞ