Օպերացիոն համակարգեր. երեք հեշտ կտոր: Մաս 2. Աբստրակցիա. Գործընթաց (թարգմանություն)
Օպերացիոն համակարգերի ներածություն
Հե՜յ Հաբր։ Ձեր ուշադրությանն եմ ներկայացնում իմ կարծիքով մեկ հետաքրքիր գրականության՝ OSTEP-ի հոդված-թարգմանությունների շարքը։ Այս նյութը բավականին խորը քննարկում է unix-ի նման օպերացիոն համակարգերի աշխատանքը, այն է՝ պրոցեսների, տարբեր ժամանակացույցերի, հիշողության և այլ նմանատիպ բաղադրիչների հետ աշխատանքը, որոնք կազմում են ժամանակակից ՕՀ: Բոլոր նյութերի բնօրինակը կարող եք տեսնել այստեղ այստեղ. Խնդրում եմ նկատի ունենալ, որ թարգմանությունը կատարվել է ոչ պրոֆեսիոնալ (բավականին ազատ), բայց հուսով եմ պահպանել եմ ընդհանուր իմաստը։
Այս թեմայով լաբորատոր աշխատանք կարելի է գտնել այստեղ.
Եկեք նայենք ամենահիմնական վերացականությանը, որը ՕՀ-ն տրամադրում է օգտատերերին՝ գործընթացին: Գործընթացի սահմանումը բավականին պարզ է գործարկող ծրագիր. Ծրագիրն ինքնին անկենդան բան է, որը գտնվում է սկավառակի վրա. դա հրահանգների մի շարք է և, հնարավոր է, որոշ ստատիկ տվյալներ, որոնք սպասում են գործարկմանը: Դա ՕՀ-ն է, որը վերցնում է այդ բայթերը և գործարկում՝ ծրագիրը վերածելով օգտակար բանի:
Ամենից հաճախ օգտատերերը ցանկանում են միաժամանակ գործարկել մեկից ավելի ծրագրեր, օրինակ՝ ձեր նոութբուքում կարող եք գործարկել բրաուզեր, խաղ, մեդիա նվագարկիչ, տեքստային խմբագրիչ և այլն: Փաստորեն, տիպիկ համակարգը կարող է միաժամանակ գործարկել տասնյակ կամ հարյուրավոր գործընթացներ: Այս փաստը հեշտացնում է համակարգի օգտագործումը, դուք երբեք չպետք է անհանգստանաք այն մասին, թե արդյոք պրոցեսորն անվճար է, դուք պարզապես գործարկում եք ծրագրեր:
Սա խնդիր է առաջացնում. ինչպե՞ս ապահովել բազմաթիվ պրոցեսորների պատրանքը: Ինչպե՞ս կարող է ՕՀ-ն ստեղծել գրեթե անսահման թվով պրոցեսորների պատրանք, նույնիսկ եթե դուք ունեք միայն մեկ ֆիզիկական պրոցեսոր:
ՕՀ-ն ստեղծում է այս պատրանքը պրոցեսորի վիրտուալացման միջոցով: Մեկ պրոցես սկսելով, հետո դադարեցնելով այն, սկսելով մեկ այլ գործընթաց և այլն, ՕՀ-ն կարող է պահպանել պատրանքը, որ կան բազմաթիվ վիրտուալ պրոցեսորներ, մինչդեռ իրականում կլինեն մեկ կամ մի քանի ֆիզիկական պրոցեսորներ: Այս տեխնիկան կոչվում է CPU-ի ռեսուրսների բաժանում ըստ ժամանակի. Այս տեխնիկան թույլ է տալիս օգտվողներին գործարկել այնքան միաժամանակյա գործընթացներ, որքան ցանկանում են: Այս լուծման արժեքը կատարողական է. քանի որ եթե պրոցեսորը կիսվում է մի քանի պրոցեսներով, յուրաքանչյուր գործընթաց ավելի դանդաղ կմշակվի:
CPU-ի վիրտուալացումն իրականացնելու և հատկապես այն լավ կատարելու համար ՕՀ-ին անհրաժեշտ է ինչպես ցածր, այնպես էլ բարձր մակարդակի աջակցություն: Ցածր մակարդակի աջակցությունը կոչվում է մեխանիզմներ ցածր մակարդակի մեթոդներ կամ արձանագրություններ են, որոնք իրականացնում են ֆունկցիոնալության պահանջվող մասը: Նման ֆունկցիոնալության օրինակ է համատեքստի փոխարկումը, որը ՕՀ-ին հնարավորություն է տալիս դադարեցնել մի ծրագիր և գործարկել մեկ այլ ծրագիր պրոցեսորի վրա: Այս ժամանակային բաժանումն իրականացվում է բոլոր ժամանակակից օպերացիոն համակարգերում։
Այս մեխանիզմների վերևում կա որոշակի տրամաբանություն, որը ներկառուցված է ՕՀ-ում՝ «քաղաքականության» տեսքով: Քաղաքականություն օպերացիոն համակարգի համար որոշումների կայացման որոշակի ալգորիթմ է: Նման քաղաքականությունները, օրինակ, որոշում են, թե որ ծրագիրն առաջինը պետք է գործարկվի (հրամանների ցանկից): Այսպիսով, օրինակ, այս խնդիրը կլուծվի քաղաքականությամբ, որը կոչվում է ժամանակացույց (պլանավորման քաղաքականություն) և լուծում ընտրելիս այն կառաջնորդվի այնպիսի տվյալներով, ինչպիսիք են՝ գործարկման պատմությունը (որ ծրագիրն է ամենաերկար գործարկվել վերջին րոպեներին), ինչ բեռ է կրում այս գործընթացը (ինչ տեսակի ծրագրեր են գործարկվել), կատարողականի չափումներ (արդյոք համակարգը օպտիմիզացված է ինտերակտիվ փոխազդեցության կամ թողունակության համար) և այլն:
Աբստրակցիա՝ գործընթաց
Գործող ծրագրի աբստրակցիան, որն իրականացվում է օպերացիոն համակարգի կողմից, այն է, ինչ մենք անվանում ենք պրոցես. Ինչպես նշվեց ավելի վաղ, գործընթացը պարզապես գործող ծրագիր է, ցանկացած ակնթարթային ժամանակահատվածում: Ծրագիր, որի միջոցով մենք կարող ենք ամփոփ տեղեկատվություն ստանալ տարբեր համակարգի ռեսուրսներից, որոնց այս ծրագիրը հասանելի է կամ ազդում է դրա կատարման ընթացքում:
Գործընթացի բաղադրիչները հասկանալու համար դուք պետք է հասկանաք համակարգի վիճակները՝ ինչ կարող է ծրագիրը կարդալ կամ փոխել իր աշխատանքի ընթացքում: Ցանկացած ժամանակ դուք պետք է հասկանաք, թե համակարգի որ տարրերն են կարևոր ծրագրի իրականացման համար:
Համակարգի ակնհայտ տարրերից մեկն այն է, որ գործընթացը ներառում է փամաթ. Հրահանգները գտնվում են հիշողության մեջ: Այն տվյալները, որոնք ծրագիրը կարդում կամ գրում է, նույնպես գտնվում են հիշողության մեջ: Այսպիսով, հիշողությունը, որին կարող է հասցեագրել պրոցեսը (կոչվում է հասցեների տարածություն) գործընթացի մի մասն է:
Համակարգային վիճակի մաս են կազմում նաև ռեգիստրները։ Շատ հրահանգներ ուղղված են ռեգիստրների արժեքը փոխելուն կամ դրանց արժեքը կարդալուն, և այդպիսով ռեգիստրները նույնպես դառնում են գործընթացի գործունեության կարևոր մասը:
Հարկ է նշել, որ մեքենայի վիճակը նույնպես ձևավորվում է որոշ հատուկ ռեգիստրներից։ Օրինակ, IP - հրահանգների ցուցիչ — ցուցիչ այն հրահանգին, որը ծրագիրը ներկայումս կատարում է: Կա նաեւ կույտի ցուցիչ և դրա հետ կապված շրջանակի ցուցիչ, որոնք օգտագործվում են կառավարելու համար՝ ֆունկցիայի պարամետրերը, տեղական փոփոխականները և վերադարձի հասցեները։
Վերջապես, ծրագրերը հաճախ մուտք են գործում ROM (միայն կարդալու հիշողություն): Այս «I/O» (մուտքային/ելք) տեղեկատվությունը պետք է ներառի գործընթացի ընթացքում բացված ֆայլերի ցանկը:
Գործընթացի API
Որպեսզի լավացնենք, թե ինչպես է աշխատում գործընթացը, եկեք ուսումնասիրենք համակարգային զանգերի օրինակներ, որոնք պետք է ներառվեն ցանկացած օպերացիոն համակարգի ինտերֆեյսում: Այս API-ները հասանելի են այս կամ այն ձևով ցանկացած ՕՀ-ում:
● Ստեղծել (ստեղծում). ՕՀ-ն պետք է ներառի որևէ մեթոդ, որը թույլ է տալիս ստեղծել նոր գործընթացներ: Երբ դուք հրաման եք մուտքագրում տերմինալ կամ գործարկում եք ծրագիր՝ կրկնակի սեղմելով պատկերակի վրա, զանգ է ուղարկվում ՕՀ՝ նոր գործընթաց ստեղծելու և այնուհետև գործարկելու նշված ծրագիրը:
● ՀեռացումՔանի որ գոյություն ունի գործընթաց ստեղծելու ինտերֆեյս, ՕՀ-ն պետք է նաև հնարավորություն տա ստիպել հեռացնել գործընթացը: Ծրագրերի մեծամասնությունը բնականաբար կսկսվի և կավարտվի ինքնուրույն, երբ դրանք գործարկվեն: Հակառակ դեպքում օգտատերը կցանկանար, որ կարողանար սպանել նրանց, և այդպիսով գործընթացը դադարեցնելու ինտերֆեյսը օգտակար կլիներ:
● Սպասեք: (սպասում). Երբեմն օգտակար է սպասել գործընթացի ավարտին, այնպես որ տրամադրվում են որոշ միջերեսներ, որոնք ապահովում են սպասելու հնարավորությունը:
● Տարբեր վերահսկում (տարբեր հսկողություն). Բացի սպանելուց և գործընթացին սպասելուց, կան նաև հսկողության այլ տարբեր մեթոդներ: Օրինակ, օպերացիոն համակարգերից շատերը հնարավորություն են տալիս սառեցնել գործընթացը (դադարեցնել դրա կատարումը որոշակի ժամկետով), այնուհետև վերսկսել այն (շարունակել կատարումը)
● Ստատուս (state). Կան տարբեր ինտերֆեյսներ գործընթացի կարգավիճակի մասին որոշ տեղեկություններ ստանալու համար, օրինակ, թե որքան ժամանակ է այն աշխատում կամ ինչ վիճակում է այն ներկայումս:
Գործընթացի ստեղծում. Մանրամասներ
Հետաքրքիր բաներից մեկն այն է, թե կոնկրետ ինչպես են ծրագրերը վերածվում գործընթացների։ Հատկապես, թե ինչպես է ՕՀ-ն վերցնում և գործարկում ծրագիրը: Ինչպես է կոնկրետ ստեղծվում գործընթացը:
Առաջին հերթին, ՕՀ-ն պետք է բեռնի ծրագրի կոդը և ստատիկ տվյալները հիշողության մեջ (գործընթացի հասցեների տարածության մեջ): Ծրագրերը սովորաբար տեղակայված են սկավառակի կամ կոշտ վիճակի սկավառակի վրա՝ գործարկվող ձևաչափով: Այսպիսով, ծրագրի և ստատիկ տվյալների հիշողության մեջ բեռնելու գործընթացը պահանջում է, որ ՕՀ-ն կարողանա կարդալ այդ բայթերը սկավառակից և տեղադրել դրանք ինչ-որ տեղ հիշողության մեջ:
Վաղ օպերացիոն համակարգերում բեռնման գործընթացը կատարվում էր եռանդով, ինչը նշանակում է, որ ամբողջ կոդը բեռնվում էր հիշողության մեջ նախքան ծրագրի գործարկումը: Ժամանակակից օպերացիոն համակարգերը դա անում են ծուլորեն, այսինքն՝ բեռնում են կոդ կամ տվյալներ միայն այն դեպքում, երբ ծրագիրը պահանջում է դրանք իր կատարման ընթացքում։
Երբ կոդը և ստատիկ տվյալները բեռնվեն ՕՀ-ի հիշողության մեջ, կան ևս մի քանի բան, որոնք պետք է արվեն նախքան գործընթացը գործարկվի: Հիշողության որոշակի քանակ պետք է հատկացվի կույտին: Ծրագրերն օգտագործում են կույտը տեղական փոփոխականների, ֆունկցիայի պարամետրերի և վերադարձի հասցեների համար. ՕՀ-ն հատկացնում է այս հիշողությունը և տալիս այն գործընթացին: Ստեկը կարող է նաև հատկացվել որոշ արգումենտներով, մասնավորապես այն լրացնում է main() ֆունկցիայի պարամետրերը, օրինակ՝ argc և argv զանգվածով:
Օպերացիոն համակարգը կարող է նաև որոշակի հիշողություն հատկացնել ծրագրի կույտին: Կույտը օգտագործվում է ծրագրերի կողմից՝ հստակորեն պահանջելու դինամիկ բաշխված տվյալներ. Ծրագրերը պահանջում են այս տարածքը՝ զանգահարելով ֆունկցիան malloc () և հստակորեն ջնջում է՝ ֆունկցիան կանչելով անվճար(). Կույտը անհրաժեշտ է տվյալների կառուցվածքների համար, ինչպիսիք են կապված թերթերը, հեշ աղյուսակները, ծառերը և այլն: Սկզբում փոքր քանակությամբ հիշողություն հատկացվում է կույտին, բայց ժամանակի ընթացքում, երբ ծրագիրը գործարկվում է, կույտը կարող է ավելի շատ հիշողություն պահանջել գրադարանի API-ի միջոցով, զանգահարելով malloc(): Օպերացիոն համակարգը ներգրավված է ավելի շատ հիշողություն հատկացնելու գործընթացում՝ օգնելու բավարարել այդ զանգերը:
Օպերացիոն համակարգը նաև կկատարի սկզբնավորման առաջադրանքներ, մասնավորապես՝ I/O-ի հետ կապված: Օրինակ, UNIX համակարգերում յուրաքանչյուր գործընթաց լռելյայն ունի 3 բաց ֆայլի նկարագրիչներ՝ ստանդարտ մուտքագրման, ելքի և սխալի համար: Այս բռնակները թույլ են տալիս ծրագրերին կարդալ մուտքը տերմինալից, ինչպես նաև ցուցադրել տեղեկատվությունը էկրանին:
Այսպիսով, բեռնելով կոդը և ստատիկ տվյալները հիշողության մեջ, ստեղծելով և սկզբնավորելով կույտը և կատարելով այլ աշխատանքներ՝ կապված I/O առաջադրանքների կատարման հետ, ՕՀ-ն նախապատրաստում է փուլը գործընթացի իրականացման համար: Վերջապես, մնում է մեկ վերջին առաջադրանք՝ ծրագիրը գործարկել իր մուտքի կետով, որը կոչվում է main() ֆունկցիա: Կատարելով main() ֆունկցիան՝ ՕՀ-ն փոխանցում է պրոցեսորի կառավարումը նոր ստեղծված գործընթացին, այդպիսով ծրագիրը սկսում է իրագործվել։
Գործընթացի վիճակը
Այժմ, երբ մենք որոշակիորեն հասկանում ենք, թե ինչ է գործընթացը և ինչպես է այն ստեղծվում, եկեք թվարկենք գործընթացի այն պետությունները, որոնցում այն կարող է լինել: Իր ամենապարզ ձևով գործընթացը կարող է լինել հետևյալ վիճակներից մեկում.
● Վազում. Աշխատելիս պրոցեսն աշխատում է պրոցեսորի վրա: Սա նշանակում է, որ հրահանգները կատարվում են։
● Պատրաստ. Պատրաստ վիճակում պրոցեսը պատրաստ է գործարկման, բայց ինչ-ինչ պատճառներով ՕՀ-ն այն չի կատարում նշված ժամին:
● Արգելափակված. Արգելափակված վիճակում պրոցեսը կատարում է որոշ գործողություններ, որոնք թույլ չեն տալիս այն պատրաստ լինել գործարկելու մինչև որևէ իրադարձություն տեղի ունենալ: Տարածված օրինակներից մեկն այն է, երբ գործընթացը սկսում է IO գործողություն, այն արգելափակվում է, որպեսզի որևէ այլ գործընթաց կարողանա օգտագործել պրոցեսորը:
Դուք կարող եք պատկերացնել այս վիճակները գրաֆիկի տեսքով։ Ինչպես տեսնում ենք նկարում, OS-ի հայեցողությամբ գործընթացի վիճակը կարող է փոխվել RUNNING-ի և READY-ի միջև: Երբ գործընթացի վիճակը փոխվում է ՊԱՏՐԱՍՏ-ից մինչև RUNNING, դա նշանակում է, որ գործընթացը պլանավորված է: Հակառակ ուղղությամբ - հեռացվել է դասավորությունից: Այն պահին, երբ պրոցեսը դառնում է արգելափակված, օրինակ, ես նախաձեռնում եմ IO գործողություն, ՕՀ-ն այն կպահի այս վիճակում, մինչև տեղի ունենա որևէ իրադարձություն, օրինակ՝ IO-ի ավարտը: այս պահին անցում ՊԱՏՐԱՍՏ վիճակին և, հնարավոր է, անմիջապես գործարկման վիճակին, եթե ՕՀ-ն այդպես որոշի:
Դիտարկենք մի օրինակ, թե ինչպես են երկու գործընթացներ անցնում այս վիճակների միջով: Սկսենք, եկեք պատկերացնենք, որ երկու գործընթացներն էլ աշխատում են, և յուրաքանչյուրն օգտագործում է միայն պրոցեսորը: Այս դեպքում նրանց նահանգներն այսպիսի տեսք կունենան.
Հետևյալ օրինակում առաջին պրոցեսը, որոշ ժամանակ աշխատելուց հետո, պահանջում է IO և մտնում է BLOCKED վիճակ՝ թույլ տալով գործարկել մեկ այլ գործընթաց (Նկար 1.4): ՕՀ-ն տեսնում է, որ 0 պրոցեսը չի օգտագործում պրոցեսորը և սկսում է գործընթացը 1: Մինչ պրոցեսը 1-ն աշխատում է, IO-ն ավարտված է, և 0 գործընթացի կարգավիճակը փոխվում է READY: Վերջապես, գործընթաց 1-ն ավարտվել է, և ավարտվելուց հետո 0 գործընթացը սկսում, կատարում և ավարտում է իր աշխատանքը:
Տվյալների կառուցվածքը
ՕՀ-ն ինքնին ծրագիր է, և ինչպես ցանկացած այլ ծրագիր, այն ունի որոշ հիմնական տվյալների կառուցվածքներ, որոնք հետևում են տարբեր համապատասխան տեղեկատվությանը: Յուրաքանչյուր գործընթացի վիճակը հետևելու համար ՕՀ-ն կաջակցի որոշներին գործընթացների ցանկը ՊԱՏՐԱՍՏ վիճակում գտնվող բոլոր գործընթացների համար և որոշ լրացուցիչ տեղեկություններ՝ ներկայումս գործող գործընթացներին հետևելու համար: Նաև ՕՀ-ն պետք է վերահսկի արգելափակված գործընթացները: IO-ի ավարտից հետո ՕՀ-ն պետք է արթնացնի պահանջվող գործընթացը և դրի այն գործարկման պատրաստ վիճակում:
Օրինակ, ՕՀ-ն պետք է պահպանի պրոցեսորների ռեգիստրների վիճակը: Գործընթացի դադարեցման պահին ռեգիստրների վիճակը պահվում է գործընթացի հասցեային տարածքում, և այն պահին, երբ դրա աշխատանքը շարունակվում է, ռեգիստրների արժեքները վերականգնվում են և այդպիսով շարունակվում է այս գործընթացի կատարումը:
Բացի պատրաստ, արգելափակված, գործող պետություններից, կան մի քանի այլ նահանգներ: Երբեմն, ստեղծման պահին, գործընթացը կարող է լինել INIT վիճակում: Վերջապես, գործընթացը կարող է տեղադրվել ԵԶՐԱՓԱԿԻՉ վիճակում, երբ այն արդեն ավարտված է, բայց դրա տեղեկատվությունը դեռ չի մաքրվել: UNIX համակարգերում այս վիճակը կոչվում է զոմբիացման գործընթացը. Այս վիճակը օգտակար է այն դեպքերի համար, երբ ծնողական գործընթացը ցանկանում է իմանալ երեխայի վերադարձի կոդը, օրինակ՝ սովորաբար 0-ն ազդանշան է տալիս հաջողության, իսկ 1-ը՝ սխալի, բայց ծրագրավորողները կարող են թողարկել լրացուցիչ ելքային կոդեր՝ տարբեր խնդիրների ազդանշան տալու համար: Երբ մայր գործընթացն ավարտվում է, այն կատարում է վերջնական համակարգային զանգ, ինչպիսին է սպասել()՝ սպասելու երեխայի գործընթացի ավարտին և ՕՀ-ին ազդանշան տալու, որ այն կարող է ջնջել ավարտված գործընթացի հետ կապված ցանկացած տվյալ:
Դասախոսության հիմնական կետերը.
● պրոցես — ՕՀ-ում գործող ծրագրի հիմնական աբստրակցիան: Ցանկացած ժամանակ պրոցեսը կարող է նկարագրվել իր վիճակով. հիշողության պարունակությունը իր հասցեային տարածքում, պրոցեսորի ռեգիստրների պարունակությունը, ներառյալ հրահանգների ցուցիչը և ստեկի ցուցիչը, և IO տեղեկատվությունը, օրինակ՝ բաց ֆայլերը, որոնք կարդացվում կամ գրվում են:
● Գործընթացի API բաղկացած է զանգերից, որոնք ծրագրերը կարող են կատարել գործընթացներին: Սովորաբար դրանք ստեղծում, ջնջում կամ այլ զանգեր են:
● Գործընթացը գտնվում է բազմաթիվ վիճակներից մեկում, ներառյալ՝ գործարկվող, պատրաստ, արգելափակված: Տարբեր իրադարձություններ, ինչպիսիք են պլանավորումը, պլանավորման բացառությունները կամ սպասումները, կարող են փոխել գործընթացի վիճակը մեկից մյուսը:
● Գործընթացների ցուցակ պարունակում է տեղեկատվություն համակարգի բոլոր գործընթացների մասին: Դրանում յուրաքանչյուր մուտք կոչվում է գործընթացի կառավարման բլոկ, որն իրականում կառույց է, որը պարունակում է բոլոր անհրաժեշտ տեղեկությունները կոնկրետ գործընթացի մասին: