24 Ocak 2008

UNIX OLANAKLARI
İŞLEMLER, KOMUT GİRME, YÖNLENDİRME,
İŞLEMLER ARASI İLETİŞİM

UNIX ORTAMI

UNIX özet olarak bellekte çalışan çekirdek bir işletim sistemi (kernel) ve bu program tarafından başlatılan diğer işlemlerden (programlardan) oluşur. Kavram olarak UNIX için her şey bir kütüktür. Ana bellek, disk, terminallerin bağlandığı seri uçlar, disket sürücü, yazıcı bağlantısı, CD sürücü ve diğerleri hepsi bir kütük olarak tanımlıdır.

UNIX ortamında bir kütük, en az bir byte okunabilen ve/veya yazılabilen birime verilen addır. Bir kütüğü açmak, kütükten okumak, kütüğe yazmak ve kütüğü kapatmak için kullanılan komutların tümüne sürücü program adı verilir. Sürücü program (driver), ya çekirdek işletim sistemi içine gömülüdür, ya da işletim sistemi tarafından bilgisayar açıldığında belleğe yüklenir.

UNIX işletim sistemi ilk çalıştığında sürücü programları yükledikten, çevre birimlerini tanıdıktan sonra kök kütük yapısını (root file sistem) sisteme bağlar ve bu yapı içinden init adlı programı çalıştırır. init UNIX ortamında çalışan ilk işlem olduğu için işlem numarası 1 dir. UNIX bellekteki her işlemi tekil bir numara ile izler. Bu işlemi başlatmak, durdurmak UNIX tarafından bilinen işlem numarası aracılığı ile yapılır. init önce stdin, stdout ve stderr kütüklerini açar. Bu kütüklerin kullanım hakkı init tarafından başlatılan tüm programlara devredilir. init kök kütük yapısındaki programları başlatmak için /etc/inittab kütüğünü okur. Burada hangi programların ne zaman başlatılacağı bilgisi vardır. Bir program, sistem ilk açıldığında, tek kullanıcılı ortamda veya çok kullanıcılı ortamda çalışabilir. Sistem açıldığında ve tek kullanıcılı ortamda çalıştırılan programlar çoğunlukla çevre birimi sürücü programları, iletişim protokolu programları olur. Çok kullanıcılı ortamda başlatılan programlar ise kullanıcıların terminallerinden ve modemlerden sisteme girişlerine olanak veren programlardır.

Aşağıdaki örnek, bir inittab kütüğünün içeriğinde bulunan bilgileri gösterir. Burada her işlem satırındaki bilgilerin anlamı kısaca şöyle açıklanabilir. Birinci bilgi alanı işlem adımının adıdır. İkinci alan, işlemin, sistemin hangi çalışma düzeyinde, çalışması gerektiğini belirtir. Çalışma düzeyleri 0-6 arasında bir değerdir. Üçüncü alan işlemin hangi konumda olması gerektiğini gösterir (respawn, wait, off gibi). Dördüncü alan ise çalışacak işlemin kök kütük yapısındaki yerini tanımlar.

/etc/inittab

#
# inittab INIT işleminin nasıl çalışacağını gösteren kütüktür
#
# # Default çalışma düzeyi.
id:3:initdefault:

# sistem başlama zamanı (sistem boot olurken çalışır).
si:S:sysinit:/etc/rc.d/rc.S

# Tek kullanıcılı ortama geçiş için gereken komut (çalışma düzeyi 1).
su:1S:wait:/etc/rc.d/rc.K

# Çok kullanıcı ortama geçiş için gereken komut.
rc:23456:wait:/etc/rc.d/rc.M

# yeniden boot etmek için gereken işlem (Ctrl+Alt+Del).
ca::ctrlaltdel:/sbin/shutdown -t5 -rfn now

# Çalışma düzeyi 0, Sistemi durdurur (kapatır).
l0:0:wait:/etc/rc.d/rc.0

# Çalışma düzeyi 6, sistemi yeniden başlatır (reboot).
l6:6:wait:/etc/rc.d/rc.6

# Güç kaynağı kesildiğinde yapılacak işlem (Sistemi tek kullanıcılı ortama alma).
pf::powerfail:/sbin/shutdown -f +5 "THE POWER IS FAILING"

# Kapanmadan güç kaynağı gelirse, kapatma işlemini durdurma.
pg:0123456:powerokwait:/sbin/shutdown -c "THE POWER IS BACK"

# Tek kullanıcılı ortamda elektrik gerilse, çok kullanıcılı ortama geçme.
ps:S:powerokwait:/sbin/init 5

# Çok kullanıcılı ortamda sistem konsolu ve terminaller için getty işlemi.
#
c1:1235:respawn:/sbin/agetty 38400 tty1 vt100
c2:1235:respawn:/sbin/agetty 38400 tty2 vt100
c3:1235:respawn:/sbin/agetty 38400 tty3 vt100

***

# Seri uçlardan terminaller için getty işlemi
#s1:12345:respawn:/sbin/agetty 19200 ttyS0 vt100
#s2:12345:respawn:/sbin/agetty 19200 ttyS1 vt100

***

# Telefon hattına bağlı modemler için getty işlemi
d1:12345:respawn:/sbin/agetty -mt60 38400,19200,9600,2400,1200 ttyS0 vt100
d2:12345:respawn:/sbin/agetty -mt60 38400,19200,9600,2400,1200 ttyS1 vt100
***


init tarafından başlatılan programlar veya işlemlerle sistem çok kullanıcılı ortama geçer. Çok kullanıcılı ortamda sisteme bağlı terminallere login ekranı gelir. Modemler telefon çağrısını bekler konuma geçer. Varsa yerel ağ donanımı dışarıdan gelen sinyalleri algılacak komunda bekler. Sisteme başka sistemlerden giriş yapılabilmesi için kullanılan sürücü programlara (nfs, nis, inetd, lpd gibi) servis sunucu programlar veya deamon adı verilir. Bu programlar bellekte dinleme konumunda bulunurlar ve ilk gelen bilgiye cevap verecek biçimde beklerler. Çoğu zaman yapılan ilk isteği algılar, bu isteğe cevap verebilecek programı çalıştırır ve tekrar bekleme konumuna geçerler.

Yalnız getty programının çalışma sistemi farklıdır. Burada terminal ekranına login bilgisi gönderilir ve giriş yapılması beklenir. İlk girilen bilgi ile getty, login programını çalıştırıp bellekten silinir. Login, kullanıcı adını /etc/passwd kütüğünden kontrol eder, bilgi geçerli ise passwd programını çalıştırarak, kullanıcı şifresinin girilmesini beklemeye başlar. passwd programı geçerli şifreyi aldıktan sonra /etc/passwd kütüğündeki kütük yoluna geçiş yapar ve kullanıcı için tanımlanan işlemi, o kullanıcı adına çalıştırır. Bu işlem çoğu kez bir kabuk (shell) programıdır. Özel durumlarda ise hiç bir kabuk oluşturmadan, doğrudan uygulama programı başlatılabilir.

KABUK (SHELL) ORTAMI

Kabuk (shell), kullanıcının komut girebilmesi, girdiği komutu çalıştırabilmesi için hazırlanmış özel bir programdır. /usr/bin/sh kullanılan programın yolunu ve programın adını belirtir. Kabuk programı /etc/passwd kütüğünde belirtilen kullanıcı yolunu, o kullanıcı için UNIX kütük yapısı altında kullanıcı yurdu (HOME) olarak belirler. Burada bulunan profile adlı kütükten ilk tanımları, çevre değişkenleri değerlerini ve çalıştırması gereken programları alır ve kullanıcıya komut girmesi için komut simgesi (prompt) görüntüler.

Artık kullanıcı UNIX ortamında komut girebilir, derleme yapabilir, yetkisi ölçüsünde çalıştırabileceği her şeyi kullanır.

Kullanıcı kabuktan çıkmak için Crtl+D tuşlarına basar veya exit yazar. Terminal tekrar init programı kontroluna geçer. init programı /etc/inittab kütüğünden bu terminal için çalıştırcağı programı bulur (bu getty adlı programdır) ve onu çalıştırır. getty ekrana login bilgisini görüntüler ve bilgi girişi yapılmasını bekler.

UNIX ortamında işletim sistemine bir işlem yaptırmak için kullanıcının sisteme girmesi, kendi kabuk programı altından ilgili komutu çalıştırması gerekir. UNIX ortamında çalıştırılan bir program, kullanıcının ve kullanıcının bağlı olduğu grubun sistem kullanma olanakları ve yetkileri ile sınırlıdır. Teorik olarak her kullanıcı, her işlemi çalıştıramaz, başlattığı her işlemde her işi yaptıramaz.

Özetlemek gerekirse bir işlem, UNIX altında çalışan bir programdır. Her programı başlatan bir program bulunur. Başlatan programa veli, başlatılan programa çocuk denir. veli öldüğünde ya çocuk da ölür, ya da çocuk yetim kalmasın diye init, vasi olarak görevi üstlenir. Bir işlem kendi altında bir başka işlem başlatırsa o işlemin velisi olur ve onun işletim sistemi altındaki kontrolunu elinde bulundurur. Veli-çocuk ilişkisi işletim sisteminin olanakları (sınırları) içinde derinleşebilir. İşletim sistemi bir kullanıcının iç içe başlatabileceği işlem sayısını ve sistemde çalışan toplam işlem sayısını sınırlayabilir.

İŞLEMLER ve STANDARD KÜTÜKLER

Bir kabuk altında çalışan her program UNIX açısından bir işlemdir. UNIX her işlemi ayrı ve tekil bir işlem numarası ile bellekte tutar. Bir komut çalışırken stdin, sdtout ve stderr kütüklerini açmak gerekmez. Çünkü bu kütükler veli program tarafından çocuk işlemin kullanımına sunulmuş hazır açık kütüklerdir. Bu kütükler sıra ile 0, 1 ve 2 nolu kütükler olarak anılır ve programlarda bu kütük numaraları ile kullanılır. Bir işlem stdin olarak kullanıcının tuş takımını, stdout ve stderr olarak kullanıcı ekranını bilir.

Bu kütüklerin nereden alınacağı, nasıl yönlendirileceği komut yazılırken belirtilebilir. UNIX ortamındaki giriş/çıkış kütüklerini yönlendirme özelliği, programı değiştirmeden değişik bilgi saklama ortamlarından bilgi okuyabilme veya değişik ortamlara bilgi yazabilme olanağı getirir.

GİRİŞ/ÇIKIŞ KÜTÜKLERİNİ YÖNLENDİRME

Giriş kütüğünü yönlerdirmek için program komutundan sonra '<' simgesi kullanılır. Örneğin :

    $ komut < okuma.dat
Bu örnekte standart giriş kütüğü yerine bilgiler okuma.dat kütüğünden satır satır okunarak programa aktarılır.

Çıkış kütüğünü ekrandan bir başka yöne yönlendirmek için :

    $ komut > yazma.dat
komutu örneği kullanılır. Burada '>' simgesi çıkış bilgisinin yazma.dat kütüğüne yazılmasını sağlar. Daha önce var olan bir kütüğün sonuna ek yapmak için '>>' simgeleri kullanılır.

Çıkış bilgisinin hiç bir kütüğe yazılmadan silinmesi istenirse

    $ komut > /dev/null
örneğinde olduğu gibi çıkış bilgisi olmayan kütüğe yönlendirilebilir.

stderr kütüğünü yönlerdirme işlemi normal koşullara göre biraz daha karmaşıktır. Burada kullanılan örnek :

    $ komut 2>&1 > okuma.dat
biçiminde olunca 2 nolu kütük (stderr) önce 1 nolu kütüğe (stdout) yönlendirilmekte, sonra bir numaralı kütük okuma.dat kütüğüne yönlendirilmektedir. Burada "2>&1" simgeleri arasında boşluk bırakılmamalıdır.

KOMUT GİRME ve ÇALIŞTIRMA

Kullanıcı, kabuk program çalıştığında, ekranda komut girme simgesi ile karşılaşır. Buraya çalıştırılacak programın adını girer. UNIX kullanıcı için tanımlanmış PATH çevre değişkenindeki kütük yolu tanımlarını sıra ile arar ve yazılan programı ilk bulduğu yerden belleğe yükleyerek çalıştırır.

Çalışan program göreceli kütükleri kullanıcının yurdundaki kütük yolundan veya o anda bulunduğu alandan başlayarak okur veya yaratır.

İsterse kullanıcı bir programın kökten başlayarak tüm yolunu vererek başlatabilir. Bu durumda UNIX PATH değişkeni değerlerine bakmaksızın istenilen programı belirtilen kütük yolundan okuyup belleğe alır ve çalıştırır.

Komut satırında programa parametre aktarma olanağı vardır. Eğer bir program komut satırındaki parametreleri algılayabilecek biçimde yazılmış ise, komut satırına yazılan her parametre programın değişen seçeneklerle kullanılmasını sağlar. Komut satırında çift tırnak (") kullanılmadan yazılan her parametre arasındaki boşluklar kabuk program tarafından bilgi alanı ayıracı olarak kullanılır. Ama (") içine yazılan parametreler bir arada (boşluklar dahil edilerek) programa gönderilir. Örneğin :

    $ komut param_1 param_2 param_3 ... param_n
çalıştırılan programa :
char *argv[] = {
      "komut",
      "param_1",
      "param_2",
      "param_3",
        ...
      "param_n"
      };
tanımındaki gibi aktarılır. Bu tablodaki toplam eleman sayısı (n+1) dir. Programa aktarılan ilk parametre komut satırında kaç parametre olduğunu belirtir. Tablodaki 0 numaralı eleman her zaman programın adını içerir.
    $ komut param_1 "param_2 param_3 ... param_n"
biçiminde çalıştırılan programda, programa aktarılan parametre tablosu
char *argv[] = {
      "komut",
      "param_1",
      "param_2 param_3 ... param_n"
      };
tanımında olduğu gibidir. Bu örnekte toplam parametre sayısı (3) dür.

İŞLEMLER ARASI İLETİŞİM

PIPE Bir işlemin çıkışını diğerinin girişine yönlendirme işlemine verilen genel addır. Bu işlem komut satırında (|) işareti ile yapılabilir. Örneğin :

    $ komut_1 | komut_2
Burada komut_1 çalışırken çıktısı komut_2 için giriş bilgisi olur. PIPE işlemi aslında aynı komut satırında çıkış ve giriş kütüklerini yönlendirme işlemidir.

Bir program içinden bu tür yönlendirme yapmak için popen (pipe open) komutu kullanılır. Bu komutta kütük adı yerine çalıştırılacak program yazılır ve PIPE işleminin nasıl olacağı okuma/yazma seçeneğinde belirtilir. Eğer bu seçenekte "w" kullanılırsa popen komutu ile açılan kütük ilgili program için çıktı kütüğüdür. PIPE komutu ile çalıştırılan program ise giriş bilgisini kendisini çağıran programdan alır. Eğer bu alana "r" yazılırsa, Çağırılan programın çıktısı çağıran program tarafından popen komutu ile açılan kütük aracılığı ile okunmuş olur.

ADLANDIRILMIŞ PIPE (NAMED PIPE)

Bu komut UNIX ortamında kullanılan eski bir işlemler arası iletişim yöntemidir. Önce adlandırılmış PIPE mknod komutu ile yaratılır. Birbirleri ile iletişim kuracak programlardan biri bu adlandırılmış PIPE'ı giriş kütüğü diğeri ise çıkış kütüğü olarak açar. Giriş kütüğü olarak açan PIPE'dan bilgi okur. Çıkış kütüğü olarak açan ise PIPE'a bilgi yazar. Tek yönlü iletişim bir başka adlandırılmış PIPE aracılığı ile diğer yönde de kurulabilir. Diğer bir deyimle bir PIPE çıkış kütüğü olarak açılmış ise aynı programda diğer PIPE giriş kütüğü olarak açılır. Diğer program ise öncekinin çıkış kütüğü olarak açtığını giriş, giriş kütüğü olarak açtığını çıkış kütüğü olarak açarsa iki yönlü iletişim kurulmuş olur.

Adlandırılmış PIPE bir kez yaratıldıktan sonra hep sistemde kalır.

SOCKET (AF_UNIX PROTOKOLÜ)

AF_UNIX protokolü kullanarak açılan socket ler kavram olarak PIPE kullanımına benzer. Bir program socket dinlerken diğeri socket aracılığı ile mesaj gönderir, sonra cevap bekler. Bu kullanım biçimindeki en önemli değişiklik bir socket'in her iki program tarafından hem mesaj okuma hem de mesaj yazma ortamı olarak kullanılabilir olmasıdır.

socket dinleyen program önce socket bilgisini yaratır. Diğer program, bu socket bilgisini kullanır. İşlem bittiğinde socket yaratan program (dinleyen) socket bilgisini siler. Eğer sistemde aynı adla bir socket varsa, program yeni socket yaratamaz. socket kullanılıyor diye mesaj verip işlemi bitirir.

İŞLEMLER ARASI İLETİŞİM (IPC)

UNIX System V kavramları ile işletim sistemine gelen bu özellik üç temel bilgiden oluşur :

  • İşlemler arası ortak bellek kullanma,
  • işlemler arası mesaj kuyrukları oluşturma,
  • işlemler arası semaphore kullanımı.
Kavram olarak; ortak bellek, mesaj kuyrukları ve semaphore sistemde işletim sistemi tarafından denetlenen bellek alanlarının adlarıdır. Bir işlem bu kavramlardan birini kullanmak istediğinde işletim sistemi ya ilgili kavram için bellekte yer açar ya da mevcut kavramın adresini, adını veya anahtar bilgisini kullanıcının kullanımına sunar. Bellekteki her kavramın bir adı veya anahtar bilgisi vardır. Bu kavramı kullanacak program, anahtar bilgi aracılığı ile kavrama erişir, okur, değerini değiştirir veya kuyruğa yeni bilgi ekler.

Bu bölümde her kavramın nasıl kullanıldığı, anlamı kısaca anlatılmıştır.

  • ORTAK BELLEK

    shmget, shmat, shmdt komutları ortak bellek işlemlerinde programlar tarafından kullanılır.

    shmget Bu komut işletim sisteminin, ortak bellek kesidi ataması yapması için kullanılır. Program hangi anahtar bilgi için ne kadar uzunlukta bellek ataması yapılacağını belirtir. Bu anahtar bilgi için daha önce atanmış alan varsa adresi programa geri dönerken, işletim sistemi hiç bir bilgi bulamaz ise komutun özelliğine göre iki işlem yapar :

    • Eğer komutta IPC_CREAT tanımlanmış ise hemen bellek alanı açar ve adını (identifier) programa geri döndürür.
    • Eğer komutta IPC_CREAT yoksa, bir başka program alan açıncaya kadar ilk programı bekletir.

    shmat Bu komut daha önce shmget komutundan alınan ortak bellek adının komutu kullanan programa atanması için gereklidir. Atama ilgili ortak belleğin programdaki veri kesimine bağlanması anlamına gelir.

    shmdt Bu komut daha önce atanmış ortak belleğin bağlantısını kaldırmak için kullanılır.

    Örnek :

        shmid = shmget((key_t) SUBESHM,
                       sizeof(struct GDATA),
                       0666 | IPC_CREAT);
        shr_ptr = (char *)shmat(shmid, NULL, 0);
        

    Bu komutlarla program adres değişkeni olan shr_ptr işletim sistemi tarafından yaratılan ortak belleği hem okuma hem de yazma amaçlı kullanabilir.

  • MESAJ KUYRUĞU

    msgget, msgsnd, msgrcv komutları mesaj kuyruğu kavramları için programlarda kullanılır.

    msgget Bu komut mesaj kuyruğu adını almak için kullanılır. Eğer daha önce bu mesaj tipi için bellekte kuyruk açılmamış ise işletim sistemi IPC_CREAT seçeneği ile mesaj kuyruğunu açar ve tanımını programa geri gönderir.

    msgsnd Bu komut bir kez msgget ile alınmış olan mesaj adını kullanarak mesaj kuyruğuna bilgi göndermek için kullanılır. işlem seçeneğinde IPC_NOWAIT varsa, mesajın kuyruklanması yeterlidir. Program işlemlerine devam eder. Eğer IPC_NOWAIT yoksa mesaj kuyruktan okununcaya kadar beklenir.

    msgrcv Mesaj kuyruğundan bilgi okuyacak program mesaj adını msgget komutu ile alır, daha sonra okuyacağı mesaj numarasını kuyruktan almak için msgrcv komutunu kullanılır. İlgili program mesaj kuyruğuna aynı mesaj numarası ile mesaj koymuş ise onu okur. Eğer IPC_NOWAIT tanımlanmışsa ve mesaj bulunamaz ise okuyan program işlemlerine devam eder. IPC_NOWAIT kullanılmamış ise kuyruğa mesaj yazılıncaya kadar bekler.

    Örnek :

        struct MSGBUF {
            long mtype;
            char msg[MAXMSG];
            };
        struct MSGBUF msgbuf;
                 .
                 .
                 .
        *********** mesaj gonderen program *********
        msgid = msgget((key_t)SUBEMSG, 0666 | IPC_CREAT);
        msgtype = no;
        msgsnd(msgid, &msgbuf, 
               sizeof(struct MSGBUF), 
               msgtype, 
               IPC_WAIT);
        *********** mesaj okuyan program ***********
        msgid = msgget((key_t)SUBEMSG, 0666 | IPC_CREAT);
        msgtype = no;
        msgrcv(msgid, &msgbuf, 
               sizeof(struct MSGBUF), 
               msgtype, 
               IPC_WAIT);
        
    Bu örnekte mesaj okuyan program msgrcv komutunda bekler. Aynı şekilde mesaj gönderen program da msgsnd komutunda bekler. Her iki komut işlemini bitirdikten sonra programlar bir sonraki adıma geçer. Eğer IPC_WAIT yerine IPC_NOWAIT kullanılmış olsaydı yukarıdaki örnekte gönderme işlemi yapan program kuyruğa bilgiyi yazıp hemen bir sonraki işleme geçecek, diğer programın mesajı alıp almamasını beklemeyecekti. Aynı mantıkla okuma yapan program msgrcv komutunda beklemeyecek, eğer mesaj yoksa veya daha hazır değilse bir sonraki işlemden program akışına devam edecekti.

  • SEMAPHORE

    semget, semop komutları ilgili kavram için programlarda kullanılır.

    semget Bu komut istenilen anahtar bilgi için işletim sistemi tarafından atanan semaphore kümesinin adını (identifier) döndürür. Eğer aynı anahtar bilgi ile sistemede tanımlı semaphore kümesi yoksa ve komut kullanımında IPC_CREAT belirtilmiş ise işletim sistemi semaphore kümesi yaratır ve yaratılan semaphore'un adını döndürür.

    semop Bu komut semaphore kullanımında yapılacak işlemleri tanımlamak için kullanılır. struct sembuf yapısında belirtilen işlemlerin ne amaç için kullanıldığı bu yapı tanımındaki bilgilerin alacağı değerlerle ilişkilidir. Bu yapı tanımında bulunan :

        short sem_num;
        short sem_op;
        short sem_flg;
        
    değişkenleri yapılacak işlemi tanımlamada önemli değerler alır. sem_flg içinde bulunan IPC_NOWAIT ve SEM_UNDO işlev tamamlanmadığında semaphore işlemini geri almak için kullanılır. sem_num ilk değeri 0 ile başlayan ve aynı küme içinde yer alan semaphore'ları tanımlar. sem_op değeri artı bir sayısal değer ise semval değişkenini arttırır. Eğer sem_flg içinde IPC_NOWAIT tanımlanmamış ise bu işlev aşağıdakilerden biri oluşuncaya kadar bekler :

    1. semval değeri 0 olunca,
    2. semaphore kümesi bellekten silinince,
    3. işlevi başlatan program bir sinyal alıp işlemi kesince.

    sem_op eksi bir değer ise semval değişkeni eksiltilir. Bu işlem için programın semaphore kümesini değiştirebilme yetkisi olmalıdır.


Ana Sayfaya   Teknik Bilgiler Sayfasina


Aglar Aglink Agteknik C-Kodlama C-Önişleme CRC/LRC DEA etcsrv Çatal (fork) ilet inetd Make Msg Auth Özyinelemeli Robotlar için SDLC Güvenlik Seri uçlar SNA LU0 SNA LU6.2 tcp/ip tcp Programı Unix vi Editör