[LinuxFocus-icon]
<--  | Ana Sayfa  | Eri�imd�zeni  | ��indekiler  | Arama

Duyumlar | Belgelikler | Ba�lant�lar | LF Nedir
Bu makalenin farkl� dillerde bulundu�u adresler: English  Castellano  Deutsch  Francais  Russian  Turkce  

[Leonardo]
Leonardo Giordani
<leo.giordani(at)libero.it>

Yazar hakk�nda:

Milan Politecnico Telekom�nikasyon M�hendisli�i fak�ltesinde yeni diploma ald�m.Programlama ile ilgileniyorum (�o�unlukla Assembly ve C/C++).1999'dan beri neredeyse sadece Linux/Unix ile �al��t�m.



T�rk�e'ye �eviri:
�zcan G�ng�r <ozcangungor(at)netscape.net>

��erik:

 

E�zamanl� Programlama - �leti Kuyruklar� (3)

[paralel olarak çalýþtýr]

�zet:

Bu makale, e�zamanl� programlama hakk�ndaki son makaledir: Burada, protokol�m�z�n ikinci ve son katman�n� uygulaca��z. Bu katman, �nceki makalede geli�tirdi�imiz ilk katman�n �zerinde kullan�c� davran��lar�n� uygulayan fonksiyonlar� yarat�r.

Bu serinin �nceki makalelerini okumak faydal� olacakt�r:


_________________ _________________ _________________

 

Protokol uygulamas� - Katman 2 - Genel

ipcdemo program�, bir kullan�c�dan di�er kullan�c�ya ileti g�nderen bir anahtar�n basit bir uygulamas� olarak geli�tirildi. Sim�lasyona biraz e�lence katmak i�in, "servis" kavram�n� ekledim: bir servis iletisi (sinyalleme), as�l i�levi kullan�c�dan kullan�c�ya veri g�ndermek de�il de kontrol bilgileri g�ndermek olan bir iletidir. Servis iletileri, kullan�c�lar taraf�ndan anahtara, onlar�n canl� olduklar�, onlara nas�l ula�abilecekleri ( IPC kuyruk kimli�ini g�ndererek) ve ba�lant�y� kesecekleri iletilerini g�nderir. �ki servis daha tan�mlanm��t�r: Ba�lant� kesme ve Zamanlama. �lki, anahtar taraf�ndan kullan�l�r ve kullan�c�ya ba�lant�y� kesmeleri gerekti�ini s�yler. �kincisi, kullan�c�n�n yan�t verme s�resini �l�er. Daha fazlas� kullan�c� ve anahtar b�l�m�nde anlat�lacakt�r.

Katman 2, servis isteyen, servise cevap veren ve ba�lang�� i�lemlerini yapan y�ksek seviyeli fonksiyonlar� i�erir. Bu fonksiyonlar Katman 1'deki fonksiyonlar kullan�larak olu�turulmu�tur ve bu y�zden anlamas� �ok kolayd�r. Sadece �una dikkat edin: layer2.h dosyas�nda, ileti tiplerini g�steren (kullan�c� iletisi veya servis iletisi) ve farkl� servisleri g�steren (�rne�in deneyler i�in iki kullan�c�-tan�ml� servis) isimleri tan�mlad�m.

ipcdemo, sadece tan�t�m kodudur: optimize edilmemi�tir ve farkedece�iniz gibi, bir�ok k�resel de�i�ken kulland�m. Ama bunu okuyucunun koda de�il IPC k�sm�na dikkatini �ekmek i�in yapt�m. Herneyse, e�er �ok garip bir�ey bulursan�z, bana hemen yaz�n ve tart��al�m.

 

Kullan�c� s�re�lerinin Uygulamas�

Kullan�c�, sabit olarak anahtar�n bir o�ul s�recidir ( ya da daha iyisi, anahtar olarak i� yapan baba s�recin). Bu, kullan�c�lar�n anahtar gibi ba�lat�lan b�t�n de�i�kenlere sahiptir. �rene�in, anahtar�n kuyruk kimli�ini bilir, ��nk� i�lemi b�lmeden �nce (forking) anahtar tarf�ndan bir yerel de�i�kede saklanmaktad�r.

Bir kullan�c� hayata geldi�inde, yapt��� ilk i� bir kuyruk yaratmak ve anahtar�n ona nas�l ula�aca��n� bildirmektir. Bunu yapmak i�in kullan�c�, iki servis iletisi g�nderir: SERV_BIRTH ve SERV_QID.

/* Kuyru�u ba�lat*/
qid = init_queue(i);

/* Anahtara hayatta oldu�umuzu bildir*/
child_send_birth(i, sw);

/* Anahtara bize nas�l ula�abilece�ini bildir*/
child_send_qid(i, qid, sw);
Sonra as�l d�ng�ye girer: Burada kullan�c� bir ileti g�nderir, di�re kullan�calardan gelen iletileri kontrol eder ve anahtar�n bir servis isteyip istemedi�ini kontrol eder.

�leti g�nderme hakk�ndaki karar, olas�l�k temeline dayanmaktad�r: myrand() fonksiyonu, verilen arg�mana g�re normalle�tirilmi� bir rastgele say� �retir, bizim durumumuzda 100. Biz , sadece bu say� belirlenen olas�l�ktan b�y�k ise iletiyi g�ndeririz. ��nk� kullan�c�, iki d�ng� aras�nda 1 saniye uyumaktad�r. Bu �u demektir: Kullan�c� az ya da �ok her y�z saniyede g�nderme olas�l��� kadar ileti g�nderir. 100'�n, olas�l��� ger�e�e �evirmek i�in yeterli oldu�unu varsay�yoruz.Asl�nda �ok azd�r. Sadece �ok k���k olas�l�k kullanmamaya dikkat edin yoksa sim�lasyonunuz y�llarca �al���r.

if(myrand(100) < send_prob){
  dest = 0;

  /* Anahtara, kendine ve �nceki iletinin al�c�s�na*/
  /* ileti g�nderme*/
  while((dest == 0) || (dest == i) || (dest == olddest)){
    dest = myrand(childs + 1);
  }
  olddest = dest;

  printf("%d -- U %d kullan�c�s�na ileti\n", (int) time(NULL), i, dest);
  child_send_msg(i, dest, 0, sw);
}
Di�er kullan�c�lardan gelen iletiler asl�nda, di�er kullan�c�lar�n anahtara ve onunda bize g�nderdi�i iletilerdir ve TYPE_CONN (ba�lant� olarak) i�retlenmi�lerdir.
/* Basit iletiler i�in gelen kutusunu kontrol et*/
if(child_get_msg(TYPE_CONN, &in)){
  msg_sender = get_sender(&in);
  msg_data = get_data(&in);
  printf("%d -- U %d kullan�c�s�ndan ileti: %d\n",
         (int) time(NULL), i, msg_sender, msg_data);
}
E�er anahtar bir servis isterse, TYPE_SERV i�aretli bir ileti g�ndeririz ve cevap vermek zorunday�z. Ba�lant� kesme servisi durumda, anahtara bir bilgi iletisi g�ndeririz. B�ylece anahtar bizi ula��lamaz yapar ve bize ileti g�ndermeyi denemez. Sonra bir kalan b�t�n iletileri okuruz (nazik olmak i�in s�yledim, bu k�sm� atlayabiliriz), kuyru�u sileriz ve sim�lasyona "G�leg�le" deriz. Anahtara servis iste�i g�nderdi�imiz andaki zaman, o anki zaman� i�eren bir iletidir: Anahtar bu zaman� iletinin g�nderildi�i zamandan ��kar�r ve iletinin ne kadar s�redir kuyrukta bekledi�ini �eteleye yazar. G�rd���n�z gibi burada Qos(Quality of Service- Servis Kalitesi) yap�yoruz, sim�lasyonumuz var olan bir telefon sisteminden daha iyidir.
/* Anahtar�n servis isteyip istemedi�ini kontrol et*/
if(child_get_msg(TYPE_SERV, &in)){
  msg_service = get_service(&in);

  switch(msg_service){
  case SERV_TERM:
    /* �zg�n�z, kapatmak zorunday�z*/
    /* ANahtara bilgi g�nder*/
    child_send_death(i, getpid(), sw);

    /* Kuyruktaki son iletileri oku*/
    while(child_get_msg(TYPE_CONN, &in)){
      msg_sender = get_sender(&in);
      msg_data = get_data(&in);
      printf("%d -- U %d kullan�c�s�ndan ileti: %d\n",
             (int) time(NULL), i, msg_sender, msg_data);
    }

    /* Kuyru�u sil*/
    close_queue(qid);
    printf("%d -- U %d -- Kapatma\n", (int) time(NULL), i);
    exit(0);
    break;
  case SERV_TIME:
    /* ��imiz i�in s�re tutmal�y�z*/
    child_send_time(i, sw);
    printf("%d -- U %d -- S�re\n", (int) time(NULL), i);
    break;
  }
}
 

Anahtar s�recinin uygulamas�

Ana s�re� iki par�aya ayr�lm��t�r: o�ul s�re�lerin olu�turulmas�ndan �ncesi ve sonras�. �lki s�ras�nda, o�ul kuyruk kimliklerinin ve kendi kuyruk kimli�inin saklanmas� i�in bir dizi(array) olu�turur. Bu tip bir i� i�in tabiiki do�ru bir yol de�ildir ama burada dinamik listelerde bahsetek uygun de�ildir ve tamamen yarars�zd�r. Herneyse, Bir �ok say�da ba�lant� kabul edecek olan bir uygulama geli�tirecekseniz, dinamik listeleri ve bellek ayt�rmalar�n� (memmory allocation) kullanmal�s�n�z. uyruk kimlikleri, en ba�ta anahtar�n kuyruk kmli�ine e�itlenir. Bunun anlam� kullan�c�n�n hen�z ba�lanmad���d�r. Kullan�c�n�n her ba�lant�y� kesi�inde, kuyruk kimli�i orjinal de�erine d�ner.

�kinci k�s�mda, ana s�re� bir anahtar olarak g�rev yapar. Kullan�c�n� yapt��� bir d�ng� i�inde b�t�n kullan�c�lar ba�lant�y� kesinceye kadar �al���r. Anahtar, kullan�c�lardan gelen iletileri kontrol eder ve gitmesi gereken yerlere y�nlendirir.

/* Kullan�c�n�n ba�lan�p ba�lanmad���n� kontrol et*/
if(switch_get_msg(TYPE_CONN, &in)){

  msg_receiver = get_receiver(&in);
  msg_sender = get_sender(&in);
  msg_data = get_data(&in);

  /* E�er iletinin g�nderilece�i yer ba�l� ise*/
  if(queues[msg_receiver] != sw){

    /* �letinin g�nderildi�i yere ileti g�nder (gelecek cevab� bekle)*/
    switch_send_msg(msg_sender, msg_data, queues[msg_receiver]);

    printf("%d -- S -- G�nderen: %d -- G�nderilen yer: %d\n",
           (int) time(NULL), msg_sender, msg_receiver);
  }
  else{
    /* E�er iletinin gidece�i yer ba�l� de�ilse*/
    printf("%d -- S -- G�nderilen yere ula��lam�yor (Kullan�c�: %d - G�nderilen yer: %d)\n",
          (int) time(NULL), msg_sender, msg_receiver);
  }
E�er kullan�c�, ahatar arac�l��� ile bir ileti g�nderiyorsa, bu olas�l�k temeline dayanan (daha �nce �al���yor oldu�u gibi) bir servis iste�i nesnesi olabilir. �lk durumda, kullan�c�n�n ba�lant�y� kesmesi i�in zorlar�z, ikincisinde ise bir zaman tutma i�lemine ba�lar�z: �u anki zaman� kaydederiz ve kullan�c�y� i�aretleriz, b�ylece zaten bu i�i yapan kullan�c� i�in zaman tutmu� olmay�z. E�er ileti almazsak, b�y�k ihtimalle b�t�n kullan�c�lar ba�lant�y� kesmi�tir: Bu durumda o�ul s�re�lerin ger�ekten bitmesini bekleriz (belki son o�ul s�re� son iletilerini kontrol ediyordur), kuyru�umuzu sileriz ve ��kar�z.
  /* Son iletiyi g�nderene rastlant�sal olarak servis g�nder*/
  if((myrand(100)  < death_prob) && (queues[msg_sender] != sw)){
    switch(myrand(2))
      {
      case 0:
    /* Kullan�c� ba�lant�y� kesmeli*/
    printf("%d -- S -- %d Ba�lant�y� kesmesi i�in se�ilen kullan�c�\n",
          (int) time(NULL), msg_sender);
    switch_send_term(i, queues[msg_sender]);
    break;
      case 1:
    /* Bu kullan�c� i�in zaman tutup tutmad���m�z� kontrol et*/
    if(!timing[msg_sender][0]){
      timing[msg_sender][0] = 1;
      timing[msg_sender][1] = (int) time(NULL);
      printf("%d -- S -- %d kullan�c� zaman tutmak i�in se�ildi\n",
            timing[msg_sender][1], msg_sender);
      switch_send_time(queues[msg_sender]);
    }
    break;
      }
  }
}
else{
  if(deadproc == childs){
    /* B�t�n o�ul s�re�ler sonland�, son ikisini son i�lerini bitirmeleri i�in bekle*/
    waitpid(pid, &status, 0);

    /* Anahtar�n kuyru�unu sil*/
    remove_queue(sw);

    /* Program� bitir*/
    exit(0);
  }
}
�imdi servis iletilerini bekleriz: kullan�c�n�n do�umu, kullan�c�n�n ba�lant�y� kesmesi ve zaman tutma servisi hakk�nda iletiler alabiliriz.
if(switch_get_msg(TYPE_SERV, &in)){
  msg_service = get_service(&in);
  msg_sender = get_sender(&in);

  switch(msg_service)
    {
    case SERV_BIRTH:
      /* Yeni bir kullan�c� ba�land�*/
      printf("%d -- S -- Kullan�c� %d'nin etkinle�tirilmesi\n", (int) time(NULL), msg_sender);
      break;

    case SERV_DEATH:
      /* Kullan�c� ba�lant�y� kesiyor*/
      printf("%d -- S -- %d kullan�c�s� ba�lant�y� kesiyor\n", (int) time(NULL), msg_sender);

      /* Listeden onun kuyru�unu sil*/
      queues[msg_sender] = sw;

      /* Ka� kullan�c�n�n ba�lant�y� kesti�ini bil*/
      deadproc++;
    break;

    case SERV_QID:
      /* Kullan�c� bize kendi kuyruk kimli�ini g�nderiyor*/
      msg_data = get_data(&in);
      printf("%d -- S -- Kullan�c�s�n�n kuyurk kimli�i : %d\n",
            (int) time(NULL), msg_sender, msg_data);
      queues[msg_sender] = msg_data;
      break;

    case SERV_TIME:
      msg_data = get_data(&in);

      /* Zaman tutma bilgileri*/
      timing[msg_sender][1] = msg_data - timing[msg_sender][1];

      printf("%d -- S -- %d kullan�c�s�n�n zaman tutma i�lemi: %d saniye\n",
            (int) time(NULL), msg_sender, timing[msg_sender][1]);
      /* Kullan�c� art�k zaman tutma i�leminde de�il*/
      timing[msg_sender][0] = 0;
      break;
    }
}
 

Son D���nceler

E�zamanl� programlama ile ilgili k���k makale serimizin sonuna geldik: B�t�n olas� durumlar g�z �n�ne al�mad� anca IPC kelimesinin neleri ifade etti�ini ve ne gibi sornlar� ��zebilece�ini ��rendiniz.Bu makale i�in yazd���m program� de�i�tirmenizi ve geli�tirmenizi tavsiye ederim. S�yledi�im gibi, �ok s�re�li programlar�nhatalar�n� bulmak zordur. Ama hata bulucular(debuggers) hakk�nda daha �ok bilgi edinmeniz i�in iyi bir f�rsatt�r( gdb, programlama s�ras�nda sizin en iyi arkada��n�z olackt�r). Genelde programlama s�ras�nda ilgin� bulaca��n�z programlar� makalenin sonunda bulabilirsiniz.

IPC deneyileri hakk�nda k���k bir �neri. �o�u zaman porgramlar sizin istedi�iniz gibi �al��mayacakt�r ( yukar�daki program� defalarca �al��t� ). Ama programlar� b�ld���n�zde (forking) ctrl-C'ye basmak b�t�n i�elmleri �ld�rmez. Daha �nce kill komutundan bahsetmedim ama kullanma klavuzundan (man page) kolayca anlayabilirsiniz. Program�n�z �ld�r�ld�kten sonra arkas�nda b�rakaca�� birka� �ey var: IPC yap�lar�. Yukar�daki �rnekte, �al��an s�re�leri �ld�r�rseniz, ileti kuyruklar�n� kesinlikle ay�rmalar�n� kald�rmaz (deallocation). B�t�n �ekirdek belle�ini temizlemek i�in ipcs ve ipcrm komutlar�n� kullan�r�z: ipcs o anki b�t�n ayr�lm�� IPC kaynaklar�n� (sadece sizinkini de�il, hepsini. Dikkatli olun) g�sterir. ipcrm bunlardan istediklerinizi kald�rman�za yard�mc� olur. E�er ipcrm komutunu hi�bir arg�man vermeden �al��t�r�rsan�z ihtiyac�n�z olan b�t�n bilgileri size g�sterir: ilk denemede �nerilen say�laer "5 70 70".

Projeyi a�mak i�in "tar xvzf ipcdemo-0.1.tar.gz" komutunu �al��t�r�n. ipcdemo program�n� derlemek i�in sadece "make" komutunu projenin dizini i�inde �al��t�r�n. "make clean" yedekleme dosyalar�n�, "make cleanall" hem yedekleme hem de nesne dosyalar�n� siler.

 

Sonu�

Bu makalenin ge� yay�nlanmas�ndan dolay� hepinizden �z�r diliyorum. Yaz�l�m geli�tirme hayattaki tek �ey de�il. Her zaman oldu�u gibi ilerideki makaleler ve makale konular� i�in sizden yaorumlar bekliyorum: "thread"ler ?  

�nerilen programlar, siteler ve yaz�lar

Tavsiye edilen kitaplar i�in eski makalelere bak�n. Bu defa size programlama, hata ay�klama (debugging) ve g�zerl yaz�larla ilgili baz� internet adresleri verece�im.

Hata ay�klay�c�lar (debuggers), geli�tiricinin en iyi arkada�lar�d�r, en az�ndan geli�tirme s�ras�nda. ddd'den �nce gdb'nin nas�l kullan�ld���n� ��renin. ��nk� grafiksel ara�lar g�zeldir ama gerekli de�ildir.

"Segmentation fault" iletisi ald�n�z ve nerede hata yapt���n�z� m� merak ediyorsunuz. At�lm�� bir �ekirdek (core) dosyas�n� gdb ile okumaya ek olarak, valgrind ile program� �al��t�r�p onun bellek sim�lasyonu �er�evei�i (framework) �zelli�inden faydalanabilirsiniz.

Farketti�iniz gibi C'de IPC program� yazmank e�lencelidir ama karma��kt�r. Python bir ��z�md�r: S�re� b�lme (forking) ve di�er i�ler i�in tam deste�i vard�r ve C geni�lemesi vard�r. Bir bak�n, buna de�er.

 

Program �ndirme

 

Bu yaz� i�in g�r�� bildiriminde bulunabilirsiniz

Her yaz� kendi g�r�� bildirim sayfas�na sahiptir. Bu sayfaya yorumlar�n�z� yazabilir ve di�er okuyucular�n yorumlar�na bakabilirsiniz.
 talkback page 

<--, Bu say�n�n ana sayfas�na gider

G�rsely�re sayfalar�n�n bak�m�, LinuxFocus Edit�rleri taraf�ndan yap�lmaktad�r
© Leonardo Giordani, FDL
LinuxFocus.org
�eviri bilgisi:
en --> -- : Leonardo Giordani <leo.giordani(at)libero.it>
en --> tr: �zcan G�ng�r <ozcangungor(at)netscape.net>

2003-12-22, generated by lfparser version 2.43