İŞLETİM SİSTEMLERİ (POSIX THREADS v1)

Benzer belgeler
İşletim Sistemleri-II

Multicore/Multithread Programlama

Proses. Prosesler 2. İşletim Sistemleri

PROSESLER. Proses. Proses

Struct VE GÖSTERİCİLER FONKSİYONLARDA STRUCT KULLANIMI Programlama dilleri hafta -

İşletim Sistemlerine Giriş

Süreç 1 Kavramı ve Oluşturma Yöntemleri

PROGRAMLAMAYA GİRİŞ FONKSİYONLAR

YZM 3102 İşletim Sistemleri

BLM 112- Programlama Dilleri II. Hafta 2 C Programlarının Bellek Düzeni ve Rekürsif (Özyinelemeli) Fonksiyonlar

BMB1002 Bilgisayar Programlamaya Giriş. Dosyalar. Prof. Dr. Necmettin Kaya

Windows'da çalışırken pek çok durumda bir işe başlamadan önce işletim sisteminin o işe ilişkin bilgileri depolayacağı bir alan yaratması gerekir.

FONKSİYONLAR. Gerçek hayattaki problemlerin çözümü için geliştirilen programlar çok büyük boyutlardadır.

Bil101 Bilgisayar Yazılımı I. M. Erdem ÇORAPÇIOĞLU Bilgisayar Yüksek Mühendisi

Örnek: İki fonksiyondan oluşan bir program. Fonksiyon Tanımı

Bölüm 4: İş Parçacıkları. Operating System Concepts with Java 8 th Edition

İş Parçacıkları Thread(s)

Sınav tarihi : Süre : 60 dak. a) strstr b) strchr c) strcat d) strcpy e) strlen. a) b) d) e) 0

10. DOSYA GİRİŞ ÇIKIŞ FONKSİYONLARI

Bölüm 5: İşlemci Zamanlaması. Operating System Concepts with Java 8 th Edition

İşletim Sistemleri. Dr. Binnur Kurt Omega Eğitim ve Danışmanlık İşletim Sistemleri

Yrd. Doç. Dr. Caner ÖZCAN

MAK 1005 Bilgisayar Programlamaya Giriş. Fonksiyonlar. Prof. Dr. Necmettin Kaya

İşletim Sistemleri. Hazırlayan: M. Ali Akcayol Gazi Üniversitesi Bilgisayar Mühendisliği Bölümü

Sınav tarihi : Süre : 60 dak.

ELN1001 BİLGİSAYAR PROGRAMLAMA I

Fonksiyonlar. C++ ve NESNEYE DAYALI PROGRAMLAMA 51. /* Fonksiyon: kup Bir tamsayının küpünü hesaplar */ long int kup(int x) {

8. İŞARETCİLER (POINTERS)

Yrd. Doç. Dr. Caner ÖZCAN

Diziler (Arrays) Çok Boyutlu Diziler

Bölüm 3: İşlemler Operating System Concepts with Java 8th Edition 3.1 Silberschatz, Galvin and Gagne 2009

Bölüm 3: İşlemler Operating System Concepts with Java 8th Edition 3.1 Silberschatz, Galvin and Gagne 2009

BLM-112 PROGRAMLAMA DİLLERİ II. Ders-3 İşaretçiler (Pointer) (Kısım-2)

BASİT C PROGRAMLARI Öğr.Gör.Dr. Mahmut YALÇIN

Hafta 13 Fonksiyonlar

İşletim Sistemleri (Operating Systems)

Diziler. Yrd.Doç.Dr.Bülent ÇOBANOĞLU

BİL-142 Bilgisayar Programlama II

10/17/2007 Nesneye Yonelik Programlama 3.1

1 PROGRAMLAMAYA GİRİŞ

NESNEYE YÖNELİK PROGRAMLAMA

/ C Bilgisayar Programlama Final Sınavı Test Soruları. Adı soyadı :... Öğrenci no :... İmza :... Tarih, Süre : , 60 dak.

PROCESS YARATIMI (TEKRAR):

Metin Dosyaları. Metin Dosyaları Dosya Açma ve Kapama Dosya Okuma ve Yazma Rastgele Erişim Standart Girdi/Çıktı Hata Kontrolü

BMT 101 Algoritma ve Programlama I 11. Hafta. Yük. Müh. Köksal Gündoğdu 1

İşletim Sistemleri. Dr. Binnur Kurt Omega Eğitim ve Danışmanlık İşletim Sistemleri

PROGRAMLAMAYA GİRİŞ DERS 2

C++ Dersi: Nesne Tabanlı Programlama

BLM 112- Programlama Dilleri II. Hafta 5 İşaretçiler (Pointers)

else *on=*on+1; return gecici; } int giseyeyerlestir(struct gise*giseler) {//giseye bos olmasi durumunda yerlestirme yapiliyor...

Çoktan Seçmeli Değerlendirme Soruları Akış Şemaları İle Algoritma Geliştirme Örnekleri Giriş 39 1.Gündelik Hayattan Algoritma Örnekleri 39 2.Say

DOSYA İŞLEMLERİ Programlama dilleri hafta -

BİLGİSAYAR TEMELLERİ VE PROGRAMLAMAYA GİRİŞ

Bölüm 9. Altprogramlar ISBN

Deney 7: Fonksiyon Tanımlama ve Parametre Aktarım Yöntemleri

Bölüm 4: Threads (İş Parçaları)

DERS 3 MİKROİŞLEMCİ SİSTEM MİMARİSİ. İçerik

mod ile açılacak olan dosyanın ne amaçla açılacağı belirlenir. Bunlar:

Giris {\} /\ Suhap SAHIN Onur GÖK

Algoritma ve Programlama II Recursive Fonksiyonlar Dosyalama

YAPILAR BİRLİKLER SAYMA SABİTLERİ/KÜMELERİ. 3. Hafta

Bil 101 Bilgisayar Yazılımı 1 Çözümlü Sorular Timur Karaçay

ENF102 TEMEL BİLGİSAYAR BİLİMLERİ VE C/ C++ PROGRAMLAMA DİLİ. Gazi Üniversitesi Mühendislik Fakültesi Bilgisayar Mühendisliği Bölümü

KOCAELİ ÜNİVERSİTESİ MÜHENDİSLİK FAKÜLTESİ

Prosesler Arası Haberleşme ve Senkronizasyon

2) /* Kullanıcıdan alınan iki sayının obebini alt fonksiyon yardımı ile hesaplayan C programı*/

Arasınav Sınavı Soruları Güz 2017 Süre: 90 Dakika

Temel Giriş/Çıkış Fonksiyonları

Giriş. İplik Modeli. geleneksel işletim sistemlerinde her prosesin özel adres uzayı ve tek akış kontrolü var.

Adı soyadı :... Öğrenci no :... İmza :... Tarih, Süre : dak.

Dr. Fatih AY Tel: fatihay@fatihay.net

Göstericiler (Pointers)

BLM-111 PROGRAMLAMA DİLLERİ I. Ders-12 Fonksiyonlar. Yrd. Doç. Dr. Ümit ATİLA

INTEGER OVERFLOW ***************************************************************/

NESNE TABANLI PROGRAMLAMA Final Sınavı Cevapları

Final Sınavı Soruları Güz, Süre: 90 Dakika

Nesne tabanlı programlama nesneleri kullanan programlamayı içerir. Bir nesne farklı olarak tanımlanabilen gerçek dünyadaki bir varlıktır.

Temel Bilgisayar Bilimleri Ders Notu #4-2. kısım

Hafta 11 Çok Boyutlu Diziler

Bilgisayar İşletim Sistemleri BLG 312

C Programlama Dilininin Basit Yapıları

Sınav tarihi : Süre : 60 dak. c) En başta #include<stdio.h> yazılmamıştır. c) zt d) Pi e) X0

BLM111 Programlama Dilleri I. Hafta 10 Diziler. Yrd. Doç. Dr. Caner ÖZCAN

Linux'ta Kabuk ve Kabuk Programlama

Giriş. geleneksel işletim sistemlerinde her prosesin. aynı adres uzayında birden fazla akış kontrolü gerekebilir

İstanbul Teknik Üniversitesi IEEE Öğrenci Kolu DİZİLER

İŞLETİM SİSTEMLERİ DÖNEMİÇİ SINAVI

Temel Dosya İşlemleri. Kütük Organizasyonu 1

NB Ekran Seri Port Üzerinden Veri Okuma/Yazma. Genel Bilgi Protokol Oluşturma Veri Okuma Veri Yazma

Uzaktan Eğitim Uygulama ve Araştırma Merkezi

Uzaktan Eğitim Uygulama ve Araştırma Merkezi

C PROGRAMLAMA D İ L İ

sayi=3 harf=a reelsayi=8.72 Bellek durumu 5. İşaretç iler (pointers)

Linux Assembly Programlamaya Giriş

LPC2104 Mikro Denetleyicisini KEIL İle Programlamak

Yazılım Kodlama ve İ simlendirme Standartları v1.0

KOCAELİ ÜNİVERSİTESİ BİLGİSAYAR MÜHENDİSLİĞİ. BİLGİSAYAR LABORATUVARI II FİNAL SINAVI SORU ve CEVAPLARI(I. ogr)

ÇOK BOYUTLU DİZİLER VE DİNAMİK BELLEK YÖNETİMİ İLE İLGİLİ ÖRNEKLER

Sunum İçeriği. Programlamaya Giriş

VERİ YAPILARI DERS NOTLARI BÖLÜM 5 QUEUE (KUYRUK) Yard. Doç. Dr. Deniz KILINÇ

Transkript:

YILDIZ TEKNİK ÜNİVERSİTESİ BİLGİSAYAR MÜHENDİSLİĞİ İŞLETİM SİSTEMLERİ (POSIX THREADS v1) ARŞ. GRV. UĞUR ÇEKMEZ

Multi Thread Programlama Thread Çalışma Mantığı Basit manada threadler, bir prosesin içinde var olan ve işle:m sistemi tara;ndan o prosesin kendi işleyişinden bağımsız olarak çalış?rılabilen ayrık kod parçalarıdır. Threadler için ayrık kelimesini karşılayan faktörler aşağıdaki şekilde sıralanabilir: - Stack pointer, register, schedule, thread specific data Sıralanan faktörler, her bir threadin kendi kontrolünde işlenmektedir. Threadlerin parent prosesleri var olduğu müddetçe kendilerinin de bir kontrol akışı vardır ve yalnızca (temel manada) hayama kalabilmek için gereksinim duydukları kaynakları parent proseslerinden kopyalarlar. Parent proses sonlandığında, onun al?nda çalış?rılan tüm threadler de sonlanır. Threadler, kaynaklarını aynı proses al?nda oluşturulan diğer bağımsız (veya bağımlı) threadler ile paylaşabilirler. Bu demek oluyor ki bir threadin paylaşılan değişkenler üzerindeki hareketleri doğrudan veya dolaylı yoldan diğer threadleri etkileyebilir ve aynı proses içindeki threadler bu değişikliklerden haberdar olurlar. Aynı kaynağa erişebilen threadlerin ilgili kaynak üzerinde aynı anda erişim gereksinimleri doğabilir. Örneğin bir thread t anında F dosyasının sa?rlarını okumak isterken, başka bir thread bu dosyaya hali hazırda veri girmekte olabilir. Thread dizaynı yapılırken, paylaşılan kaynaklar için belirli kri:k noktalar senkronize edilip paylaşım problemlerinin önüne geçilebilir. Bu dokümanın ilerleyen örneklerinde bu tarz problemlere değineceğiz. (POSIX thread yapısı, IEEE POSIX standartlarına göre belirlenmektedir)

Proses vs. Thread Thread man?ğının işlenmesine geçilmeden, öncelikle UNIX proses yapısının anlaşılması fayda sağlayacak?r. Bir proses, gelen komutlarla birlikte işle:m sistemi vasıtasıyla oluşturulur ve bir prosesin oluşturulması için belli bir sistem kaynağı tahsis edilir. Bunun da sisteme belli bir yükü vardır. Prosesler özet olarak aşağıdaki kaynaklara sahip:rler: - Proses ID, grup ID, user ID, çalışılan dizin, program komutları, register, stack, heap, diğer proseslerle mesajlaşma araçları vs. Bir prosesin oluşturulması ve yöne:lmesi ile aynı işlemlerin thread ayağı kıyaslandığında, thread oluşturma, işleme ve sonlandırma yükü çok daha hafizir. Threadler yukarıda belir:len proseslerin içerisinde çalışırlar. Thread modelleri Manager / Worker : Yöne:ci (manager) thread, diğer (worker) threadlere iş paslar. İşin bölümlenmesi ve dağı?lması yöne:ciye ai`r. Bu dağı?m sta:k veya dinamik şekilde yapılabilir. Pipeline : Bir görev alt görevlere bölünür ve bu alt görevlerden paralel olarak çalışması mümkün olanların her biri farklı bir thread tara;ndan yürütülür. Peer : Manager/Worker ile benzer yapıda olup diğerinden farkı, yöne:ci threadin de görev bölümleme haricinde işin içine girmesidir. Pthread API POSIX threadleri kullanabileceğimiz API, aşağıdaki 4 temel kategoride incelenebilir: Thread management : Bu kategoride threadler üzerinde yapılan işlemler ele alınır. Thread oluşumu, görev atanması, işleme geçilmesi vs. Mutex : Senkronizasyonla ilgili konuları kapsayan kategoridir. Mutex işlemleri, bunları oluşturma, sonlandırma, kilitleme ve kilitlenmiş mutexleri açma olarak tanımlanabilir. Condi:on variables : Mutex leri paylaşan threadler arasındaki ile:şimi kapsayan kategoridir. Programı yazan geliş:riciye bağlıdır. Mutexleri paylaşan threadlerin bu mutexleri kullanması, diğer threadlerin bekle:lmesi ve paylaşılan değişkenlerden ilgili threadlerin çıkarılması gibi işlemler yapılır. Synchroniza:on : Okuma ve yazma kilitlerini ve bariyerlerin oluşumunu kapsayan kategoridir.

Thread Management C programı çalış?rıldığında, varsayılan olarak birinci oluşturulan thread, programın main(..) fonksiyonudur. Diğer threadlerin tümü el ile oluşturulabilir. pthread_create(..) fonksiyonu ile yeni bir thread oluşturup bu thread çalış?rılabilir hale ge:rilir. Oluşturulmak istenen her bir thread için bu fonksiyon kullanılabilir. Fonksiyonun alacağı parametreler aşağıdaki şekildedir: - thread : thread için önceden tanımlanmış bir adres (değişken adresi) - amr : thread için verilebilecek diğer parametreler. Bir object değeri verilebilir. Yok ise NULL verilir. - start_rou:ne : thread oluşturulduğunda ilk çalış?racağı fonksiyon - arg : start_rou0ne fonksiyonuna verilecek parametre Bir programın oluşturabileceği maksimum (limitlenmiş) bir thread sayısı vardır. İlgili limitler işle:m sistemi tara;ndan sistem kaynaklarına göre belirlenir. Bundan daha fazla thread oluşturulmak istenirse program tara;ndan hata üre:lebilir. Burada sistem kaynakları, ilgili threadlerin paylaş?ğı sistem kaynaklarıdır (örneğin bir prosesin sahip olduğu stack alanı gibi.) ulimit -a Maximum size of core files created (kb, -c) 0 Maximum size of a process s data segment (kb, -d) unlimited Maximum size of files created by the shell (kb, -f) unlimited Maximum size that may be locked into memory (kb, -l) unlimited Maximum resident set size (kb, -m) unlimited Maximum number of open file descriptors (-n) 256 Maximum stack siz (kb, -s) 8192 Maximum amount of cpu time in seconds (seconds, -t) unlimited Maximum number of processes available to a single user (-u) 709 Maximum amount of virtual memory available to the shell (kb, -v) unlimited Sarı renk ile çizilmiş alan bir kullanıcının bir proseste kullanabileceği maksimum stack boyutunu verir. Prosesler içinde oluşturulan threadler de bunu paylaşırlar. Dolayısı ile toplamda üre:lebilecek thread sayısı için yaklaşık olarak: sistemin sahip olduğu bellek / stack boyutuna karşılık gelir diyebiliriz Threadler, oluşturulduktan sonra ar?k başka threadleri de oluşturabilirler.

Oluşturulan threadler, aşağıda anla?lan durumlarda sonlandırılabilir: - Thread normal döngüsü içinde kendisine atanan görevi tamamladığında - Thread pthread_exit(..) fonksiyonunu çağırdığında (görev tamamlanmasa bile çağırabilir) - Thread, başka bir thread tara;ndan pthread_cancel(..) fonksiyonu ile kesildiğinde - Threadin içinde bulunduğu parent proses herhangi bir şekilde sonlandırıldığında (Örneğin exit() ile) - main() fonksiyonu pthread_exit(..) fonksiyonunu çağırmadan sonlandığında (Eğer thread herhangi bir dosyayı düzenlemek için aç?ysa ve henüz kapatmadıysa, thread sonlandırıldığında da bu dosya açık kalabilir) Örnek bir thread oluşturma, işleme ve sonlandırma uygulaması aşağıdaki şekilde özetlenmiş:r: #include <pthread.h> #include <stdio.h> #include <stdlib.h> #define THREAD_SAYISI 5 void * giris_fonksiyonu(void * thread_id) { printf("merhaba, ben %ld. thread\n", (long)thread_id); pthread_exit(null); int main () { pthread_t threads[thread_sayisi]; int donus_degeri; long i; for(i=0; i<thread_sayisi; i++){ printf(" %ld. thread olusturuluyor...\n", i); donus_degeri = pthread_create(&threads[i], NULL, giris_fonksiyonu, (void *)i); if (donus_degeri){ printf("hata : %d\n", donus_degeri); exit(-1); pthread_exit(null);

Threadler arası senkronizasyon için pthread_join(..) fonksiyonu kullanılır. pthread_join(..) fonksiyonuna parametre olarak ilgili threadin ID si verilir ve bu thread bitene kadar ilgili komut satırı bekleme moduna geçer. Thread sonlandıktan sonra, join fonksiyonunu çağıran thread normal işleyişine döner. Sonlanan thread in bitiş durumunu görmek için, ilgili thread in pthread_exit(..) çıkış fonksiyonuna parametre olarak status değeri verilir ve bu değer join fonksiyonunun dönüş değeri olarak alınabilir. Bir join fonksiyonu yalnızca bir thread ile ilişkilendirilebilir. Her bir thread için ayrı ayrı join çağrımı yapılmalıdır. - pthread_self(..) fonksiyonu, içinde çağrıldığı threadin sistem tarafından atanmış olan ID sini döndürür. - pthread_equals(t_id1, T_ID2) fonksiyonu, ID leri verilmiş iki threadin aynı olup olmadığını kontrol eder. Threadler farklı ise 0, aynı ise farklı bir değer döndürür.

Aşağıda örnek bir join işlemi vardır: #include <pthread.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> #define THREAD_SAYISI 10 void * giris_fonksiyonu(void * thread_id) { int rastgele_sayi = rand() % 4; sleep(rastgele_sayi); printf("merhaba, ben %ld. thread\n", (long)thread_id); pthread_exit(null); int main () { srand(time(null)); pthread_t threadler[thread_sayisi]; int donus_degeri; long i; for(i=0; i<thread_sayisi; i++){ printf(" %ld. thread olusturuluyor...\n", i); donus_degeri = pthread_create(&threadler[i], NULL, giris_fonksiyonu, (void *)i); if (donus_degeri){ printf("hata : %d\n", donus_degeri); exit(-1); // tum threadler bitene kadar bekle for(i=0; i<thread_sayisi;i++) { donus_degeri = pthread_join(threadler[i], NULL); if (donus_degeri){ printf("hata : %d. threadde bir sorun oldu\n", donus_degeri); exit(-1);

Mutex Mutex değişkeni, paylaşılan bir veri kaynağını kilitleyerek erişimi koruma amacıyla kullanılır. Posix thread lerde bu manadaki temel mantık, anlık olarak yalnızca bir thread in bir mutex değişkenini kilitleyebilmesi üzerinedir. Bu demek oluyor ki, atomik seviyede düşünülebilecek bir işlem olan mutex değişkenini kilitlemeyi, ortamda birden fazla thread bulunsa bile yalnızca biri başarıp bu değişkene sahip olabilecektir. Kilitlenmiş bir mutex değişkenini, ancak onu kilitleyen thread tekrar açabilir ve diğer threadlerin ona erişebilmelerine izin verebilir. Mutex değişkenleri, pthread_mutex_init(mutex, a@r), pthread_mutex_destroy(mutex) komutlarıyla oluşturulup kaldırılabilirler. Mutex değişkenleri, pthread_mutex_lock(mutex), pthread_mutex_trylock(mutex) pthread_mutex_unlock(mutex) komutlarıyla kilitlenirler ve kilitleri açılabilir. ve Birden fazla thread, kilitlenmiş bir mutex değişkeni için bekleme yapıyorsa, hangi thread in mutex değişkeninin kilidi açıldığında ona erişeceği, eğer sistemde bir priority scheduling yapısı tanımlanmadıysa, çoğunlukla rastgele bir yapıda işletim sistemi tarafından belirlenir. Mutex değişkenlerinin kullanıldığı bir örnek aşağıdaki şekildedir #include <pthread.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> #define THREAD_SAYISI 10 void * giris_fonksiyonu(void * thread_id) { pthread_mutex_lock(&lock); sleep(rand()%5); int i; sayac += 1; printf("%d. islem basladi...\n",sayac); for(i=0; i<(0xfffff);i++); printf("%d. islem bitti...\n",sayac); pthread_mutex_unlock(&lock); pthread_exit(null); int main() { pthread_t threadler[thread_sayisi]; // threadlerimize yer aciyoruz pthread_mutex_init(&lock,null); // muteximizi olusturuyoruz long i,donus_degeri; srand(time(null)); for(i=0; i<thread_sayisi; i++){ donus_degeri = pthread_create(&threadler[i], NULL, giris_fonksiyonu, (void *)i); if (donus_degeri){ printf("hata : %ld\n", donus_degeri); exit(-1); pthread_mutex_destroy(&m); return 0;

Condition Variables Bu yapı, threadlerin senkron bir halde çalışabilmesi için bir başka yoldur. Mutex değişkenleri ile bir threadin veriye erişip erişemeyeceğini kontrol edebilirken, CV ile threadlerin bir verinin güncel durumundaki değişikliğe göre o veriye erişip erişemeyeceğini kontrol edebiliriz. CV yardımıyla program geliştiricinin, örneğin bir sayaç değişkeninin değerinin sıfırdan büyük olup olmadığını elle kontrol etmesine gerek kalmamaktadır. Bu da hem yazılımın karmaşıklığı hem de sürekli manüel kontroller yaparak sistem kaynaklarını harcamasının önüne geçmektedir. Koşul değişkenleri, pthread_cond_init(cond,a@r), pthread_cond_destroy(cond), pthread_conda@r_init(a@r) ve pthread_conda@r_destroy(a@r) fonksiyonları ile oluşturulup kaldırılabilirler. Threadlerin belli şartlar sağlanana kadar paylaşılan kaynaklara erişiminin kısıtlanması ise pthread_cond_wait(cond, mutex), pthread_cond_signam(cond) ve pthread_cond_broadcast(cond) fonksiyonları ile tanımlanır. Örnek bir kod aşağıdaki şekildedir. #include <stdio.h> #include <stdlib.h> #include <pthread.h> pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t c = PTHREAD_COND_INITIALIZER; int sayac = 0, aralik1 = 3, aralik2 = 6; void * f1() { while(1) { pthread_mutex_lock(&m); // mutexi kilitle pthread_cond_wait(&c,&m); // f2 calisirken bekle, sinyal gönderecek sayac++; printf("f1 : %d\n", sayac); pthread_mutex_unlock(&m); // mutexi kilidini aç if(sayac >= 10) return(null); void * f2() { while(1) { pthread_mutex_lock(&m); if (sayac < aralik1 sayac > aralik2) { pthread_cond_signal(&c); else { sayac++; printf("**f2 : %d\n", sayac); pthread_mutex_unlock(&m); if(sayac >= 10) return(null); int main() { pthread_t t1, t2; pthread_create(&t1, NULL, &f1, NULL); pthread_create(&t2, NULL, &f2, NULL); pthread_join(t1, NULL); pthread_join(t2, NULL); printf("sayacin son durumu : %d\n", sayac); return 0;