Semafor Operasyonları

Semaforları, işaretsiz integer değerler olarak düşünebiliriz.

Bir semafor üzerinde, artırma ve azaltma yönünde iki temel operasyon gerçekleştirilebilir.

Operasyonel Semafor Fonksiyonları

sem_wait

  • Semaforun değerini 1 azaltmak için kullanılır.

  • Eğer ilgili semafor değeri 1'den büyükse azaltma işlemi anında gerçekleştirilir ve fonksiyon geri döner.

  • Semafor değeri zaten 0'a eşitse, sem_wait fonksiyonu, semaforun değerinin 1 artmasını bekler. Artış olduğunda hemen tekrar 0'a çeker ve fonksiyon geri döner.

  • Yukarıdaki bloklanmış bekleme durumunda bir sinyal yakalanması halinde, sinyale ilişkin SA_RESTART bayrağının ayarlanmış olup olmamasından bağımsız olarak, EINTR hatasıyla fonksiyondan çıkılır.

Örnek: Semafor Bekleme

/* sem_wait.c */
#include <semaphore.h>
#include "common.h"

int main(int argc, char *argv[])
{
    sem_t *sem;
    if (argc < 2 || strcmp(argv[1], "--help") == 0)
        usageErr("%s sem-name\n", argv[0]);
    sem = sem_open(argv[1], 0);
    if (sem == SEM_FAILED)
        errExit("sem_open");
    if (sem_wait(sem) == -1)
        errExit("sem_wait");
    printf("%ld sem_wait() succeeded\n", (long) getpid());
    exit(EXIT_SUCCESS);
}

sem_trywait ve sem_timedwait

  • Semafor bekleme operasyonu bir sinyal gelmediği müddetçe işlem gerçekleşene kadar çağıran süreci bloklamaktadır.

  • Bloklama yapması istenmediği durumda, sem_trywait kullanılabilir. Bu modelde eğer semafor değeri 1 ise azaltılıp başarılı döner, ancak değer zaten 0 ise bloklama yapılmaz ve EAGAIN hatası ile dönülür.

  • Bekleme işlemi için maksimum zaman aralığını seçmek istersek, sem_timedwait fonksiyonunu kullanabiliriz. Bu durumda semafor değeri hemen azaltılamıyorsa, maksimum olarak verilen parametre süresi kadar bekleyecektir. Bu süre zarfında da işlemin gerçekleşmemesi halinde ETIMEDOUT hatası ile döner.

sem_post

  • Semaforun değerini 1 artırmak için kullanılır.

  • Eğer semaforun değeri zaten 0 ise ve başka bir süreç aynı semaforu beklediği için bloklanmış durumdaysa, ilgili süreç uyandırılır.

  • Yukarıdaki durumda birden fazla sürecin aynı semaforu beklerken bloklanması sözkonusu olursa, hangi sürecin uyandırılacağı garanti edilemez.

Örnek: Semafor Değerini Artırma

/* sem_post.c */
#include <semaphore.h>
#include "common.h"

int main(int argc, char *argv[])
{
    sem_t *sem;
    if (argc != 2)
        usageErr("%s sem-name\n", argv[0]);

    sem = sem_open(argv[1], 0);
    if (sem == SEM_FAILED)
        errExit("sem_open");

    if (sem_post(sem) == -1)
        errExit("sem_post");

    exit(EXIT_SUCCESS);
}

sem_getvalue

  • Mevcut bir semaforun o anki değerini almak için kullanılır.

Örnek

/* sem_get.c */
#include <semaphore.h>
#include "common.h"

int main(int argc, char *argv[])
{
    int value;
    sem_t *sem;
    if (argc != 2)
        usageErr("%s sem-name\n", argv[0]);

    sem = sem_open(argv[1], 0);

    if (sem == SEM_FAILED)
        errExit("sem_open");

    if (sem_getvalue(sem, &value) == -1)
        errExit("sem_getvalue");

    printf("%d\n", value);
    exit(EXIT_SUCCESS);
}

İsimsiz Semaforlar

  • İsimsiz semaforlar, ortak bir bellek alanına erişimin mümkün olduğu tüm senaryolarda kullanılabilir.

  • İsimlendirilmiş semaforlardaki fonksiyonlar aynen kullanılabilir.

  • Bu fonksiyonlara ek olarak isimsize semaforlarda sem_init ve sem_destroy fonksiyonları da kullanılmaktadır.

sem_init

  • İlgili semaforun ilklendirilmesi işlemlerini gerçekleştirir.

  • Fonksiyonun 2. parametresi olan pshared değeri 0 olduğu takdirde, semafor sadece aynı sürecin thread'leri içerisinde kullanılabilir. Bu nedenle shared memory kullanımına gerek kalmadan, global bir değişkende veya heap üzerinde ayrılan bir alanda tutulabilir.

  • pshared değeri 0'dan farklı olursa, semafor farklı süreçler arasında kullanılabilir. Bu durumda 1. parametredeki adres, shared memory üzerindeki bir yeri göstermelidir.

  • Bu fonksiyonun aynı semafor için birden fazla çağrılması durumunda sistem kararlı davranamaz. Bu nedenle, her semaforun sadece bir defa ilklendirilmesi garanti edilmelidir.


sem_destroy

  • İsimsiz bir semaforun sonlandırılmasını sağlar.

  • Semafor sonlandırılmadan, tutulduğu bellek bölgesi free edilmemelidir.

Örnek: İsimsiz semafor kullanımı

/* sem_unnamed.c */
#include <semaphore.h>
#include <pthread.h>
#include "common.h"

static int glob = 0;
static sem_t sem;

static void *threadFunc(void *arg)
{
    int loops = *((int *) arg);
    int loc, j;
    for (j = 0; j < loops; j++) {
        if (sem_wait(&sem) == -1)
            errExit("sem_wait");
        loc = glob;
        loc++;
        glob = loc;
        if (sem_post(&sem) == -1)
            errExit("sem_post");
    }
    return NULL;
}

int main(int argc, char *argv[])
{
    pthread_t t1, t2;
    int loops, s;
    loops = (argc > 1) ? getInt(argv[1], GN_GT_0, "num-loops") : 10000000;

    /* Initialize a thread-shared mutex with the value 1 */
    if (sem_init(&sem, 0, 1) == -1)
        errExit("sem_init");

    /* Create two threads that increment 'glob' */
    s = pthread_create(&t1, NULL, threadFunc, &loops);
    if (s != 0)
        errExit("pthread_create");

    s = pthread_create(&t2, NULL, threadFunc, &loops);
    if (s != 0)
        errExit("pthread_create");

    /* Wait for threads to terminate */
    s = pthread_join(t1, NULL);
    if (s != 0)
        errExit("pthread_join");

    s = pthread_join(t2, NULL);
    if (s != 0)
        errExit("pthread_join");

    printf("glob = %d\n", glob);
    exit(EXIT_SUCCESS);
}

results matching ""

    No results matching ""