19 Nisan 2017 Çarşamba

Posix Threadleri

Giriş
Posix threadlerini kullanmak için şu dosya gerekir
#include <pthread.h>
pthread kütüphanesi ile linklemek için -pthread seçeneği kullanılır. Bu kısım hep karışıyor çünkü
-lpthread şeklinde kullanmaya ve düşünmeye alışkınız. Yani şöyle yaparız.

gcc -Wall -g main.c -pthread -o a.out

gcc man sayfasında şöyle yazıyor.
-pthread Adds support for multithreading with the pthreads library. This option sets flags for both the preprocessor and linker.
getcontext setcontext vs.
POSIX threadlerinden önce getcontextsetcontext gibi metodlar varmış. Ancak bu metodlar artık kullanılmıyorlar.

Thread Sınıfı
Bütün thread'ler şu sınıf tipinden tutulur.
pthread_t thread;
pthread_create metodu
pthread_create metodu yazısına taşıdım.

pthread_attr_setdetachedstate metodu
Bu metod ile thread başlatılırken detached başlaması belirtilir.

Detached Thread
Eğer bir thread detach edilmez ise, yani joinable yaratılırsa, threadin exit kodunun okunması gerekir. Aksi halde resource leak oluşacaktır.

Detached thread yaratmak için iki yöntem var. İlki thread'i direkt detached olarak başlatmak.
Bu iş için thread attribute alanına PTHREAD_CREATE_DETACHED atanıyor.
Örnek:

İkincisi ise pthread_detach ile thread başladıktan sonra ayırmak. Örnek:
pthread_detach( pthread_self() );

pthread_join metodu
pthread_join metodu yazısına taşıdım.

pthread_self metodu
thread içinde kendi kendine erişimi sağlar.

Örnek
Linux'ta pthread_t unsigned int olarak tanımlandığı için şöyle print edilebilir.
printf("%u\n", (unsigned int) pthread_self());
Örnek
Şöyle yaparız.
int main()
{
  pthread_t t = pthread_self();
  std::cout << t << std::endl;
  return 0;
}
Metod C kütüphanesinde tanımlı. Eğer pthread kütüphanesi ile linklemezse çıktı olarak şunu alırız.
0
Eğer pthread ile linklersek
g++ test.c -o test -lpthread; ./test
Çıktı olarak şunu alırız.
139675118393152
Açıklaması şöyle
More or less it is as follows: first, as pthread_self() is implemented in the standard C library, it doesn't need to be linked to be linked against -lpthreads.

Now, pthread_self() uses a global variable, a pointer to a TCB (thread control block), to store the thread information, including the ID (unique within the process).

This pointer is initialized to NULL (0), but Pthreads library (when linked) changes it so it now points to current thread header structure.

That's why you get a 0 when not linking with Pthreads and the actual POSIX thread ID when you do.
Thread ve PID
getpid metodu yazısına taşıdım.

pthread_exit
Eğer bir thread işi bittikten sonra çıkmak isterse pthread_exit metodunu çağırır.
pthread_exit(NULL); şeklinde çağırılabilir. Eğer thred'den çıkmak için pthread_exit() yerine exit() metodunu çağırırsak tüm uygulamanın sonlandığını görürüz.

pthread_cancel
Metodun imzası şöyle
int pthread_cancel(pthread_t thread);
Normalde bir thread cancellation point'lerden birisini çağırırsa iptal olur. Yani thread PTHREAD_CANCEL_DEFERRED ile yatatılmıştır. Thread kodunda pthread_testcancel() çağrısı ile de kendimizde iptal edilip edilmediğimizi test edebiliriz. Ancak eğer istenirse thread asenkron iptal edilir hale de getirilebilir.

pthread_setcancelstate ve pthread_setcanceltype
Sadece pure processing yapan thread'ler için kullanılmalı. pthread_setcanceltype ile thread PTHREAD_CANCEL_ASYNCHRONOUS haline sokulur.

Örnek:
void* myThread(void *)
{
    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
    //...Do work
}
Daha sonra iptal etmek için :

pthread_t thread;
pthread_attr_t attribute;

pthread_attr_init(&attribute);
pthread_attr_setdetachstate(&attribute, PTHREAD_CREATE_DETACHED);

pthread_create(&thread, &attribute, myThread, NULL);

pthread_cancel(thread);
pthread_mutex_lock ve iptal etme
Burada sorulduğu gibi pthread_mutex_lock() ile beklemekte olan bir thread iptal edilemez.

pthread_cleanup_push ve pthread_cleanup_pop
Eğer bir thread iptal edilirse, iptal işleminin ardından temizleme işlevini görecek metodları belirtmek için kullanılır.

pthread_kill
Bir başka thread'i öldürmek için kullanılır.

pthread_setname
pthread_setname_np metodu yazısına taşıdım.

Thread Önceliği
Thread başladıktan sonra pthread_setschedparam(...) ile threadin önceliği değiştirilebilir.
Örnek:
pthread_t thread;

struct sched_param param;
int sched = SCHED_FIFO;
memset(&param, 0, sizeof(sched_param));

// Now I set priority to max value (sched_get_priority_max() returns that value)
param.sched_priority = sched_get_priority_max();

// Create my thread
pthread_create(&thread, NULL, (void *) &hard_number_crunching, (void *) &structure_passed_to_thread);

// finally I set parameters to thread
pthread_setschedparam(&thread, sched, &param);

Bir başka örnek ise burada. pthread_attr_setschedparam ile thread yaratılırken önceliği veriliyor.

pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
pthread_attr_setschedpolicy(&attr, SCHED_FIFO);

struct sched_param param;
pthread_attr_getschedparam(&attr, &param);
param.sched_priority = 10;
pthread_attr_setschedparam(&attr, &param);

pthread_t thread;
pthread_create(&thread, &attr, ThreadFunction, NULL);


Thread Local Storage
Konuyu Thread Local Storage yazısına taşıdım.

Hiç yorum yok:

Yorum Gönder