| |
 | Posted by Ali Çehreli (acehreli) in reply to Ali Çehreli (acehreli) | Permalink Reply |
|
Ali Çehreli (acehreli) 
| Bu kodu sınıf halinde düzenledim. Servis olmak isteyen bir program Servis sınıfından türetilmeli ve işlet() işlevini tanımlamalı.
import std.stdio;
import std.exception;
import core.sys.posix.unistd;
import core.sys.posix.signal;
import core.sys.posix.sys.stat;
import core.thread;
// ========== Bu bölüm servis.d modülü ==========
bool devam_mı = true;
extern(C) void sonlanmaSinyaliAlındı(int) nothrow @system
{
devam_mı = false;
}
// Not: Aynı programda birden fazla Servis nesnesinin çalışabileceğini
// sanmıyorum. Eğer gerçekten öyleyse bunun önlenmesi de gerekir.
class Servis
{
string kayıtDosyasıİsmi;
File kayıt;
this(string kayıtDosyasıİsmi)
{
this.kayıtDosyasıİsmi = kayıtDosyasıİsmi;
}
pid_t başla()
{
pid_t kimlik = fork();
enforce (kimlik >= 0, "fork başarısız");
if (kimlik > 0) {
// Bu durumda sahip programda devam etmekteyiz. Başka bir şey
// yapmamıza gerek yok.
} else {
// Bu durumda işçi programdayız. Bu programı servis (daemon)
// haline getirmemiz gerekiyor.
hazırlan();
mesajEkle("Servis işlemlerini başlatıyorum");
işlet();
mesajEkle("Servis işlemleri bitti");
}
return kimlik;
}
void hazırlan()
{
// Dosyalara yazabilmeyi sağla.
umask(0);
// Servis kayıt (log) dosyasını aç; dış dünyayla tek iletişimimiz bu
// olacak.
kayıt = File(kayıtDosyasıİsmi, "w");
void denetle(bool koşul, string mesaj)
{
if (!koşul) {
mesajEkle(mesaj);
throw new Exception(mesaj);
}
}
// Sahipsiz (orphan) bir program olmayalım diye işletim sistemi
// çekirdeğinden bir oturum numarası edin.
pid_t oturumNumarası = setsid();
denetle(oturumNumarası >= 0, "Oturum numarası (SID) edinemedim");
// Programın geçerli bir klasör içinde çalışmakta olduğunu garanti
// et. Linux standardına göre var olduğundan kesinlikle emin olunan
// klasör / (root) klasörüdür.
int hata = chdir("/");
denetle(hata == 0, "Çalışma klasörünü değiştiremedim");
// Hem konsolu kullanamayacağımız için hem de güvenlik riski nedeniyle
// üç standart akımı kapatmalıyız.
stdin.close();
stdout.close();
stderr.close();
// Sonlanma sinyalini almaya hazırlan.
signal(SIGTERM, &sonlanmaSinyaliAlındı);
mesajEkle("Servis oldum");
}
void mesajEkle(T...)(T mesajlar)
{
kayıt.writeln(mesajlar);
kayıt.flush();
}
// Servis olmak isteyen bir programın yapması gereken, Servis'ten türetmek
// ve soyut işlet() işlevinin o servise uygun bir tanımını vermektir.
abstract void işlet();
}
// ========== Bundan sonrası da o modülü kullanan örnek bir program ==========
// Bir servis tanımlıyoruz
class BenimServis : Servis
{
this()
{
// Yapmamız gereken, üst sınıfın istediği kayıt dosyası ismini vermek
super("/tmp/Servis_denemesi_kayitlari");
}
// Bir de kendi işimize uygun bir işlet() işlevi yazmak
override void işlet()
{
// Bu, servisin ana döngüsü. 'devam_mı' değişkeni servis.d modülü
// tarafından sunuluyor.
for (size_t sayaç = 0; devam_mı; ++sayaç) {
mesajEkle(sayaç);
Thread.sleep(1.seconds);
}
}
}
void main()
{
auto servis = new BenimServis();
pid_t işçiKimliği = servis.başla();
writeln("İşçi başlatıldı: ", işçiKimliği);
}
Ali
--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]
|