İşletim sistemlerine giriş
Merhaba, Habr! Sizlere ilginç bulduğum bir edebiyat serisinin çeviri makalelerini sunmak istiyorum — OSTEP. Bu materyalde Unix benzeri işletim sistemlerinin çalışma prensipleri derinlemesine ele alınıyor; özellikle süreçler, farklı zamanlayıcılar, bellek ve modern bir işletim sistemini oluşturan diğer bileşenler üzerine. Tüm materyallerin orijinal haline buradan ulaşabilirsiniz . Lütfen dikkate alın ki, çeviri profesyonelce yapılmamıştır (biraz serbest) ama umarım genel anlamı korumuşumdur.
Bu konuda laboratuvar çalışmaları burada bulunabilir:
— orijinal:
— orijinal:
— benim kişisel uyarlamam:
Bir de Telegram kanalımda bana göz atabilirsiniz =)
Programın çalışması
Bir program çalıştırıldığında ne olur? Başlatılan program, yapması gereken basit bir işi vardır — talimatları yürütmek. Her saniye, milyonlarca hatta belki milyarlarca talimat, işlemci tarafından bellekteki yerinden çıkarılır, işlemci bunları çözümler (örneğin, bu talimatların hangi türe ait olduğunu tanır) ve yürütür. Bu, iki sayının toplanması, belleğe erişim, koşul kontrolü veya bir fonksiyona geçiş gibi işlemler olabilir. Bir talimatın yürütülmesi tamamlandığında, işlemci diğerine geçer. Bu şekilde, talimatlar birbirini takip eder ve program sona erene kadar yürütülmeye devam eder.
Bu örnek elbette basitlenmiş olarak ele alınmıştır; aslında modern donanım, işlemcinin talimatları sıraya almadan yürütmesine, olası sonuçları hesaplamasına, talimatları aynı anda yürütmesine ve benzeri hileleri yapmasına olanak tanır.
Von Neumann hesaplama modeli
Yukarıda açıkladığımız basitleştirilmiş çalışma şekli, Von Neumann hesaplama modeline benzemektedir. Von Neumann, bilgisayar sistemlerinin öncülerinden biridir ve aynı zamanda oyun teorisi üzerine de çalışmalarıyla tanınır.. Program çalışırken pek çok başka olay da gerçekleşir, birçok başka süreç ve dış mantık çalışır; bunların ana amacı sistemi başlatmayı, çalıştırmayı ve bakımını kolaylaştırmaktır.
Bir programın başlatılmasını (hatta birkaç programı aynı anda çalıştırmayı) kolaylaştırmakla sorumlu bir yazılım seti vardır. Bu yazılım, programların aynı belleği paylaşmasına ve çeşitli aygıtlarla etkileşime girmesine olanak tanır. Bu yazılım setine temelde işletim sistemi denir ve görevleri arasında sistemin doğru ve verimli çalışmasını sağlamak, aynı zamanda bu sistemin yönetimini kolaylaştırmak yer alır.
Əməliyyat sistemi
Əməliyyat sistemi, qısacası, ƏS — kompüterin resurslarını idarə etməyə və istifadəçi ilə kompüter arasında qarşılıqlı əlaqə yaratmağa yönəlmiş, bir-biri ilə əlaqəli proqramların kompleksidir..
ƏS öz səmərəliliyinə, ilk növbədə, ən əsas texnika vasitəsilə — texnikadan. virtualizasiya. ƏS fiziki resursla (prosessor, yaddaş, disk və s.) qarşılıqlı əlaqə qurur və onu daha ümumi, daha geniş imkanlara malik və istifadə üçün daha asan forma çevrir. Buna görə, ümumi anlayış üçün, əməliyyat sistemini virtual maşınla çox sadə bir şəkildə müqayisə edə bilərik.
İstifadəçilərə əməliyyat sisteminə komandalar verməyə və beləliklə virtual maşının imkanlarından (məsələn: proqramı işə salmaq, yaddaş ayırmaq, fayla giriş və s.) istifadə etməyə imkan tanımaq üçün, əməliyyat sistemi bir interfeys təqdim edir ki, buna da API (application programming interface) deyilir və buna çağırışlar (call) etmək mümkündür. Tipik bir əməliyyat sistemi yüzlərlə sistem çağırışı etməyə imkan tanıyır.
Və nəhayət, virtualizasiya bir çox proqramın paralel işləməsinə (beləliklə, CPU-nu birgə istifadə etməyə) və eyni zamanda onların instrukiyalarına və məlumatlarına (buna görə də yaddaşı bölüşdürməyə) girişi icazə verdiyinə görə, əməliyyat sisteminə resurs meneceri də deyilir. Hər bir prosessor, disk və yaddaş sistemin resursudur, buna görə də əməliyyat sisteminin vəzifələrindən biri bu resursları effektiv, ədalətli və ya əksinə, bu əməliyyat sisteminin hazırlanma məqsədinə uyğun olaraq idarə etməkdir.
CPU virtualizasiyası
Gəlin aşağıdakı proqramı nəzərdən keçirək:
(https://www.youtube.com/watch?v=zDwT5fUcki4&feature=youtu.be)

Bu proqramın xüsusi bir fəaliyyəti yoxdur, əslində onun etdiyi — bir funksiyanı çağırmaqdır spin(), vəzifəsi isə zamanın dövrü yoxlanılmasıdır və bir saniyə keçdikdən sonra dönüşdür. Beləliklə, istifadəçinin arqument olaraq verdiyi sətiri sonsuz dövrədə təkrarlayır.
Bu proqramı işə salaq və ona arqument olaraq “A” simvolunu verək. Nəticə o qədər də maraqlı deyil — sistem sadəcə olaraq, periodik olaraq “A” simvolunu ekrana çıxaran proqramı icra edir.
İndi eyni proqramın bir çox nümunəsi ilə işlədikdə, lakin fərqli hərflər çıxardıqda daha aydın olması üçün bir variantı sınaqdan keçirək. Bu halda, nəticə bir qədər fərqli olacaq. Bizim yalnız bir prosessor olmasına baxmayaraq, proqram eyni anda icra edilir. Bəs bu necə mümkündür? Məsələ burasındadır ki, əməliyyat sistemi, avadanlığın imkanlarından da istifadə edərək, illüziya yaradır. Bu illüziya, sistemdə bir neçə virtual prosessorun olduğuna, bir fiziki prosessoru nəzəri cəhətdən sonsuz sayda çevirməyə imkan verir və beləliklə, proqramların görünüşdə eyni anda icra olunmasına imkan tanıyır. Bu illüziya CPU-nun virtualizasiyası.
Belə bir mənzərə bir çox suallar yaradır, məsələn, əgər bir neçə proqram eyni anda işə düşmək istəyirsə, hansı konkret proqram icra olunacaq? Bu suala əməliyyat sisteminin "siyasətləri" cavab verir. Siyasətlər əməliyyat sisteminin bir çox yerlərində istifadə olunur və belə suallara cavab verir, eyni zamanda əməliyyat sisteminin reallaşdırdığı əsas mexanizmlərdir. Buradan əməliyyat sisteminin resurs meneceri olaraq rolu da ortaya çıxır.
Yaddaşın virtualizasiyası
İndi gəlin yaddaşı nəzərdən keçirək. Müasir sistemlərdə yaddaşın fiziki modeli bayt massivləri kimi təsvir edilir. Yaddaşdan oxumaq üçün hüceyrənin ünvanınıgöstərmək lazımdır ki, ona daxil olmaq mümkün olsun. Məlumatı yazmaq və ya yeniləmək üçün də, eləcə də yazılması gərəkən hüceyrənin ünvanını göstərmək lazımdır.
Proqramın icrası zamanı yaddaşa daima müraciət edilir. Proqram yaddaşda bütün məlumat strukturlarını saxlayır və müxtəlif təlimatları yerinə yetirərkən ona müraciət edir. Bu arada, təlimatlar da yaddaşda saxlanılır, buna görə də hər növbəti təlimata müraciət zamanı da yaddaşla əlaqə qurulur.
malloc() çağırışı
İndi aşağıdakı proqramı nəzərdən keçirək ki, malloc() çağırışı ilə yaddaş sahəsi ayırır. malloc() (https://youtu.be/jnlKRnoT1m0):

Proqram bir neçə şeyi edir. Birincisi, müəyyən bir miqdar yaddaş ayırır (sətir 7), sonra ayrılan hüceyrənin ünvanını çıxarır (sətir 9), ayrılan yaddaşın birinci slotuna sıfır yazır. Daha sonra proqram, "p" dəyişənindəki ünvan üzrə yaddaşda yazılmış dəyəri artırdığı bir dövrəyə daxildir. Eyni zamanda, proqram özünün proses identifikatorunu da çıxarır. Prosesin identifikatoru hər bir işə salınmış proses üçün unikaldır. Lakin bir neçə nüsxə işə saldıqda maraqlı bir nəticəyə rast gələcəyik: Birinci halda, heç bir şey etmədən sadəcə bir neçə nüsxə işə saldıqda, ünvanlar fərqli olacaq. Amma bu, bizim nəzəriyyəmizə uyğun gəlmir! Doğrudur, çünki müasir distroslarda yaddaşın təsadüfi yerləşdirilməsi standart olaraq aktivdir. Onu deaktiv etsəniz, gözlənilən nəticəni alacağıq — eyni zamanda çalışan iki proqramın yaddaş ünvanları eyniləşəcək.

Nəticədə, iki müstəqil proqramın özəl ünvan məkanları ilə işlədiyi ortaya çıxır, ki bunlar öz növbəsində əməliyyat sistemi tərəfindən fiziki yaddaşda şəkil alır.. Buna görə də bir proqram daxilində yaddaş ünvanlarının istifadəsi digər proqramlara tamamilə təsir etməyəcək və hər bir proqrama, sanki özünə aid fiziki yaddaş parçası varmış kimi görünəcək. Lakin gerçək budur ki, fiziki yaddaş - paylaşılan bir resursdur və onun idarə olunması əməliyyat sistemi tərəfindən həyata keçirilir.
Uyğunluq
Əməliyyat sistemləri çərçivəsindəki vacib mövzulardan biri də uyğunluqdır. Bu termin, bir proqram daxilində bir çox şey eyni anda işlədilərkən ortaya çıxan sistemdəki problemlərlə əlaqədardır. Uyğunluq problemləri hətta əməliyyat sisteminin özündə də baş verə bilər. Keçmişdə yaddaş və prosessor virtualizasiyası nümunələrində, əməliyyat sisteminin eyni anda çox sayda şeyi idarə etdiyini anladıq – ilk prosesi başladır, sonra ikinci və s. Belə bir davranışın bəzi problemlərə səbəb olacağını qavramaq oldu. Məsələn, müasir çox ipli proqramlar belə çətinliklərlə üzləşir.
Gəlin aşağıdakı proqramı nəzərdən keçirək:

Proqramın əsas funksiyası iki iplik yaradır, istifadə edərək Pthread_create(). Bu nümunədə bir ipliyi digər funksiyalardan ayrılmış bir yaddaş məkanında başlamış bir funksiya kimi düşünmək olar, burada eyni anda icra olunan funksiyaların sayı bir dənədən artıqdır. Bu nümunədə hər bir iplik başlayır və worker() funksiyasını icra edir ki, bu da sadəcə olaraq dəyişəni artırır.,.
Bu proqramı 1000 arqumenti ilə işə salaq. Artıq təxmin edə biləcəyiniz kimi, nəticə 2000 olmalıdır, çünki hər bir iplik dəyişəni 1000 dəfə artırıb. Lakin hər şey bu qədər asan deyil. Proqramı təkrarlama sayı bir dərəcə daha çox olarkən işə salmağa çalışaq.

Əgər giriş olaraq 100000 ədədini verərsək, çıxışda 200000 ədədini görməyi gözləyirik. Ancaq 100000 ədədini bir neçə dəfə işə saldıqda, yalnız düzgün cavabı görməyəcəyik, həm də fərqli yanlış cavablar alacağıq. Bu problemin açarı odur ki, ədədin artırılması üçün üç əməliyyat tələb olunur - ədədin yaddaşdan çıxarılması, artırılması və sonra ədədin yenidən yazılması. Çünki bu əmrlər atomik şəkildə (hamısı eyni anda) yerinə yetirilmir, belə qəribə şeylər baş verə bilər. Bu problem proqramlaşdırmada race condition — yarış vəziyyətiadlanır. Naməlum qüvvələr naməlum bir anda sizə aid olan əməliyyatların icrasını təsir edə bilər.
Mənbə: habr.com
