Linux Sistem Programlama
  • Kapak
  • Önsöz
  • Sistem Programlamaya Giriş
    • Tarihçe
    • Standartlar
    • Sistem Çağrıları
    • API ve ABI
  • Linux Çekirdeği
  • Kabuk
  • Dosya Sistemi
  • Kullanıcı, Grup ve Erişim Yetkileri
  • Process Kavramı
  • Dosya İşlemleri
  • IO Modelleri
    • Senkron IO
    • Asenkron IO
  • Sinyaller
    • Temel Kavramlar
    • Sinyal Yakalama ve Gönderme
    • Signal-Safe Kavramı
    • Sinyal Kümeleri
    • Sinyal Bloklama
    • Sinyal İle Birlikte Veri Gönderimi
    • Sinyal ve Core Dump
    • RealTime Sinyaller
    • File Descriptor Üzerinden Sinyal İşleme
    • Genel Değerlendirme
  • Thread Kullanımı
    • Thread Oluşturma
    • Thread Türleri
    • Thread Sonlandırma
    • Mutex Kullanımı
    • SpinLock & Mutex Karşılaştırması
    • Futex
  • Semafor Kullanımı
    • Semafor ve Mutex Karşılaştırması
    • Semafor Türleri
    • Semafor Operasyonları
  • Shared Memory Kullanımı
  • Memory Mapped IO
  • Soket Kullanımı
    • Soket API
    • TCP Soketleri
    • UDP Soketleri
    • UNIX Soketleri
    • Birden Çok İstemciyle Çalışma
  • Timer Kullanımı
    • Basit Timer Yapıları
    • POSIX Timer API
    • Event Loop İçinde Kullanım
  • Daemon Oluşturma
  • Capabilities API
  • Paylaşımlı Kütüphaneler
    • Kütüphane Gereksinimi
    • Statik Kütüphaneler
    • Kod Referanslarının Ele Alınması
    • Paylaşımlı Kütüphanelerin Oluşturulması
    • Dinamik Yükleme
    • Derleme Zamanında Kütüphanelerin Aranması
    • Çalışma Zamanında Kütüphanelerin Aranması
    • Statik ve Dinamik Kütüphanelerin Beraber Kullanılması
    • Versiyon Yönetimi
  • Process'ler Arası Haberleşme
  • Memory Allocation
  • Memory Barriers
  • Hata Ayıklama Yöntemleri
    • GNU Debugger
    • Strace
  • GNU Build Sistemi Araçları
    • Make
    • Autoconf, Automake
  • Ek Bölümler
    • Derleyici Optimizasyonları
    • Clang ve LLVM
    • İçsel ve Anonim Fonksiyonlar
      • İçsel Fonksiyonlar
      • Anonim Fonksiyonlar
    • FreeTDS ile SqlServer Bağlantısı
  • Kaynak Dosyalar
Powered by GitBook
On this page
  • Operasyonel Semafor Fonksiyonları
  • sem_wait
  • Örnek: Semafor Bekleme
  • sem_trywait ve sem_timedwait
  • sem_post
  • Örnek: Semafor Değerini Artırma
  • sem_getvalue
  • Örnek
  • İsimsiz Semaforlar
  • sem_init
  • sem_destroy
  • Örnek: İsimsiz semafor kullanımı

Was this helpful?

  1. Semafor Kullanımı

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);
}
PreviousSemafor TürleriNextShared Memory Kullanımı

Last updated 5 years ago

Was this helpful?