Օպերացիոն համակարգերի ներածություն
Հե՜յ Հաբր։ Ձեր ուշադրությանն եմ ներկայացնում իմ կարծիքով մեկ հետաքրքիր գրականության՝ OSTEP-ի հոդված-թարգմանությունների շարքը։ Այս նյութը բավականին խորը քննարկում է unix-ի նման օպերացիոն համակարգերի աշխատանքը, այն է՝ պրոցեսների, տարբեր ժամանակացույցերի, հիշողության և այլ նմանատիպ բաղադրիչների հետ աշխատանքը, որոնք կազմում են ժամանակակից ՕՀ: Բոլոր նյութերի բնօրինակը կարող եք տեսնել այստեղ
Այս թեմայով լաբորատոր աշխատանք կարելի է գտնել այստեղ.
Այլ մասեր.
Կարող եք նաև դիտել իմ ալիքը
Ահազանգ Այս դասախոսության համար կա լաբորատորիա: Նայել
Գործընթացի API
Դիտարկենք UNIX համակարգում գործընթաց ստեղծելու օրինակ: Դա տեղի է ունենում երկու համակարգային զանգերի միջոցով պատառաքաղ () и exec ().
Call fork ()
Դիտարկենք մի ծրագիր, որը կատարում է fork() զանգ: Դրա կատարման արդյունքը կլինի հետևյալը.
Առաջին հերթին մենք մուտքագրում ենք main() ֆունկցիան և տպում տողը էկրանին։ Տողը պարունակում է գործընթացի նույնացուցիչը, որը բնօրինակում կոչվում է PID կամ գործընթացի նույնացուցիչը: Այս նույնացուցիչն օգտագործվում է UNIX-ում՝ գործընթացին անդրադառնալու համար: Հաջորդ հրամանը կկանչի fork(). Այս պահին ստեղծվում է գործընթացի գրեթե ճշգրիտ պատճենը: ՕՀ-ի համար, թվում է, թե համակարգում գործում է նույն ծրագրի 2 օրինակ, որն իր հերթին դուրս կգա fork() ֆունկցիայից: Նորաստեղծ երեխա պրոցեսը (կապված այն ստեղծած ծնող գործընթացի հետ) այլևս չի կատարվի՝ սկսած main() ֆունկցիայից։ Պետք է հիշել, որ երեխայի պրոցեսը ծնող գործընթացի ճշգրիտ պատճենը չէ, մասնավորապես, այն ունի իր հասցեների տարածքը, սեփական ռեգիստրները, գործարկվող հրահանգների իր ցուցիչը և այլն: Այսպիսով, fork() ֆունկցիայի կանչողին վերադարձված արժեքը տարբեր կլինի։ Մասնավորապես, մայր պրոցեսը որպես վերադարձ կստանա երեխայի պրոցեսի PID արժեքը, իսկ երեխան կստանա 0-ի արժեք: Օգտագործելով այս վերադարձի կոդերը, դուք կարող եք այնուհետև առանձնացնել գործընթացները և ստիպել նրանցից յուրաքանչյուրին կատարել իր աշխատանքը: . Այնուամենայնիվ, այս ծրագրի կատարումը խստորեն սահմանված չէ: 2 պրոցեսների բաժանվելուց հետո ՕՀ-ն սկսում է վերահսկել դրանք, ինչպես նաև պլանավորել նրանց աշխատանքը։ Եթե գործարկվի մեկ միջուկային պրոցեսորի վրա, պրոցեսներից մեկը, այս դեպքում ծնողը, կշարունակի աշխատել, և այնուհետև երեխայի գործընթացը կստանա վերահսկողություն: Վերագործարկման ժամանակ իրավիճակը կարող է տարբեր լինել:
Զանգի սպասել ()
Դիտարկենք հետևյալ ծրագիրը. Այս ծրագրում զանգի առկայության պատճառով սպասիր () Ծնողական գործընթացը միշտ կսպասի երեխայի գործընթացի ավարտին: Այս դեպքում մենք էկրանին կստանանք խիստ սահմանված տեքստային ելք
exec() զանգ
Հաշվի առեք մարտահրավերը exec (). Այս համակարգային զանգը օգտակար է, երբ մենք ցանկանում ենք գործարկել բոլորովին այլ ծրագիր: Այստեղ մենք կկանչենք execvp () գործարկել wc ծրագիրը, որը բառերի հաշվման ծրագիր է: Ի՞նչ է պատահում, երբ կանչվում է exec(): Այս զանգին փոխանցվում է գործարկվող ֆայլի անունը և որոշ պարամետրեր՝ որպես արգումենտ: Որից հետո այս գործարկվող ֆայլի կոդը և ստատիկ տվյալները բեռնվում են և ծածկագրով սեփական հատվածը վերագրվում է: Մնացած հիշողության տարածքները, ինչպիսիք են կույտը և կույտը, վերսկսվում են: Որից հետո ՕՀ-ն պարզապես կատարում է ծրագիրը՝ փոխանցելով նրան մի շարք փաստարկներ։ Այսպիսով, մենք նոր պրոցես չստեղծեցինք, մենք ուղղակի գործող ծրագիրը փոխակերպեցինք մեկ այլ գործող ծրագրի: Հետնորդում exec() կանչը կատարելուց հետո թվում է, թե սկզբնական ծրագիրը ընդհանրապես չի գործարկվել։
Գործարկման այս բարդությունը լիովին նորմալ է Unix shell-ի համար և թույլ է տալիս այդ կեղևը գործարկել կոդը զանգից հետո: պատառաքաղ (), բայց զանգից առաջ exec (). Նման կոդի օրինակ կարող է լինել shell միջավայրի հարմարեցումը գործարկվող ծրագրի կարիքներին՝ նախքան այն գործարկելը:
Խեցի - պարզապես օգտագործողի ծրագիր: Նա ձեզ ցույց է տալիս հրավերի գիծը և սպասում, որ դուք ինչ-որ բան գրեք դրա մեջ: Շատ դեպքերում, եթե այնտեղ գրեք ծրագրի անվանումը, ապա կեղևը կգտնի իր գտնվելու վայրը, կկանչի fork() մեթոդը և այնուհետև կկանչի exec() մի տեսակ՝ նոր գործընթաց ստեղծելու համար և սպասելու, որ այն ավարտվի՝ օգտագործելով a. սպասել() զանգ. Երբ երեխայի պրոցեսը դուրս գա, կեղևը կվերադառնա սպասման () զանգից և նորից կտպագրի հուշումը և կսպասի հաջորդ հրամանի մուտքագրմանը:
Fork() & exec() բաժանումը թույլ է տալիս shell-ին անել հետևյալ գործողությունները, օրինակ.
wc ֆայլ > new_file.
Այս օրինակում wc ծրագրի ելքը վերահղված է ֆայլ: Այն, թե ինչպես է կեղևը հասնում դրան, բավականին պարզ է՝ նախքան զանգահարելը ստեղծելով երեխայի գործընթաց exec (), կեղևը փակում է ստանդարտ ելքը և բացում ֆայլը նոր_ֆայլ, այսպիսով, ամբողջ արդյունքը հետագա գործող ծրագրից wc էկրանի փոխարեն կվերահղվի ֆայլ:
Unix խողովակ իրականացվում են նմանատիպ եղանակով, այն տարբերությամբ, որ օգտագործում են pipe() կանչ: Այս դեպքում պրոցեսի ելքային հոսքը կմիանա միջուկում գտնվող խողովակի հերթին, որին կմիանա մեկ այլ պրոցեսի մուտքային հոսքը։
Source: www.habr.com