İşletim Sistemleri etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
İşletim Sistemleri etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

100 Madde'de UNIX


Unix'i 100 maddede anlatmaya başlıyorum. (Herbir maddenin açıklaması yapılıp full reg)

Unix, 1969'da Bell Laboratuvarları'nda Ken Thompson ve Dennis Ritchie tarafından geliştirildi.

Bu maddeyi derinlemesine açıklayalım:

Unix'in doğuşu, bilgisayar bilimlerinin önemli dönüm noktalarından biridir. 1960'ların sonlarında, bilgisayarlar hala büyük, pahalı ve karmaşık makinelerdi. Bu dönemde, Bell Laboratuvarları (şu anki adıyla Nokia Bell Labs) bir işletim sistemi geliştirme projesinde yer alıyordu: Multics (Multiplexed Information and Computing Service).

Örnek Senaryo: Düşünün ki 1969 yılındasınız. Ken Thompson ve Dennis Ritchie, Multics projesinde çalışıyorlar ama projenin karmaşıklığı ve yavaş ilerleyişinden memnun değiller. Thompson, bir gün eski bir PDP-7 bilgisayarında basit bir dosya sistemi ve birkaç yardımcı program yazmaya başlıyor. Bu, Unix'in temellerini oluşturuyor.

Detaylar:

  1. İsim Kökeni: Sistemin adı başlangıçta "Unics" (Uniplexed Information and Computing Service) idi, Multics'in aksine tek kullanıcılı bir sistem olduğu için. Zamanla bu isim "Unix"e dönüştü.
  2. C Dilinin Gelişimi: Ritchie, Unix'i daha taşınabilir hale getirmek için C programlama dilini geliştirdi. Bu, Unix'in farklı donanımlarda çalışabilmesini sağladı.
  3. İlk Sürümler: İlk Unix sürümü 1971'de tamamlandı ve Bell Labs içinde kullanılmaya başlandı. 1973'te sistemin çekirdeği C diliyle yeniden yazıldı.
  4. Yayılma: Unix, üniversitelere ücretsiz olarak dağıtıldı. Bu, sistemin hızla yayılmasını ve gelişmesini sağladı.
  5. Etki: Unix, modern işletim sistemlerinin birçoğunu etkiledi. Linux, BSD, macOS gibi sistemler Unix felsefesini ve tasarım prensiplerini takip eder.

Günümüze Etkisi: Bugün kullandığımız birçok teknoloji, Unix'in prensiplerinden ve tasarım felsefesinden etkilenmiştir. Örneğin, akıllı telefonunuzda kullandığınız Android işletim sistemi, Linux çekirdeği üzerine inşa edilmiştir ve dolayısıyla Unix mirasını taşır.

Unix'in geliştirilmesi, bilgisayar bilimlerinde "açık kaynak" kavramının öncüsü olmuş, yazılım geliştirme pratiklerini değiştirmiş ve bilgisayarların daha erişilebilir hale gelmesine katkıda bulunmuştur.

Çok kullanıcılı ve çok görevli bir işletim sistemidir.

Unix'in çok kullanıcılı ve çok görevli yapısı, onun en temel ve devrim niteliğindeki özelliklerinden biridir. Bu özelliği derinlemesine inceleyelim:

Çok Kullanıcılı (Multi-user) Özellik:

Örnek Senaryo:
Bir üniversite bilgisayar laboratuvarındasınız. Laboratuvarda 50 terminal var, ancak hepsi tek bir güçlü Unix sunucusuna bağlı. Her öğrenci kendi kullanıcı hesabıyla sisteme giriş yapıyor ve kendi çalışmalarını yapıyor.

Detaylar:
1. Kullanıcı Hesapları: Her kullanıcının benzersiz bir kullanıcı adı ve parolası vardır.
2. Ev Dizinleri: Her kullanıcının kendi ev dizini (/home/kullanıcıadı) bulunur.
3. İzinler: Dosya ve dizinler için okuma, yazma ve çalıştırma izinleri ayarlanabilir.
4. Kaynak Paylaşımı: CPU zamanı, bellek ve disk alanı kullanıcılar arasında paylaştırılır.

Çok Görevli (Multi-tasking) Özellik:

Örnek Senaryo:
Bir sistem yöneticisisiniz. Aynı anda bir yazılım güncellemesi yapıyor, sistem loglarını inceliyor ve bir yedekleme işlemi başlatıyorsunuz.

Detaylar:
1. Prosesler: Her görev ayrı bir proses olarak çalışır.
2. Zamanlama: İşletim sistemi, CPU zamanını prosesler arasında paylaştırır.
3. Öncelik: Proseslere farklı öncelikler atanabilir (nice değeri ile).
4. Arka Plan İşlemleri: İşlemler arka planda çalıştırılabilir (& işareti ile).

Bu Özelliklerin Önemi:

1. Verimlilik: Kaynaklar etkin bir şekilde kullanılır. Bir kullanıcı veya görev beklerken, diğerleri çalışmaya devam edebilir.

2. Güvenlik: Kullanıcılar birbirlerinin verilerine erişemez (izinler olmadan).

3. Maliyet Etkinliği: Tek bir güçlü bilgisayar, birçok kullanıcıya hizmet verebilir.

4. Esneklik: Sistem yöneticileri, kullanıcı haklarını ve kaynak kullanımını detaylı olarak yönetebilir.

Günlük Hayattan Bir Örnek:
Modern bir ofis ortamını düşünün. Farklı departmanlardan çalışanlar (çok kullanıcı) aynı anda farklı görevler yapıyor (çok görev): muhasebe finansal raporlar hazırlıyor, IT ekibi sistem güncellemeleri yapıyor, pazarlama ekibi sosyal medya kampanyaları yürütüyor. Unix benzeri bir sistem, tüm bu faaliyetlerin aynı anda, güvenli ve verimli bir şekilde yürütülmesini sağlar.

Bu özellikler, Unix'i büyük organizasyonlar, üniversiteler ve araştırma kurumları için ideal bir platform haline getirmiştir. Günümüzde kullandığımız bulut sistemleri ve web sunucuları da bu çok kullanıcılı ve çok görevli mimariden yoğun şekilde faydalanmaktadır.


C programlama dili ile yazılmıştır.

Unix'in C programlama dili ile yazılması, bilgisayar bilimlerinde önemli bir dönüm noktasıdır. Bu maddeyi derinlemesine inceleyelim:

Örnek Senaryo:
1973 yılındasınız. Ken Thompson ve Dennis Ritchie, Unix'i yeniden yazmaya karar veriyorlar. İlk versiyonu assembly dili ile yazılmıştı, ancak bu, sistemin farklı donanımlarda çalışmasını zorlaştırıyordu. Ritchie, bu sorunu çözmek için C dilini geliştiriyor ve Unix'i bu dille yeniden yazıyorlar.

Detaylar:

1. C Dilinin Doğuşu:
   - C, B dilinden türetildi ve Unix için özel olarak geliştirildi.
   - Düşük seviyeli işlemlere izin verirken, yüksek seviyeli bir dil kadar okunabilir ve taşınabilirdi.

2. Taşınabilirlik:
   - C ile yazılan Unix, farklı donanımlara kolayca uyarlanabilir hale geldi.
   - Örnek: PDP-11'den IBM mainframe'lerine kadar farklı sistemlerde çalışabiliyordu.

3. Performans:
   - C, assembly kadar hızlı çalışabilen, ancak daha kolay yazılabilen bir dildi.
   - Örnek: Bir dosya sistemi işlemi, C ile yazıldığında assembly'ye yakın performans gösterebiliyordu.

4. Modülerlik:
   - C, kodun modüler yapıda yazılmasına olanak tanıdı.
   - Örnek: Bellek yönetimi, dosya sistemi, proses yönetimi gibi Unix bileşenleri ayrı modüller halinde geliştirilebiliyordu.

5. Geliştirme Hızı:
   - C ile kod yazmak, assembly'ye göre çok daha hızlıydı.
   - Örnek: Yeni bir sistem çağrısı eklemek, C ile birkaç saat sürerken, assembly ile günler alabilirdi.

Pratik Bir Örnek:
Diyelim ki Unix'in disk I/O sistemini geliştirmek istiyorsunuz. C ile yazılmış olması sayesinde:

```c
ssize_t read(int fd, void *buf, size_t count) {
    // Düşük seviyeli disk işlemleri burada yapılır
    // ...
    return bytes_read;
}
```

Bu fonksiyon, farklı donanımlarda çalışacak şekilde derlenebilir. Eğer assembly ile yazılsaydı, her donanım için ayrı ayrı kodlanması gerekirdi.

Günümüze Etkisi:
1. Linux Çekirdeği: Linux de C ile yazılmıştır ve Unix'in bu mirasını devam ettirir.
2. Sistem Programlama: C, hala sistem programlama için tercih edilen dillerden biridir.
3. Performans Kritik Uygulamalar: Veritabanları, oyun motorları gibi yüksek performans gerektiren uygulamalar hala C/C++ ile yazılır.

Unix'in C ile yazılması, sadece Unix'i değil, tüm bilgisayar bilimlerini etkiledi. Bu karar, taşınabilir işletim sistemleri ve uygulamalar çağını başlattı ve modern bilişimin temellerini attı. Bugün kullandığımız birçok teknoloji, doğrudan veya dolaylı olarak bu kararın bir sonucudur.


Açık kaynak kodlu bir sistemdir.

Unix'in açık kaynak kodlu bir sistem olması, bilişim dünyasında çok önemli bir yere sahiptir. Bu özelliği derinlemesine inceleyelim:

Örnek Senaryo:
1970'lerin başındasınız. Bell Labs, Unix'i geliştirdi ve üniversitelere kaynak koduyla birlikte dağıtmaya başladı. Berkeley Üniversitesi'nde bir öğrencisiniz ve Unix'in kaynak kodunu inceleme, değiştirme ve geliştirme fırsatınız var.

Detaylar:

1. Kaynak Kodun Erişilebilirliği:
   - Unix'in kaynak kodu, kullanıcılara açıktı.
   - Örnek: Bir üniversite, Unix'in bellek yönetim algoritmasını inceleyip kendi ihtiyaçlarına göre optimize edebilirdi.

2. Topluluk Katkısı:
   - Kullanıcılar, sisteme yeni özellikler ekleyebilir veya hataları düzeltebilirdi.
   - Örnek: Berkeley Software Distribution (BSD), Unix'e önemli geliştirmeler yapan bir topluluk projesiydi.

3. Eğitim ve Araştırma:
   - Öğrenciler ve araştırmacılar, gerçek bir işletim sistemini inceleyebiliyordu.
   - Örnek: Bir bilgisayar bilimi öğrencisi, Unix'in proses planlama algoritmasını inceleyerek kendi algoritmasını geliştirebilirdi.

4. Hızlı Gelişim:
   - Açık kaynak modeli, Unix'in hızla gelişmesini ve iyileşmesini sağladı.
   - Örnek: TCP/IP protokolü, Berkeley Unix'e eklendi ve hızla yaygınlaştı.

5. Farklı Versiyonlar:
   - Açık kaynak yapısı, farklı Unix versiyonlarının ortaya çıkmasına yol açtı.
   - Örnek: Solaris, AIX, HP-UX gibi ticari versiyonlar; FreeBSD, OpenBSD gibi açık kaynak versiyonlar.

Pratik Bir Örnek:
Diyelim ki Unix'in dosya sistemi performansını artırmak istiyorsunuz. Açık kaynak yapısı sayesinde:

1. Mevcut kodu incelersiniz:
```c
int write_file(const char *path, const char *data, size_t size) {
    // Mevcut yazma işlemi
}
```

2. Performansı artıracak değişiklikler yaparsınız:
```c
int write_file_optimized(const char *path, const char *data, size_t size) {
    // Önbellek kullanımını optimize eden yeni kod
    // Asenkron I/O kullanımı
    // ...
}
```

3. Bu değişikliği topluluğa sunarsınız ve diğer geliştiricilerle tartışırsınız.

4. Eğer kabul görürse, bu geliştirme Unix'in sonraki sürümlerine dahil edilir.

Günümüze Etkisi:
1. Linux: Unix'in açık kaynak felsefesini devam ettiren en önemli projedir.
2. Açık Kaynak Hareketi: Unix'in bu modeli, günümüzdeki açık kaynak hareketinin temelini oluşturdu.
3. İnovasyon: Açık kaynak modeli, teknolojik inovasyonu hızlandırdı.
4. Eğitim: Bilgisayar bilimleri eğitiminde, açık kaynak sistemler önemli bir rol oynamaya devam ediyor.

Unix'in açık kaynak yapısı, sadece bir işletim sisteminin gelişimini etkilemekle kalmadı, aynı zamanda yazılım geliştirme kültürünü de şekillendirdi. Bu model, bilginin paylaşımını, işbirliğini ve sürekli iyileştirmeyi teşvik ederek, modern bilişim dünyasının temellerini attı.


Taşınabilirlik, Unix'in temel tasarım prensiplerinden biridir.

Unix'in taşınabilirlik prensibi, sistemin en önemli ve yenilikçi özelliklerinden biridir. Bu prensibi derinlemesine inceleyelim:

Örnek Senaryo:
1970'lerin sonundasınız. Bir üniversitede sistem yöneticisisiniz. Laboratuvarınızda farklı donanımlara sahip bilgisayarlar var: DEC PDP-11, IBM System/370 ve yeni çıkan VAX makineleri. Unix'in taşınabilirlik özelliği sayesinde, tüm bu farklı sistemlerde aynı işletim sistemini çalıştırabiliyorsunuz.

Detaylar:

1. C Dilinin Kullanımı:
   - Unix'in C ile yazılması, farklı donanımlara uyarlanmasını kolaylaştırdı.
   - Örnek: Sadece C derleyicisini ve küçük bir assembly kod parçasını her platforma uyarlamak yeterliydi.

2. Donanımdan Bağımsız Katman:
   - Unix, donanıma özgü işlemleri soyutlayan bir katman içerir.
   - Örnek: Disk I/O işlemleri, her donanım için özel olarak yazılır, ancak üst katmanlar aynı kalır.

3. Standart API:
   - Unix, standart bir uygulama programlama arayüzü (API) sunar.
   - Örnek: open(), read(), write() gibi sistem çağrıları tüm Unix sistemlerinde aynı şekilde çalışır.

4. Kaynak Kodun Uyarlanabilirliği:
   - Unix'in kaynak kodu, farklı mimarilere kolayca uyarlanabilecek şekilde yazılmıştır.
   - Örnek: Bellek yönetimi kodu, farklı bellek mimarilerine göre düzenlenebilir.

5. Konfigürasyon Sistemi:
   - Unix, derleme zamanında sistemin özelliklerini belirlemeye olanak tanır.
   - Örnek: Makefile ve yapılandırma betikleri, sistemin özelliklerine göre kodu derler.

Pratik Bir Örnek:
Diyelim ki Unix'i yeni bir donanıma taşımak istiyorsunuz. İşte izleyeceğiniz adımlar:

1. Donanıma özgü çekirdek kodunu yazın:
```c
// arch/new_hardware/kernel/cpu.c
void cpu_init() {
    // Yeni donanıma özgü CPU başlatma kodu
}
```

2. Donanım soyutlama katmanını uyarlayın:
```c
// include/asm-new_hardware/io.h
#define outb(value, port) \
    asm volatile ("outb %b0, %w1" : : "a" (value), "Nd" (port))
```

3. Yapılandırma dosyalarını güncelleyin:
```makefile
# Makefile
ARCH := new_hardware
CROSS_COMPILE := new_hardware-unknown-unix-
```

4. Geri kalan Unix kodunu, bu yeni donanım için derleyin.

Günümüze Etkisi:
1. POSIX Standartları: Unix'in taşınabilirlik prensibi, POSIX gibi standartların geliştirilmesine yol açtı.
2. Çapraz Platform Geliştirme: Modern uygulamaların farklı işletim sistemlerinde çalışabilmesi, bu prensipten esinlenmiştir.
3. Bulut Bilişim: Farklı donanımlar üzerinde aynı yazılımı çalıştırma fikri, bulut bilişimin temelini oluşturur.
4. Konteyner Teknolojileri: Docker gibi teknolojiler, Unix'in taşınabilirlik prensibini modern bir yaklaşımla uygular.

Unix'in taşınabilirlik prensibi, "bir kez yaz, her yerde çalıştır" felsefesinin öncüsü olmuştur. Bu prensip, yazılım geliştirme ve dağıtım pratiklerini derinden etkilemiş, günümüzün heterojen bilişim ortamlarının oluşmasına katkıda bulunmuştur. Modern yazılım mühendisliğinin temel taşlarından biri olan bu prensip, teknolojinin hızla değişen donanım ortamlarına uyum sağlamasını mümkün kılmıştır.

Komut satırı arayüzü (CLI) Unix'in ana kullanıcı arayüzüdür.

Komut satırı arayüzü (CLI), Unix'in en karakteristik ve güçlü özelliklerinden biridir. Bu özelliği derinlemesine inceleyelim:

Örnek Senaryo:
Bir Unix sistem yöneticisisiniz. Uzaktaki bir sunucuya SSH ile bağlanıyorsunuz ve sadece metin tabanlı bir arayüz kullanarak tüm sistem yönetimi görevlerini gerçekleştiriyorsunuz.

Detaylar:

1. Shell Programları:
   - Unix, çeşitli shell programları sunar: sh, bash, csh, zsh, vb.
   - Örnek: Bash (Bourne Again Shell), en yaygın kullanılan shell'lerden biridir.

2. Komut Yapısı:
   - Komutlar genellikle "komut [seçenekler] [argümanlar]" yapısındadır.
   - Örnek: `ls -l /home/user` (ls komutu, -l seçeneği ile /home/user dizinini listeler)

3. Borulama (Piping):
   - Komutların çıktıları birbirine "boru" ile bağlanabilir.
   - Örnek: `cat file.txt | grep "error" | wc -l` (file.txt içindeki "error" kelimesinin geçtiği satır sayısını bulur)

4. Yönlendirme (Redirection):
   - Girdi ve çıktı yönlendirilebilir.
   - Örnek: `ls > file_list.txt` (ls komutunun çıktısını file_list.txt dosyasına yazar)

5. Betik Yazımı:
   - Komutlar, betik dosyalarında birleştirilebilir.
   - Örnek: Bir yedekleme betiği oluşturma

6. Güçlü Metin İşleme:
   - grep, sed, awk gibi araçlarla karmaşık metin işlemleri yapılabilir.
   - Örnek: Log dosyalarını analiz etme

Pratik Bir Örnek:
Diyelim ki sunucudaki tüm web sunucusu log dosyalarını inceleyip, en çok ziyaret edilen 10 sayfayı bulmak istiyorsunuz:

```bash
cat /var/log/apache2/access.log* | \
awk '{print $7}' | \
sort | \
uniq -c | \
sort -rn | \
head -n 10
```

Bu komut zinciri:
1. Tüm log dosyalarını okur
2. Her satırdan URL'yi çıkarır
3. URL'leri sıralar
4. Tekrar eden URL'leri sayar
5. En çok tekrar edenleri başa alır
6. İlk 10 sonucu gösterir

Günümüze Etkisi:
1. Sistem Yönetimi: CLI hala sistem yönetiminde tercih edilen arayüzdür.
2. Otomasyon: CLI, script yazımı ve otomasyon için idealdir.
3. Uzaktan Yönetim: SSH üzerinden sunucuları yönetmek için CLI kullanılır.
4. DevOps Pratikleri: Modern DevOps araçları, Unix CLI geleneğini sürdürür.
5. Verimlilik: Deneyimli kullanıcılar için CLI, GUI'den daha hızlı ve verimlidir.

CLI'nin Avantajları:
- Düşük kaynak kullanımı
- Uzaktan erişim kolaylığı
- Tekrarlanabilir işlemler
- Güçlü otomasyon imkanları
- Hassas kontrol

Dezavantajları:
- Öğrenme eğrisi diktir
- Görsel geri bildirim eksikliği
- Yeni kullanıcılar için korkutucu olabilir

Unix'in komut satırı arayüzü, sistemin gücünü ve esnekliğini ortaya çıkaran en önemli özelliklerden biridir. Modern bilişim dünyasında, özellikle sunucu yönetimi, yazılım geliştirme ve DevOps alanlarında, CLI hala vazgeçilmez bir araç olmaya devam etmektedir. GUI'lerin yaygınlaşmasına rağmen, CLI'nin sunduğu verimlilik ve kontrol, onu Unix ve türevi sistemlerde ana kullanıcı arayüzü konumunda tutmaktadır.

Unix felsefesi: "Bir işi iyi yapan küçük programlar yaz."

Unix felsefesinin bu önemli prensibini derinlemesine inceleyelim:

Örnek Senaryo:
Bir yazılım geliştiricisisiniz ve karmaşık bir metin işleme görevi var önünüzde. Unix felsefesini benimseyerek, bu görevi küçük, özelleşmiş programlarla çözmeye karar veriyorsunuz.

Detaylar:

1. Modülerlik:
   - Her program tek bir işi iyi yapar.
   - Örnek: 'grep' sadece metin arama, 'sort' sadece sıralama yapar.

2. Birleştirilebilirlik:
   - Küçük programlar, borular (pipes) aracılığıyla birleştirilebilir.
   - Örnek: `cat file.txt | grep "error" | sort | uniq -c`

3. Yeniden Kullanılabilirlik:
   - Programlar, farklı bağlamlarda tekrar kullanılabilir.
   - Örnek: 'cut' komutu, log analizi, veri temizleme gibi farklı görevlerde kullanılabilir.

4. Basitlik:
   - Programlar karmaşık olmak yerine basit ve anlaşılır olmalıdır.
   - Örnek: 'ls' komutu sadece dizin içeriğini listeler, başka bir şey yapmaz.

5. Metin Arayüzü:
   - Programlar metin girdi alıp metin çıktı verir, bu da birleştirilebilirliği artırır.
   - Örnek: 'wc' komutu metin girdi alır ve sayısal sonuçları metin olarak verir.

Pratik Bir Örnek:
Diyelim ki bir web sunucusu log dosyasından, belirli bir IP adresinden gelen ve 404 hatası döndüren istekleri bulmak ve bu istekleri zamana göre sıralamak istiyorsunuz:

```bash
grep "192.168.1.100" access.log | \
grep "404" | \
cut -d'[' -f2 | cut -d']' -f1 | \
sort
```

Bu komut zinciri:
1. `grep "192.168.1.100"`: Belirli IP adresini içeren satırları filtreler.
2. `grep "404"`: 404 hatasını içeren satırları filtreler.
3. `cut -d'[' -f2 | cut -d']' -f1`: Tarih ve saat bilgisini ayıklar.
4. `sort`: Sonuçları sıralar.

Her komut tek bir işi yapar ve birlikte karmaşık bir görevi yerine getirirler.

Günümüze Etkisi:
1. Mikroservis Mimarisi: Modern yazılım geliştirmede, büyük monolitik uygulamalar yerine küçük, özelleşmiş servisler kullanma trendi bu felsefeyi yansıtır.

2. Fonksiyonel Programlama: Tek bir görevi yerine getiren saf fonksiyonlar yazma fikri, Unix felsefesiyle paraleldir.

3. API Tasarımı: RESTful API'ler, genellikle tek bir kaynağı manipüle eden endpoint'ler sunar, bu da Unix felsefesini yansıtır.

4. DevOps Araçları: Docker, Kubernetes gibi araçlar, küçük, özelleşmiş bileşenleri birleştirerek karmaşık sistemler oluşturma fikrini uygular.

5. Açık Kaynak Ekosistemi: Küçük, özelleşmiş kütüphaneler ve araçlar geliştirme trendi, bu felsefeyi yansıtır.

Avantajları:
- Kod bakımı ve hata ayıklama kolaylaşır
- Yeniden kullanılabilirlik artar
- Sistem esnekliği ve genişletilebilirliği iyileşir
- Farklı dillerde yazılmış programlar bile bir arada çalışabilir

Dezavantajları:
- Bazen aşırı parçalama, sistem karmaşıklığını artırabilir
- Çok sayıda küçük program arasındaki bağımlılıkları yönetmek zor olabilir

Unix felsefesinin bu prensibi, yazılım geliştirme dünyasında derin izler bırakmıştır. Modern yazılım mimarileri ve pratikleri, bu basit ama güçlü fikrin evrimidir. Bu felsefe, karmaşık problemleri basit, yönetilebilir parçalara ayırarak çözme yaklaşımını teşvik eder ve bu, günümüz yazılım mühendisliğinin temel taşlarından biri haline gelmiştir.


Dosya sistemi hiyerarşik bir yapıya sahiptir.

Unix'in hiyerarşik dosya sistemi yapısı, işletim sisteminin en temel ve karakteristik özelliklerinden biridir. Bu yapıyı derinlemesine inceleyelim:

Örnek Senaryo:
Bir Unix sistem yöneticisisiniz ve yeni bir çalışana sistem dosya yapısını anlatıyorsunuz. Dosya sisteminin nasıl organize edildiğini ve neden bu şekilde yapılandırıldığını açıklıyorsunuz.

Detaylar:

1. Kök Dizin (/):
   - Tüm dosya sistemi hiyerarşisinin başlangıç noktasıdır.
   - Örnek: Tüm diğer dizinler ve dosyalar "/" altında bulunur.

2. Ana Dizinler:
   - /home: Kullanıcı ev dizinleri
   - /etc: Sistem konfigürasyon dosyaları
   - /var: Değişken veriler (log dosyaları, geçici dosyalar)
   - /bin: Temel sistem komutları
   - /usr: Kullanıcı programları ve verileri
   - /tmp: Geçici dosyalar

3. Alt Dizinler:
   - Her ana dizin, kendi alt dizinlerine sahip olabilir.
   - Örnek: /home/alice, /home/bob

4. Bağlama Noktaları (Mount Points):
   - Fiziksel depolama aygıtları, dosya sistemi hiyerarşisine bağlanabilir.
   - Örnek: Harici bir disk /mnt/external altına bağlanabilir.

5. Sembolik Bağlantılar:
   - Dosya veya dizinlere başka bir yoldan erişim sağlar.
   - Örnek: /bin dizini genellikle /usr/bin'e sembolik bağlantıdır.

Pratik Bir Örnek:
Diyelim ki bir web uygulaması kurmak istiyorsunuz. İşte dosya sistemi hiyerarşisini kullanarak nasıl organize edebileceğiniz:

```
/
├── etc/
│   └── apache2/
│       └── sites-available/
│           └── myapp.conf
├── var/
│   ├── www/
│   │   └── myapp/
│   │       ├── index.html
│   │       └── images/
│   └── log/
│       └── apache2/
│           └── myapp_access.log
├── home/
│   └── developer/
│       └── projects/
│           └── myapp/
│               └── source_code/
└── tmp/
    └── myapp_cache/
```

Bu yapıda:
- Web uygulaması dosyaları /var/www/myapp altında
- Konfigürasyon dosyası /etc/apache2/sites-available altında
- Log dosyaları /var/log/apache2 altında
- Geliştirici kaynak kodları /home/developer/projects/myapp altında
- Geçici dosyalar /tmp/myapp_cache altında bulunur

Günümüze Etkisi:
1. Standartlaşma: FHS (Filesystem Hierarchy Standard) gibi standartlar, Unix-benzeri sistemlerde tutarlı bir yapı sağlar.

2. Güvenlik: Hiyerarşik yapı, erişim kontrolünü ve izinleri yönetmeyi kolaylaştırır.

3. Çoklu Kullanıcı Desteği: Her kullanıcının kendi ev dizini (/home/username) olması, çoklu kullanıcı ortamlarını destekler.

4. Sistem Yönetimi: Standart bir hiyerarşi, sistem yönetimini ve sorun gidermeyi kolaylaştırır.

5. Taşınabilirlik: Tutarlı bir yapı, uygulamaların farklı Unix sistemleri arasında taşınabilirliğini artırır.

Avantajları:
- Organize ve mantıksal bir yapı sunar
- Sistem kaynaklarına erişimi kontrol etmeyi kolaylaştırır
- Farklı türdeki verileri (sistem dosyaları, kullanıcı verileri, geçici dosyalar) ayırır
- Sistem yönetimini ve bakımını basitleştirir

Dezavantajları:
- Yeni kullanıcılar için öğrenmesi zor olabilir
- Bazı durumlarda, derin iç içe geçmiş dizin yapıları karmaşıklığa yol açabilir

Unix'in hiyerarşik dosya sistemi yapısı, modern işletim sistemlerinin temel taşlarından biridir. Bu yapı, sistemin organize edilmesini, yönetilmesini ve güvenliğinin sağlanmasını kolaylaştırır. Günümüzde Linux, macOS ve hatta kısmen Windows gibi modern işletim sistemleri, bu hiyerarşik yapıyı benimsemiş ve kendi ihtiyaçlarına göre uyarlamıştır.

Unix'te "her şey bir dosyadır" prensibi geçerlidir.

Unix'in "her şey bir dosyadır" prensibi, sistemin en temel ve güçlü konseptlerinden biridir. Bu prensibi derinlemesine inceleyelim:

Örnek Senaryo:
Bir Unix sistem programcısısınız ve yeni bir geliştiriciyle çalışıyorsunuz. Ona Unix'in bu prensibini anlatıyor ve bunun sistem tasarımını nasıl etkilediğini gösteriyorsunuz.

Detaylar:

1. Dosya Soyutlaması:
   - Donanım aygıtları, ağ soketleri, hatta prosesler bile dosya olarak temsil edilir.
   - Örnek: Bir yazıcıya /dev/lp0 dosyası üzerinden erişilebilir.

2. Standart Dosya İşlemleri:
   - open(), read(), write(), close() gibi standart dosya işlemleri, çoğu sistem kaynağı için kullanılabilir.
   - Örnek: Bir ağ soketine veri yazmak, bir dosyaya yazmakla aynı şekilde yapılır.

3. Aygıt Dosyaları:
   - Donanım aygıtları /dev dizini altında dosyalar olarak temsil edilir.
   - Örnek: /dev/sda (ilk SATA disk), /dev/tty (terminal)

4. Proses Bilgileri:
   - Çalışan prosesler hakkında bilgiler /proc dizini altında dosyalar olarak sunulur.
   - Örnek: /proc/[PID]/status bir prosesin durumunu içerir.

5. Yapılandırma:
   - Sistem ve uygulama yapılandırmaları genellikle düz metin dosyalarında saklanır.
   - Örnek: /etc/passwd kullanıcı bilgilerini içerir.

Pratik Bir Örnek:
Diyelim ki bir USB diskin içeriğini okumak ve bir ağ soketi üzerinden göndermek istiyorsunuz:

```bash
# USB diski bağlayalım
mount /dev/sdb1 /mnt/usb

# Disk içeriğini okuyup ağ üzerinden gönderelim
cat /mnt/usb/myfile.txt > /dev/tcp/192.168.1.100/12345
```

Bu örnekte:
1. USB disk bir dosya (/dev/sdb1) olarak temsil edilir.
2. Disk içeriği standart bir dosya gibi okunur (cat komutu ile).
3. Ağ soketi de bir dosya (/dev/tcp/...) olarak ele alınır.
4. Yönlendirme operatörü (>) kullanılarak veri dosyadan sokete "kopyalanır".

Günümüze Etkisi:
1. API Tasarımı: RESTful API'ler, kaynakları URL'ler (bir nevi dosya yolları) olarak temsil eder.
2. Konteyner Teknolojileri: Docker gibi teknolojiler, konteyner içindeki prosesleri ve kaynakları dosya sistemindeki öğeler olarak yönetir.
3. DevOps Pratikleri: "Infrastructure as Code" yaklaşımı, sistem yapılandırmalarını metin dosyaları olarak ele alır.
4. IoT (Nesnelerin İnterneti): Birçok IoT cihazı, sensör verilerini ve kontrol mekanizmalarını dosya sistemi benzeri bir arayüz üzerinden sunar.

Avantajları:
- Tutarlı bir arayüz sağlar: Farklı kaynak türleri için aynı işlemler kullanılabilir.
- Programlama kolaylığı: Geliştiriciler, farklı kaynak türleri için yeni API'ler öğrenmek zorunda kalmaz.
- Esneklik: Yeni aygıt veya kaynak türleri kolayca sisteme entegre edilebilir.
- Betik yazımı kolaylığı: Karmaşık işlemler, basit dosya işlemleriyle gerçekleştirilebilir.

Dezavantajları:
- Bazen aşırı basitleştirme, karmaşık aygıtların tüm özelliklerini kullanmayı zorlaştırabilir.
- Yeni kullanıcılar için kafa karıştırıcı olabilir (örneğin, bir yazıcıya dosya olarak davranmak).

"Her şey bir dosyadır" prensibi, Unix'in tasarımındaki dehasını gösterir. Bu yaklaşım, sistem kaynaklarına erişimi basitleştirir, tutarlı bir programlama modeli sunar ve Unix'in esnekliğini ve gücünü artırır. Modern işletim sistemleri ve teknolojiler, bu prensibin avantajlarından hala faydalanmakta ve bu felsefeyi çeşitli şekillerde uygulamaktadır.

Çekirdek (kernel), Unix'in kalbidir ve donanımla iletişimi sağlar.


Unix'in çekirdeği (kernel), sistemin en temel ve kritik bileşenidir. Bu önemli kavramı derinlemesine inceleyelim:

Örnek Senaryo:
Bir bilgisayar mühendisisiniz ve yeni bir Unix-benzeri işletim sistemi geliştiriyorsunuz. Ekibinize çekirdeğin rolünü ve önemini anlatıyorsunuz.

Detaylar:

1. Donanım Soyutlaması:
   - Çekirdek, donanım detaylarını uygulama katmanından gizler.
   - Örnek: Bir uygulama, disk tipini bilmeden dosya okuyabilir.

2. Kaynak Yönetimi:
   - CPU zamanı, bellek, disk alanı gibi kaynakları yönetir.
   - Örnek: Çekirdek, hangi prosesin ne kadar CPU zamanı alacağına karar verir.

3. Proses Yönetimi:
   - Proseslerin oluşturulması, sonlandırılması ve zamanlanmasını kontrol eder.
   - Örnek: fork() sistem çağrısı yeni bir proses oluşturur.

4. Bellek Yönetimi:
   - Fiziksel ve sanal belleği yönetir, sayfalama ve takas işlemlerini gerçekleştirir.
   - Örnek: Çekirdek, bir uygulamanın kullanabileceği bellek miktarını kontrol eder.

5. Dosya Sistemi Yönetimi:
   - Dosya sistemlerini yönetir, dosya ve dizin işlemlerini gerçekleştirir.
   - Örnek: open(), read(), write() gibi sistem çağrıları çekirdek tarafından işlenir.

6. Aygıt Sürücüleri:
   - Donanım aygıtlarıyla iletişimi sağlayan kod parçalarını içerir.
   - Örnek: Disk sürücüsü, fiziksel disk operasyonlarını yönetir.

Pratik Bir Örnek:
Bir uygulamanın dosya okuması senaryosunu ele alalım:

```c
int fd = open("/home/user/file.txt", O_RDONLY);
char buffer[1024];
ssize_t bytes_read = read(fd, buffer, sizeof(buffer));
```

Bu basit kod parçasında:

1. open() çağrısı çekirdeğe gider. Çekirdek:
   - Dosya sistemini kontrol eder.
   - Kullanıcının dosyaya erişim iznini kontrol eder.
   - Dosya için bir tanımlayıcı oluşturur.

2. read() çağrısı çekirdeğe gider. Çekirdek:
   - Disk sürücüsüne komut gönderir.
   - Okunan veriyi belleğe alır.
   - Veriyi uygulama alanına kopyalar.

Tüm bu işlemler çekirdek tarafından yönetilir ve uygulama bunların detaylarını bilmez.

Günümüze Etkisi:
1. Mikro Çekirdek vs Monolitik Çekirdek: Modern işletim sistemleri farklı çekirdek tasarımları kullanır.
2. Gerçek Zamanlı Sistemler: Özel çekirdek tasarımları, gerçek zamanlı sistemlerde kritik öneme sahiptir.
3. Sanallaştırma: Hypervisor'lar, çekirdek seviyesinde sanallaştırma sağlar.
4. Güvenlik: Çekirdek düzeyinde güvenlik önlemleri, sistem güvenliğinin temelidir.
5. IoT ve Gömülü Sistemler: Özelleştirilmiş, hafif çekirdekler bu alanlarda yaygın kullanılır.

Avantajları:
- Donanım bağımsızlığı sağlar.
- Kaynak yönetimini merkezileştirir.
- Güvenlik ve kararlılık sağlar.
- Uygulamaların daha basit olmasına olanak tanır.

Dezavantajları:
- Karmaşıktır ve hata ayıklaması zordur.
- Bir çekirdek hatası tüm sistemi etkileyebilir.
- Çekirdek geliştirmek yüksek uzmanlık gerektirir.

Çekirdek, Unix ve diğer modern işletim sistemlerinin "kalbi" olarak nitelendirilir çünkü sistemin tüm temel işlevlerini yönetir. Donanım ile yazılım arasında bir köprü görevi görür ve uygulamaların donanımla doğrudan etkileşime girmesine gerek kalmadan çalışmasını sağlar. Bu tasarım, Unix'in güçlü, esnek ve dayanıklı bir sistem olmasının temel nedenlerinden biridir.

Kabuk (shell), kullanıcı ile çekirdek arasındaki arayüzdür.

Unix'in kabuk (shell) konsepti, sistemin kullanıcı ile etkileşiminin temelidir. Bu önemli bileşeni derinlemesine inceleyelim:

Örnek Senaryo:
Bir Unix sistem yöneticisisiniz ve yeni bir kullanıcıya sistem üzerinde çalışmayı öğretiyorsunuz. Kabuğun ne olduğunu ve nasıl kullanılacağını anlatıyorsunuz.

Detaylar:

1. Komut Yorumlayıcı:
   - Kabuk, kullanıcının girdiği komutları yorumlar ve çekirdeğe iletir.
   - Örnek: ls komutu girildiğinde, kabuk bunu çekirdeğe uygun sistem çağrılarına çevirir.

2. Betik Dili:
   - Kabuk, kendi programlama diline sahiptir.
   - Örnek: for döngüleri, if-else yapıları kullanılabilir.

3. Ortam Değişkenleri:
   - Sistem ve kullanıcı ortam değişkenlerini yönetir.
   - Örnek: PATH değişkeni, çalıştırılabilir dosyaların aranacağı yerleri belirtir.

4. Giriş/Çıkış Yönlendirme:
   - Standart giriş, çıkış ve hata akışlarını yönetir.
   - Örnek: command > output.txt çıktıyı bir dosyaya yönlendirir.

5. Boru Hattı (Pipeline):
   - Komutları birbirine bağlayarak karmaşık işlemler yapılmasını sağlar.
   - Örnek: ls | grep ".txt" | wc -l

6. İş Kontrolü:
   - Arka planda çalışan işleri yönetir.
   - Örnek: command & komutu arka planda başlatır.

Pratik Bir Örnek:
Diyelim ki tüm .log uzantılı dosyaları bulup içlerinde "error" kelimesini arayan ve sonuçları sıralayan bir işlem yapmak istiyorsunuz:

```bash
find /var/log -name "*.log" | xargs grep "error" | sort | uniq -c
```

Bu komut zincirinde kabuk:
1. find komutunu çalıştırır.
2. Çıktıyı grep komutuna yönlendirir (boru hattı).
3. grep'in çıktısını sort'a yönlendirir.
4. Son olarak uniq komutunu çalıştırır.

Tüm bu işlem boyunca kabuk, her bir komutun çıktısını bir sonrakine aktarır ve son çıktıyı ekrana yazdırır.

Günümüze Etkisi:
1. Modern CLI Araçları: PowerShell gibi modern komut satırı araçları, Unix kabuğunun konseptlerini genişletir.
2. Otomasyon: DevOps pratiklerinde, kabuk betikleri yaygın olarak kullanılır.
3. Sistem Yönetimi: Uzak sunucu yönetimi genellikle kabuk üzerinden yapılır.
4. Programlama Dilleri: Python gibi diller, kabuk benzeri etkileşimli ortamlar sunar.
5. Container Teknolojileri: Docker gibi teknolojiler, kabuk komutlarını yaygın olarak kullanır.

Avantajları:
- Güçlü ve esnek bir komut arayüzü sunar.
- Karmaşık görevleri otomatikleştirmeyi kolaylaştırır.
- Sistem kaynaklarını verimli kullanır.
- Uzaktan yönetim için idealdir.

Dezavantajları:
- Öğrenme eğrisi diktir.
- Görsel geri bildirim eksikliği olabilir.
- Syntax hataları ciddi sonuçlara yol açabilir.

Farklı Kabuk Türleri:
1. Bourne Shell (sh)
2. Bash (Bourne Again Shell)
3. C Shell (csh)
4. Korn Shell (ksh)
5. Z Shell (zsh)

Her biri farklı özellikler ve sözdizimi sunar, ancak temel prensipler aynıdır.

Kabuk, Unix sistemlerinde kullanıcı ile sistem arasındaki birincil arayüzdür. Güçlü komut yorumlama ve betik yazma yetenekleri, sistem yönetimini ve otomasyon görevlerini büyük ölçüde kolaylaştırır. Modern bilişim dünyasında, kabuğun sunduğu konseptler ve yetenekler hala büyük öneme sahiptir ve çeşitli alanlarda yaygın olarak kullanılmaktadır.

Bash, sh, csh gibi farklı kabuk türleri vardır.

Bu önemli noktayı derinlemesine inceleyelim. Farklı kabuk türleri, Unix ve Unix-benzeri sistemlerin esnekliğini ve çeşitliliğini gösterir.

Örnek Senaryo:
Bir Unix sistem yöneticisisiniz ve ekibinizdeki farklı geliştiricilerin tercih ettikleri kabukları kullanmalarına izin veriyorsunuz. Her bir kabuğun özelliklerini ve farklılıklarını açıklıyorsunuz.

Detaylar:

1. Bourne Shell (sh):
   - İlk Unix kabuğu, Steve Bourne tarafından geliştirildi.
   - Basit ve hafif, temel betik yazma yetenekleri sunar.
   - Örnek özellik: $ echo $PATH

2. Bash (Bourne Again Shell):
   - sh'nin gelişmiş versiyonu, GNU Projesi için geliştirildi.
   - Komut tamamlama, geçmiş, alias'lar gibi gelişmiş özellikler sunar.
   - Örnek özellik: $ history | grep "git commit"

3. C Shell (csh):
   - C programlama diline benzer syntax ile tasarlandı.
   - Komut geçmişi ve alias'ları ilk sunan kabuk.
   - Örnek özellik: $ alias ls 'ls -l'

4. Korn Shell (ksh):
   - sh ve csh'nin iyi özelliklerini birleştirir.
   - Güçlü betik yazma yetenekleri sunar.
   - Örnek özellik: $ print -n "Enter your name: "; read name

5. Z Shell (zsh):
   - Bash, ksh ve tcsh'nin özelliklerini içerir ve genişletir.
   - Tema ve eklenti desteği sunar (Oh My Zsh gibi).
   - Örnek özellik: $ git checkout <TAB> (git dallarını otomatik tamamlar)

Pratik Bir Örnek:
Aynı görevi farklı kabuklarda nasıl yapabileceğimizi görelim. 1'den 5'e kadar sayıları yazdıran bir döngü:

Bash:
```bash
for i in {1..5}; do
    echo $i
done
```

C Shell:
```csh
foreach i (`seq 1 5`)
    echo $i
end
```

Korn Shell:
```ksh
for ((i=1; i<=5; i++)); do
    print $i
done
```

Z Shell:
```zsh
for i in {1..5}; do
    echo $i
done
```

Günümüze Etkisi:
1. Kişiselleştirme: Kullanıcılar, tercih ettikleri kabuğu seçebilir ve özelleştirebilir.
2. Betik Uyumluluğu: Farklı kabuklar için yazılan betikler, uyumluluk sorunlarına yol açabilir.
3. Modern Kabuklar: Fish gibi yeni nesil kabuklar, daha kullanıcı dostu arayüzler sunar.
4. Cloud ve DevOps: Farklı kabukların özellikleri, bulut ortamlarında ve DevOps süreçlerinde önemli rol oynar.
5. Sistem Güvenliği: Bazı kabuklar, diğerlerine göre daha güvenli olabilir.

Avantajları:
- Kullanıcılara seçenek sunar
- Farklı iş akışlarına uygun kabuklar seçilebilir
- Her kabuk, belirli görevler için optimize edilmiş olabilir

Dezavantajları:
- Öğrenme eğrisi: Birden fazla kabuğu öğrenmek zaman alabilir
- Uyumluluk sorunları: Bir kabukta çalışan betik, diğerinde çalışmayabilir
- Sistem yönetimi karmaşıklığı: Farklı kullanıcıların farklı kabukları kullanması, yönetimi zorlaştırabilir

Kabuk seçimi genellikle kişisel tercih, iş gereksinimleri ve sistem politikalarına bağlıdır. Örneğin, sistem yöneticileri genellikle Bash'i tercih ederken, bazı geliştiriciler Zsh'in gelişmiş özelliklerini tercih edebilir. Önemli olan, projenizin veya sisteminizin ihtiyaçlarına en uygun kabuğu seçmek ve tutarlı bir şekilde kullanmaktır. Modern Unix ve Linux sistemleri, kullanıcılara bu esnekliği sunarak, farklı iş akışlarına ve tercihlere uyum sağlama yeteneği sağlar.

Unix sistemlerde kullanıcı ve grup kavramları önemlidir.

Unix sistemlerde kullanıcı ve grup kavramları, sistem güvenliği ve kaynak yönetiminin temelini oluşturur. Bu önemli konuyu derinlemesine inceleyelim:

Örnek Senaryo:
Bir üniversite bilgisayar laboratuvarında sistem yöneticisisiniz. Öğrenciler, öğretim görevlileri ve araştırmacılar için farklı erişim seviyelerine sahip kullanıcı hesapları ve grupları oluşturuyorsunuz.

Detaylar:

1. Kullanıcı Hesapları:
   - Her kullanıcının benzersiz bir kullanıcı adı (UID) vardır.
   - Kullanıcı bilgileri /etc/passwd dosyasında saklanır.
   - Örnek: `jsmith:x:1001:1001:John Smith:/home/jsmith:/bin/bash`

2. Gruplar:
   - Kullanıcılar bir veya daha fazla gruba ait olabilir.
   - Grup bilgileri /etc/group dosyasında saklanır.
   - Örnek: `researchers:x:2001:jsmith,alee,btaylor`

3. Ev Dizinleri:
   - Her kullanıcının kendi ev dizini vardır (genellikle /home/username).
   - Kullanıcılar kendi ev dizinlerinde tam yetkiye sahiptir.

4. Süper Kullanıcı (root):
   - UID 0'a sahip, sistemde tam yetkili kullanıcı.
   - Güvenlik nedeniyle doğrudan kullanımı önerilmez (sudo tercih edilir).

5. Dosya ve Dizin İzinleri:
   - Kullanıcı ve grup kavramları, dosya ve dizin izinleriyle yakından ilişkilidir.
   - Örnek: `ls -l` komutu dosya sahibi, grup ve izinleri gösterir.

Pratik Bir Örnek:
Araştırma grubu için yeni bir proje dizini oluşturalım:

```bash
# Yeni grup oluştur
sudo groupadd research_team

# Kullanıcıları gruba ekle
sudo usermod -aG research_team jsmith
sudo usermod -aG research_team alee

# Proje dizini oluştur
sudo mkdir /projects/new_research

# Dizin sahipliğini ve izinlerini ayarla
sudo chown root:research_team /projects/new_research
sudo chmod 775 /projects/new_research

# Grup ID'sini (SGID) bit'ini ayarla
sudo chmod g+s /projects/new_research
```

Bu örnekte:
1. Yeni bir araştırma grubu oluşturuyoruz.
2. İki kullanıcıyı bu gruba ekliyoruz.
3. Yeni bir proje dizini oluşturup, grup sahipliğini ayarlıyoruz.
4. Dizine grup yazma izni veriyoruz.
5. SGID bit'ini ayarlayarak, bu dizinde oluşturulan tüm dosyaların otomatik olarak araştırma grubuna ait olmasını sağlıyoruz.

Günümüze Etkisi:
1. Çok Kullanıcılı Sistemler: Bulut sunucuları ve paylaşımlı sistemlerde hala kritik öneme sahip.
2. Konteyner Teknolojileri: Docker gibi teknolojiler, kullanıcı ve grup kavramlarını konteyner içinde de kullanır.
3. DevOps Pratikleri: Otomatik kullanıcı ve grup yönetimi, modern sistem yönetiminin bir parçasıdır.
4. Güvenlik Politikaları: Kurumsal BT politikaları, kullanıcı ve grup yönetimine dayanır.
5. Access Control Lists (ACL): Daha granüler erişim kontrolü için kullanıcı ve grup kavramlarını genişletir.

Avantajları:
- Güvenlik: Kaynakları ve verileri korur.
- Esneklik: Farklı erişim seviyeleri tanımlanabilir.
- Yönetilebilirlik: Grup bazlı yönetim, büyük sistemlerde kolaylık sağlar.
- Denetlenebilirlik: Kullanıcı eylemleri izlenebilir ve kaydedilebilir.

Dezavantajları:
- Karmaşıklık: Büyük sistemlerde yönetimi zorlaşabilir.
- Overhead: Çok sayıda kullanıcı ve grup, sistem kaynaklarını tüketebilir.
- Güvenlik Riskleri: Yanlış yapılandırma, güvenlik açıklarına yol açabilir.

Unix'in kullanıcı ve grup kavramları, sistemin çok kullanıcılı doğasının temelidir. Bu yapı, farklı kullanıcıların aynı sistemi güvenli bir şekilde paylaşmasını sağlar. Modern işletim sistemleri ve bulut teknolojileri, bu temel kavramları genişleterek ve uyarlayarak kullanmaya devam etmektedir. Sistem yöneticileri ve güvenlik uzmanları için, bu kavramları anlamak ve etkin bir şekilde yönetmek kritik öneme sahiptir.

İzinler (permissions) dosya ve dizin erişimini kontrol eder.

Evet, Unix izinleri (permissions), dosya ve dizin erişimini kontrol eder. Unix tabanlı sistemlerde her dosya ve dizin, kullanıcılar ve gruplar için belirli erişim izinlerine sahiptir. İzinler üç kategoriye ayrılır:

  1. Sahip (Owner) İzinleri: Dosyanın sahibinin izinlerini belirtir.
  2. Grup İzinleri: Dosyanın sahibiyle aynı grupta olan kullanıcıların izinlerini belirtir.
  3. Diğer (Other) İzinleri: Dosyanın sahibi ve sahibiyle aynı grupta olmayan tüm diğer kullanıcıların izinlerini belirtir.

Her kategori için üç temel izin türü vardır:

  • Okuma (Read, r): Dosyayı okuma izni verir.
  • Yazma (Write, w): Dosyayı yazma veya değiştirme izni verir.
  • Çalıştırma (Execute, x): Dosyayı çalıştırma veya bir dizine erişim izni verir.

İzinler sembolik olarak veya oktal olarak belirtilir. Sembolik olarak izinler, r, w ve x karakterleriyle ifade edilir ve şu şekilde gösterilir:

plaintext
rwxr-xr--

Bu örnek, şu anlama gelir:

  • Sahip için: Okuma, yazma ve çalıştırma izni (rwx)
  • Grup için: Okuma ve çalıştırma izni (r-x)
  • Diğer kullanıcılar için: Sadece okuma izni (r--)

Oktal sistemde ise her izin türü bir sayı ile temsil edilir:

  • r = 4 (okuma)
  • w = 2 (yazma)
  • x = 1 (çalıştırma)

Örneğin, rwxr-xr-- izni oktal olarak 755 şeklinde ifade edilir:

  • Sahip için: rwx = 4+2+1 = 7
  • Grup için: r-x = 4+0+1 = 5
  • Diğer kullanıcılar için: r-- = 4+0+0 = 4

Bu izinler chmod komutu ile ayarlanabilir:


chmod 755 dosyaadı

Unix izinleri, sistem güvenliğini sağlamak ve kullanıcılar arasında doğru erişim kontrollerini yapmak için hayati öneme sahiptir.


Borular (pipes) ve yönlendirmeler (redirections) Unix'in güçlü özellikleridir.

Unix işletim sistemi, güçlü özelliklerinden biri olan borular (pipes) ve yönlendirmeler (redirections) ile kullanıcıların komut satırında çok çeşitli işlemleri kolayca gerçekleştirmelerine olanak tanır. Bu özellikler, farklı komutların ve programların birlikte çalışarak verileri işleyip, dönüştürmesini sağlar. İşte bu kavramları derinlemesine inceleyelim.

### Borular (Pipes)

Borular, Unix'te bir komutun çıktısını doğrudan başka bir komutun girdisi olarak kullanmanızı sağlar. Bu, `|` (pipe) sembolü kullanılarak yapılır. Borular, çeşitli komutları ardışık olarak zincirleyerek kompleks görevleri basit ve okunabilir hale getirir.

#### Temel Kullanım
Örneğin, bir dosyanın içeriğini `cat` komutuyla okuyup, ardından bu içeriği `grep` komutuyla filtreleyebilirsiniz:

```sh
cat dosya.txt | grep "arama_kriteri"
```

Bu örnekte:
- `cat dosya.txt`: `dosya.txt` dosyasının içeriğini ekrana yazdırır.
- `|`: `cat` komutunun çıktısını `grep` komutuna yönlendirir.
- `grep "arama_kriteri"`: Borudan gelen veriyi `arama_kriteri` içeren satırlar için filtreler.

#### Örnek Senaryo: Büyük Dosyaların İşlenmesi
Büyük bir log dosyasını (`log.txt`) işleyerek belirli bir tarihe ait hataları (`ERROR`) bulmak isteyebilirsiniz:

```sh
cat log.txt | grep "2024-07-10" | grep "ERROR" > errors_on_2024-07-10.txt
```

Bu komut:
1. `log.txt` dosyasının tüm içeriğini `cat` komutuyla okur.
2. `2024-07-10` tarihini içeren satırları `grep` komutuyla filtreler.
3. Bu satırlar içinden `ERROR` kelimesini içerenleri bir diğer `grep` komutuyla filtreler.
4. Sonuçları `errors_on_2024-07-10.txt` dosyasına yönlendirir.

### Yönlendirmeler (Redirections)

Yönlendirmeler, komutların giriş ve çıkışlarını başka dosyalara veya cihazlara yönlendirmeyi sağlar. Üç temel yönlendirme türü vardır: standart çıktı (stdout), standart hata (stderr) ve standart giriş (stdin).

#### Standart Çıktı (stdout) Yönlendirmesi
Komutların standart çıktısı (ekrana yazılan metin) `>` sembolü kullanılarak bir dosyaya yönlendirilebilir. Örneğin:

```sh
ls -l > dosya_listesi.txt
```

Bu komut, `ls -l` çıktısını `dosya_listesi.txt` dosyasına yazar. Eğer dosya mevcutsa, üzerine yazarak eski içeriği siler. Dosyayı ekleme modunda açmak için `>>` kullanılır:

```sh
ls -l >> dosya_listesi.txt
```

#### Standart Hata (stderr) Yönlendirmesi
Komutların hata mesajlarını başka bir yere yönlendirmek için `2>` sembolü kullanılır. Örneğin:

```sh
ls -l /olmayan_dizin 2> hata_mesaji.txt
```

Bu komut, `/olmayan_dizin` bulunamadığında oluşacak hata mesajını `hata_mesaji.txt` dosyasına yazar.

#### Standart Giriş (stdin) Yönlendirmesi
Bir komutun girişini bir dosyadan veya başka bir kaynaktan almak için `<` sembolü kullanılır. Örneğin:

```sh
sort < dosya.txt
```

Bu komut, `dosya.txt` dosyasını okuyarak içeriğini sıralar ve ekrana yazdırır.

#### Örnek Senaryo: Yönlendirme Kullanarak Log Analizi
Büyük bir log dosyasını analiz ederken hem çıktıyı hem de hataları ayrı dosyalara yazdırmak isteyebilirsiniz:

```sh
grep "ERROR" log.txt > errors.txt 2> errors.log
```

Bu komut:
- `log.txt` dosyasındaki `ERROR` içeren satırları `errors.txt` dosyasına yazar.
- Herhangi bir hata mesajını `errors.log` dosyasına yönlendirir.

### Borular ve Yönlendirmelerin Birlikte Kullanımı

Borular ve yönlendirmeler birlikte kullanılarak daha karmaşık görevler gerçekleştirebilir. Örneğin, belirli bir hatayı içeren satırları bulup sayısını öğrenmek ve sonucu bir dosyaya yazmak:

```sh
grep "ERROR" log.txt | wc -l > error_count.txt
```

Bu komut:
1. `log.txt` dosyasındaki `ERROR` içeren satırları bulur.
2. Bu satırları `wc -l` komutuna yönlendirir ve satır sayısını hesaplar.
3. Sonucu `error_count.txt` dosyasına yazar.

### Özet

Unix'in borular ve yönlendirmeler özellikleri, kullanıcıların karmaşık işlemleri kolay ve esnek bir şekilde gerçekleştirmelerini sağlar. Bu özellikler, komut satırında farklı araçları bir araya getirerek daha büyük ve güçlü komut zincirleri oluşturma yeteneği sunar. Bu temel bilgilerle, borular ve yönlendirmeleri kullanarak çok çeşitli senaryoları yönetebilir ve iş süreçlerinizi optimize edebilirsiniz.

Prosesler, Unix'te çalışan programlardır.

Unix'te prosesler (processes), çalışan programlardır ve sistemdeki her türlü görev veya iş yükü bir proses olarak yürütülür. Prosesler, Unix işletim sisteminin temel yapı taşlarından biridir ve işletim sistemi, bu proseslerin yönetimini sağlar. Prosesler hakkında daha derinlemesine bilgi verelim ve önemli kavramları inceleyelim.

### Proseslerin Temelleri

Bir proses, bir programın çalışan bir örneğidir. Bir program çalıştırıldığında, işletim sistemi tarafından bir proses oluşturulur. Her prosesin kendine özgü bir kimlik numarası (PID - Process ID) vardır. Prosesler, diğer proseslerle ve işletim sistemi ile etkileşime geçebilir.

#### Proses Oluşturma

Unix'te yeni bir proses oluşturmak için `fork` ve `exec` sistem çağrıları kullanılır. `fork` sistemi çağrısı, mevcut bir prosesin kopyasını oluşturarak yeni bir proses yaratır. `exec` sistemi çağrısı ise mevcut prosesin yürütülmekte olan programını yeni bir programla değiştirir.

```c
#include <stdio.h>
#include <unistd.h>

int main() {
    pid_t pid = fork();

    if (pid < 0) {
        // Hata durumu
        fprintf(stderr, "Fork failed\n");
        return 1;
    } else if (pid == 0) {
        // Çocuk proses
        execlp("/bin/ls", "ls", NULL);
    } else {
        // Ebeveyn proses
        wait(NULL);
        printf("Child process complete\n");
    }

    return 0;
}
```

Bu örnekte:
- `fork()` sistemi çağrısı, mevcut prosesi kopyalayarak bir çocuk proses (child process) oluşturur.
- `execlp()` sistemi çağrısı, çocuk proses içinde `ls` komutunu çalıştırır.
- Ebeveyn proses (parent process), çocuk prosesin tamamlanmasını `wait()` fonksiyonu ile bekler.

#### Proses Durumları

Unix'te prosesler farklı durumlarda olabilir:
- **Çalışan (Running)**: Proses, CPU üzerinde yürütülmektedir.
- **Bekleyen (Waiting/Sleeping)**: Proses, bir olayın gerçekleşmesini beklemektedir.
- **Durdurulmuş (Stopped)**: Proses, sinyaller tarafından durdurulmuştur.
- **Zombi (Zombie)**: Proses tamamlanmış ancak ebeveyn prosesi tarafından henüz temizlenmemiştir.

### Proses Yönetimi

Unix'te proses yönetimi, çeşitli komutlar ve araçlarla gerçekleştirilir.

#### `ps` Komutu

`ps` komutu, sistemde çalışan proseslerin durumunu gösterir.

```sh
ps -ef
```

Bu komut, tüm proseslerin ayrıntılı bir listesini sağlar.

#### `top` Komutu

`top` komutu, sistemdeki proseslerin dinamik bir görünümünü sağlar. Prosesler CPU ve bellek kullanımına göre sıralanır.

```sh
top
```

#### `kill` Komutu

`kill` komutu, proseslere sinyaller göndermek için kullanılır. Bir prosesi sonlandırmak için kullanılır.

```sh
kill -9 12345
```

Bu komut, PID'si 12345 olan prosesi zorla sonlandırır.

#### `nice` ve `renice` Komutları

`nice` ve `renice` komutları, proseslerin öncelik seviyelerini ayarlamak için kullanılır.

```sh
nice -n 10 komut
renice -n 15 -p 12345
```

Bu komutlar, bir prosesin önceliğini değiştirerek CPU zamanını daha verimli kullanmasını sağlar.

### Örnek Senaryo: Uzun Süreli İşlem ve Proses Yönetimi

Bir dosya indirme işlemi (`wget`) uzun sürebilir ve bu süre zarfında diğer işlemlerle etkileşime girmek isteyebilirsiniz. Bu durumda, işlemi arka planda çalıştırabilirsiniz.

```sh
wget http://example.com/bigfile.zip &
```

Bu komut, dosya indirme işlemini arka planda başlatır. Arka planda çalışan işlemi listelemek için `jobs` komutunu kullanabilirsiniz:

```sh
jobs
```

Arka planda çalışan işlemle ilgili daha fazla bilgi almak için `ps` komutunu kullanabilirsiniz:

```sh
ps -ef | grep wget
```

İşlemi duraklatmak (askıya almak) ve yeniden başlatmak için `kill` komutunu kullanabilirsiniz:

```sh
kill -STOP 12345  # İşlemi duraklatır
kill -CONT 12345  # İşlemi yeniden başlatır
```

### Özet

Unix'te prosesler, sistemde çalışan programlardır ve işletim sistemi tarafından yönetilirler. Proseslerin oluşturulması, yönetimi ve izlenmesi, Unix işletim sisteminin temel işlevlerinden biridir. `fork`, `exec`, `ps`, `top`, `kill`, `nice` ve diğer komutlar, proses yönetimi ve kontrolünde kullanılır. Proseslerin etkin bir şekilde yönetilmesi, Unix sisteminin verimliliğini ve kararlılığını sağlar. Bu bilgilerle, Unix'teki proseslerin nasıl çalıştığını ve nasıl yönetileceğini daha iyi anlayabilir ve uygulamalarınızı optimize edebilirsiniz.

Her prosesin bir PID (Process ID) numarası vardır.

Her prosesin bir PID (Process ID) numarası vardır ve bu, Unix işletim sistemi tarafından her yeni proses oluşturulduğunda atanan benzersiz bir kimlik numarasıdır. PID'ler, sistemde çalışan proseslerin izlenmesi ve yönetilmesi için kullanılır. PID'ler hakkında daha derinlemesine bilgi verelim ve bu konuda örneklerle açıklamalar yapalım.

### PID (Process ID) Nedir?

PID, her prosese işletim sistemi tarafından atanan benzersiz bir tanımlayıcıdır. Bu numara, sistemdeki proseslerin izlenmesi ve yönetilmesi için kritik öneme sahiptir. PID'ler, proseslerin belirlenmesi, kontrol edilmesi ve izlenmesi için kullanılır.

### PID'lerin Kullanımı

PID'ler, çeşitli Unix komutları ve sistem çağrıları ile kullanılarak prosesler üzerinde çeşitli işlemler gerçekleştirilebilir.

#### `ps` Komutu ile PID Görüntüleme

`ps` komutu, sistemde çalışan proseslerin durumunu gösterir. PID'leri görmek için `ps` komutunu kullanabilirsiniz:

```sh
ps -ef
```

Bu komut, sistemde çalışan tüm proseslerin detaylı bir listesini sağlar. Örnek çıktı:

```
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 08:44 ?        00:00:01 /sbin/init
root       569     1  0 08:44 ?        00:00:00 /usr/lib/systemd/systemd-journald
user      1234  1200  0 09:01 pts/1    00:00:00 bash
user      1250  1234  0 09:02 pts/1    00:00:00 ps -ef
```

Bu çıktıda:
- `UID`: Prosesin sahibi olan kullanıcı.
- `PID`: Prosesin kimlik numarası.
- `PPID`: Ebeveyn prosesin kimlik numarası.
- `CMD`: Çalıştırılan komut.

#### Prosesleri `kill` Komutu ile Yönetme

Bir prosesi sonlandırmak veya belirli bir sinyal göndermek için `kill` komutunu kullanabilirsiniz. Örneğin, PID'si 1234 olan bir prosesi sonlandırmak için:

```sh
kill 1234
```

Eğer prosesin sonlandırılması gerekiyorsa, `-9` sinyalini kullanabilirsiniz:

```sh
kill -9 1234
```

#### `pgrep` ve `pkill` Komutları

`pgrep` komutu, belirli bir adı taşıyan proseslerin PID'lerini bulur:

```sh
pgrep bash
```

Bu komut, çalışan tüm `bash` proseslerinin PID'lerini listeler. `pkill` komutu ise adı belirtilen prosesleri sonlandırır:

```sh
pkill bash
```

Bu komut, tüm `bash` proseslerini sonlandırır.

### Örnek Senaryo: Proses İzleme ve Yönetimi

Bir web sunucusunun çalıştığını ve bu sunucunun PID'sini bulup yönetmek istediğinizi varsayalım.

#### Adım 1: PID'yi Bulma

İlk olarak, web sunucusunun çalışıp çalışmadığını ve PID'sini bulmak için `ps` veya `pgrep` komutlarını kullanabilirsiniz:

```sh
ps -ef | grep apache2
```

veya

```sh
pgrep apache2
```

#### Adım 2: Prosesleri İzleme

Web sunucusunun performansını ve kaynak kullanımını izlemek için `top` komutunu kullanabilirsiniz:

```sh
top -p <PID>
```

Bu komut, belirli bir PID'ye sahip prosesi izler.

#### Adım 3: Prosesleri Yönetme

Web sunucusunda bir sorun olduğunu ve yeniden başlatılması gerektiğini varsayalım. Önce mevcut prosesi sonlandırıp ardından yeniden başlatabilirsiniz:

```sh
sudo kill -HUP <PID>
```

Bu komut, `SIGHUP` sinyali göndererek web sunucusunu yeniden başlatır.

### Özet

PID'ler, Unix işletim sisteminde proseslerin izlenmesi ve yönetilmesi için hayati öneme sahiptir. Her prosesin benzersiz bir PID'si vardır ve bu PID'ler, proseslerin izlenmesi, kontrol edilmesi ve yönetilmesi için kullanılır. `ps`, `kill`, `pgrep`, `pkill`, ve `top` gibi komutlar, proseslerin yönetiminde ve izlenmesinde kullanılır. Bu bilgilerle, Unix sistemlerinde proses yönetimini daha etkili bir şekilde gerçekleştirebilirsiniz.

Fork ve exec, yeni prosesler oluşturmak için kullanılan temel mekanizmalardır.

Unix işletim sisteminde yeni prosesler oluşturmak için kullanılan temel mekanizmalar `fork` ve `exec` sistem çağrılarıdır. Bu iki sistem çağrısı, proseslerin nasıl oluşturulduğunu ve yürütüldüğünü kontrol etmek için kullanılır. Her iki mekanizma da proses yönetiminin temel yapı taşlarıdır. Şimdi bu mekanizmaları derinlemesine inceleyelim ve kod örnekleriyle açıklayalım.

### `fork` Sistem Çağrısı

`fork`, mevcut bir prosesi kopyalayarak yeni bir proses (çocuk proses) oluşturur. `fork` çağrısı, yeni bir proses oluşturmanın tek yoludur ve çocuk proses ebeveyn prosesin bir kopyasıdır. Yeni prosesin PID'si farklıdır, ancak belleğin bir kopyası dahil olmak üzere her şey aynıdır.

#### `fork` Kullanımı

`fork` çağrısı, aşağıdaki gibi kullanılır:

```c
#include <stdio.h>
#include <unistd.h>

int main() {
    pid_t pid = fork();

    if (pid < 0) {
        // Hata durumu
        fprintf(stderr, "Fork failed\n");
        return 1;
    } else if (pid == 0) {
        // Çocuk proses
        printf("Child process: PID = %d\n", getpid());
    } else {
        // Ebeveyn proses
        printf("Parent process: PID = %d, Child PID = %d\n", getpid(), pid);
    }

    return 0;
}
```

Bu örnekte:
- `fork()` çağrısı, mevcut prosesi kopyalayarak yeni bir çocuk proses oluşturur.
- Eğer `fork` başarısız olursa, `pid` değeri negatif olur ve hata mesajı yazdırılır.
- `pid` değeri sıfır ise, çocuk proses içindeyizdir ve çocuk prosesin PID'si yazdırılır.
- `pid` değeri sıfırdan büyük ise, ebeveyn proses içindeyizdir ve ebeveyn prosesin PID'si ile çocuk prosesin PID'si yazdırılır.

### `exec` Sistem Çağrısı

`exec` sistem çağrısı, mevcut prosesin belleğinde yüklü olan programı yeni bir programla değiştirir. `exec` çağrısı, yeni bir prosesi başlatmak için değil, mevcut bir prosesi değiştirmek için kullanılır. `exec` ailesinde birkaç farklı işlev bulunur (`execl`, `execv`, `execle`, `execve`, vb.), ancak hepsi aynı temel amacı taşır.

#### `exec` Kullanımı

Bir `exec` çağrısı aşağıdaki gibi yapılabilir:

```c
#include <stdio.h>
#include <unistd.h>

int main() {
    pid_t pid = fork();

    if (pid < 0) {
        // Hata durumu
        fprintf(stderr, "Fork failed\n");
        return 1;
    } else if (pid == 0) {
        // Çocuk proses
        execlp("/bin/ls", "ls", NULL);
    } else {
        // Ebeveyn proses
        wait(NULL);
        printf("Child process complete\n");
    }

    return 0;
}
```

Bu örnekte:
- `fork()` çağrısı, yeni bir çocuk proses oluşturur.
- Çocuk proses içinde `execlp()` çağrısı, mevcut prosesi `/bin/ls` programıyla değiştirir.
- Ebeveyn proses, çocuk prosesin tamamlanmasını `wait()` fonksiyonu ile bekler ve ardından bir mesaj yazdırır.

### Örnek Senaryo: `fork` ve `exec` ile Komut Yürütme

Bir Unix komutunu yeni bir çocuk proses içinde çalıştırmak için `fork` ve `exec` sistem çağrılarını birlikte kullanabilirsiniz. Örneğin, bir `ls` komutunu çalıştırmak:

```c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

int main() {
    pid_t pid = fork();

    if (pid < 0) {
        // Hata durumu
        perror("Fork failed");
        return 1;
    } else if (pid == 0) {
        // Çocuk proses
        printf("Executing ls command...\n");
        execlp("ls", "ls", NULL);
        // Eğer exec başarısız olursa
        perror("exec failed");
        exit(1);
    } else {
        // Ebeveyn proses
        wait(NULL);
        printf("Child process complete\n");
    }

    return 0;
}
```

Bu örnekte:
- `fork()` yeni bir çocuk proses oluşturur.
- Çocuk proses içinde `execlp("ls", "ls", NULL)` çağrısı, mevcut prosesi `ls` komutuyla değiştirir.
- Ebeveyn proses, çocuk prosesin tamamlanmasını `wait()` ile bekler ve ardından bir tamamlanma mesajı yazdırır.

### Özet

`fork` ve `exec` sistem çağrıları, Unix'te yeni prosesler oluşturmak ve mevcut prosesleri değiştirmek için kullanılan temel mekanizmalardır. `fork`, mevcut bir prosesi kopyalayarak yeni bir proses oluşturur. `exec`, mevcut prosesi yeni bir programla değiştirir. Bu iki çağrı, birlikte kullanılarak çok çeşitli işlemleri ve görevleri gerçekleştirmek için güçlü araçlar sunar. Bu bilgileri ve örnekleri kullanarak, Unix sistemlerinde proses yönetimini daha etkili bir şekilde gerçekleştirebilirsiniz.

Sinyaller, prosesler arası iletişim için kullanılır.

Unix ve Unix benzeri işletim sistemlerinde sinyaller (signals), prosesler arası iletişim (IPC - Inter-Process Communication) için kullanılır. Sinyaller, bir prosesin diğerine veya işletim sisteminin bir prosese belirli bir olayın gerçekleştiğini bildirmesini sağlar. Sinyaller, genellikle asenkron olarak iletilir ve alıcı proses, sinyali aldığında belirli bir eylemi gerçekleştirmek üzere yapılandırılabilir. İşte sinyaller hakkında daha detaylı bilgi ve örneklerle açıklamalar:

### Temel Sinyaller ve Kullanımları

#### Yaygın Sinyaller
- **SIGINT** (2): Kullanıcı tarafından `Ctrl+C` tuş kombinasyonu ile gönderilir. Genellikle bir prosesi sonlandırmak için kullanılır.
- **SIGTERM** (15): Bir prosesi düzgün bir şekilde sonlandırmak için kullanılır. Proses bu sinyali işleyip, temizleme işlemlerini gerçekleştirebilir.
- **SIGKILL** (9): Bir prosesi hemen sonlandırmak için kullanılır. Proses bu sinyali işleyemez.
- **SIGSTOP** (19): Bir prosesi durdurmak (askıya almak) için kullanılır. Proses bu sinyali işleyemez.
- **SIGCONT** (18): Durdurulmuş bir prosesi devam ettirmek için kullanılır.

#### Sinyal Gönderme

Sinyal göndermek için `kill` komutu veya `kill` sistem çağrısı kullanılır. Örneğin, PID'si 1234 olan bir prosese SIGINT sinyali göndermek için:

```sh
kill -SIGINT 1234
```

veya kısaltılmış haliyle:

```sh
kill -2 1234
```

### Sinyal İşleme

Prosesler, belirli sinyalleri yakalamak ve işlemek için sinyal işleyiciler (signal handlers) tanımlayabilirler. Bu, `signal` veya `sigaction` sistem çağrıları kullanılarak yapılır.

#### `signal` Kullanımı

```c
#include <stdio.h>
#include <signal.h>
#include <unistd.h>

// Sinyal işleyici fonksiyon
void handle_signal(int sig) {
    printf("Caught signal %d\n", sig);
}

int main() {
    // SIGINT sinyali için işleyici tanımla
    signal(SIGINT, handle_signal);

    while (1) {
        printf("Running...\n");
        sleep(1);
    }

    return 0;
}
```

Bu örnekte:
- `signal(SIGINT, handle_signal)` çağrısı, SIGINT sinyali (genellikle `Ctrl+C` ile gönderilir) alındığında `handle_signal` fonksiyonunun çağrılmasını sağlar.
- `handle_signal` fonksiyonu, sinyal numarasını yazdırır.
- Proses, sonsuz bir döngü içinde her saniye "Running..." mesajını yazdırır.

#### `sigaction` Kullanımı

`sigaction`, `signal` fonksiyonuna göre daha esnek ve güvenlidir:

```c
#include <stdio.h>
#include <signal.h>
#include <unistd.h>

// Sinyal işleyici fonksiyon
void handle_signal(int sig) {
    printf("Caught signal %d\n", sig);
}

int main() {
    struct sigaction sa;

    sa.sa_handler = handle_signal;
    sa.sa_flags = 0; // veya SA_RESTART
    sigemptyset(&sa.sa_mask);

    if (sigaction(SIGINT, &sa, NULL) == -1) {
        perror("sigaction");
        return 1;
    }

    while (1) {
        printf("Running...\n");
        sleep(1);
    }

    return 0;
}
```

Bu örnekte:
- `sigaction` yapısı kullanılarak, SIGINT sinyali için `handle_signal` işleyicisi atanır.
- `sigemptyset(&sa.sa_mask)`, sinyal işleyici çalışırken bloke edilecek sinyalleri tanımlar.
- `sigaction(SIGINT, &sa, NULL)`, SIGINT sinyali alındığında `handle_signal` fonksiyonunun çağrılmasını sağlar.

### Örnek Senaryo: Prosesler Arası İletişim

İki prosesin birbirine sinyal göndererek iletişim kurmasını sağlayan bir örnek düşünelim.

#### Proses 1: Sinyal Gönderen

```c
#include <stdio.h>
#include <signal.h>
#include <unistd.h>

int main() {
    pid_t pid;

    printf("Enter PID of the receiver process: ");
    scanf("%d", &pid);

    // Alıcı prosese SIGUSR1 sinyali gönder
    kill(pid, SIGUSR1);

    return 0;
}
```

#### Proses 2: Sinyal Alan

```c
#include <stdio.h>
#include <signal.h>
#include <unistd.h>

// Sinyal işleyici fonksiyon
void handle_signal(int sig) {
    if (sig == SIGUSR1) {
        printf("Received SIGUSR1 signal\n");
    }
}

int main() {
    struct sigaction sa;

    sa.sa_handler = handle_signal;
    sa.sa_flags = 0; // veya SA_RESTART
    sigemptyset(&sa.sa_mask);

    if (sigaction(SIGUSR1, &sa, NULL) == -1) {
        perror("sigaction");
        return 1;
    }

    printf("Waiting for signals...\n");

    while (1) {
        pause(); // Sinyal bekle
    }

    return 0;
}
```

Bu örnekte:
- İlk proses, kullanıcıdan alıcı prosesin PID'sini alır ve SIGUSR1 sinyali gönderir.
- İkinci proses, SIGUSR1 sinyalini yakalamak ve işlemek için bir sinyal işleyici tanımlar.
- İkinci proses, sinyali aldığında "Received SIGUSR1 signal" mesajını yazdırır.

### Özet

Unix'te sinyaller, prosesler arası iletişim için kullanılan önemli araçlardır. Sinyaller, bir prosesin diğerine veya işletim sisteminin bir prosese belirli bir olayın gerçekleştiğini bildirmesini sağlar. `kill`, `signal`, ve `sigaction` gibi fonksiyonlar ve komutlar, sinyal göndermek ve işlemek için kullanılır. Bu bilgiler ve örnekler, sinyallerin nasıl çalıştığını ve prosesler arası iletişimde nasıl kullanılabileceğini anlamanızı sağlar.

man komutu, Unix'in dahili dokümantasyon sistemidir.



Unix, zaman paylaşımlı sistemler için tasarlanmıştır.



Çok sayıda Unix türevi vardır: Linux, BSD, macOS vb.



POSIX, Unix sistemler için standartları belirler.



Sembolik bağlantılar (symbolic links) dosya sisteminde esneklik sağlar.



Cron, zamanlanmış görevleri yönetmek için kullanılır.



X Window System, Unix'in grafik kullanıcı arayüzü (GUI) altyapısıdır.



vi ve emacs, Unix'in popüler metin düzenleyicileridir.



grep, sed, awk gibi metin işleme araçları Unix'in güçlü yanlarındandır.



Regular expressions (düzenli ifadeler) Unix araçlarında yaygın kullanılır.



find komutu, dosya ve dizinleri aramak için kullanılır.



tar, Unix sistemlerde arşivleme için kullanılan standarttır.



NFS (Network File System), ağ üzerinden dosya paylaşımı sağlar.



SSH, güvenli uzaktan erişim için kullanılır.



Unix sistemlerde çok sayıda daemon (arka plan hizmeti) çalışır.



/etc dizini, sistem konfigürasyon dosyalarını içerir.



/home dizini, kullanıcı ev dizinlerini barındırır.



/var dizini, değişken verileri (log dosyaları gibi) saklar.



/tmp dizini, geçici dosyalar için kullanılır.



Unix sistemlerde birden çok çalışma seviyesi (runlevel) vardır.



init, geleneksel Unix sistemlerde ilk çalışan prosestir.



systemd, modern Unix sistemlerinde init'in yerini almıştır.



Unix'te prosesler arası iletişim için çeşitli mekanizmalar vardır: borular, soketler, sinyaller vb.



nice komutu, proseslerin önceliğini ayarlamak için kullanılır.



top komutu, sistem kaynaklarının kullanımını izlemek için kullanılır.



Unix sistemlerde swap alanı, sanal bellek için kullanılır.



fsck komutu, dosya sistemi tutarlılığını kontrol eder ve onarır.



df komutu, disk kullanımını gösterir.



du komutu, dizin ve dosyaların boyutunu gösterir.



chmod komutu, dosya ve dizin izinlerini değiştirmek için kullanılır.



chown komutu, dosya ve dizinlerin sahipliğini değiştirmek için kullanılır.



umask, yeni oluşturulan dosya ve dizinlerin varsayılan izinlerini belirler.



Unix sistemlerde çevre değişkenleri (environment variables) önemli bir rol oynar.



.bashrc ve .bash_profile, kullanıcı oturum ayarlarını içerir.



/dev dizini, aygıt dosyalarını içerir.



/proc dizini, çalışan sistemin ve proseslerin bilgilerini içerir.



Unix sistemlerde çekirdek modülleri, çalışma zamanında yüklenebilir.



lsmod komutu, yüklü çekirdek modüllerini listeler.



ps komutu, çalışan prosesleri gösterir.



kill komutu, proseslere sinyal göndermek için kullanılır.



Unix sistemlerde inode'lar, dosya sistemi meta verilerini saklar.



ln komutu, sabit ve sembolik bağlantılar oluşturmak için kullanılır.



mount komutu, dosya sistemlerini bağlamak için kullanılır.



umount komutu, bağlı dosya sistemlerini ayırmak için kullanılır.



ulimit, kullanıcı ve proseslerin kaynak kullanımını sınırlar.



crontab, periyodik görevleri zamanlamak için kullanılır.



at komutu, tek seferlik görevleri zamanlamak için kullanılır.



iptables, Unix sistemlerde güvenlik duvarı yapılandırması için kullanılır.



sed, akış editörü olarak metin manipülasyonu için kullanılır.



awk, metin tabanlı veri işleme için güçlü bir araçtır.



tail komutu, dosyanın son satırlarını görüntülemek için kullanılır.



head komutu, dosyanın ilk satırlarını görüntülemek için kullanılır.



xargs, komut satırı argümanlarını işlemek için kullanılır.



Unix sistemlerde RAID, veri depolama güvenilirliği için kullanılır.



LVM (Logical Volume Manager), esnek disk yönetimi sağlar.



rsync, dosya senkronizasyonu ve yedekleme için kullanılır.



tcpdump, ağ trafiğini analiz etmek için kullanılır.



netstat, ağ bağlantılarını ve istatistiklerini gösterir.



lsof, açık dosyaları listelemek için kullanılır.



strace, sistem çağrılarını ve sinyalleri izlemek için kullanılır.



gcc, GNU Compiler Collection, Unix sistemlerde yaygın kullanılan bir derleyicidir.



chroot, bir prosesi farklı bir kök dizinle çalıştırmak için kullanılır.



Nice değeri, proseslerin CPU önceliğini belirler (-20 en yüksek, 19 en düşük).



/etc/passwd dosyası, kullanıcı hesap bilgilerini saklar.



/etc/shadow dosyası, şifrelenmiş kullanıcı parolalarını içerir.



SUID (Set User ID) biti, bir programın sahibinin izinleriyle çalışmasını sağlar.



SGID (Set Group ID) biti, bir programın grup izinleriyle çalışmasını sağlar.



ptrace sistem çağrısı, hata ayıklama için prosesleri izlemeye olanak tanır.



setuid() ve setgid() sistem çağrıları, proses kimliğini değiştirmek için kullanılır.



mmap() sistem çağrısı, bellek eşlemesi için kullanılır.



fcntl() sistem çağrısı, dosya tanımlayıcılarını kontrol etmek için kullanılır.



epoll, yüksek ölçekli I/O olaylarını izlemek için kullanılan bir API'dir.



Unix domain soketleri, aynı makinedeki prosesler arası iletişim için kullanılır.



FIFOs (named pipes), ilişkili olmayan prosesler arasında veri akışı sağlar.



Semaphores, paylaşılan kaynakların senkronizasyonu için kullanılır.



Shared memory, prosesler arası hızlı veri paylaşımı sağlar.



inotify, dosya sistemi olaylarını izlemek için kullanılır.



User namespaces, ayrıcalıklı işlemleri güvenli bir şekilde yalıtır.



Control groups (cgroups), proses gruplarının kaynak kullanımını sınırlar.



Namespaces, proses yalıtımı için kullanılır (PID, network, mount vb.).



Containers, namespaces ve cgroups kullanarak hafif sanallaştırma sağlar.

Assembly dili



Assembly dili, düşük seviyeli bir programlama dili olup, bilgisayarın donanım mimarisine özgü talimatları doğrudan içerir. Bir bilgisayarın işlemcisi tarafından doğrudan anlaşılabilecek olan makine diline çok yakındır. Assembly dili, genellikle sistem düzeyindeki programlama, sürücülerin geliştirilmesi, gömülü sistemler ve performans gerektiren uygulamalar için kullanılır. Bu dil, yüksek seviyeli dillerde bulunan abstraksiyonların çoğundan yoksun olduğundan, programcının donanım üzerinde daha fazla kontrol sahibi olmasını sağlar ancak bu, aynı zamanda daha fazla dikkat ve uzmanlık gerektirir.


Assembly dilinin temel özellikleri şunlardır:


Yakın Donanım Erişimi: Bilgisayarın CPU'su ve belleği gibi donanım bileşenlerine doğrudan erişim sağlar.

Düşük Seviye Kontrol: Bellek yönetimi ve işlemci talimatları üzerinde doğrudan kontrol imkanı sunar.

Performans: Yüksek seviye dillerden daha hızlı çalışan programlar oluşturabilir.

Portabilite Eksikliği: Yazılan kod genellikle belirli bir işlemci mimarisine özgü olduğu için, farklı sistemler arasında taşınabilirliği sınırlıdır.

Karmaşıklık ve Zorluk: Anlaşılması ve kullanılması daha zor olabilir çünkü donanımın ayrıntılı bilgisini gerektirir.

Assembly dilinde yazılmış bir program, genellikle bir assembler tarafından makine diline çevrilir. Bu süreçte, insan tarafından okunabilir assembly kodu, CPU'nun anlayabileceği makine koduna dönüştürülür. Assembly, özellikle eski zamanlarda, kaynakların kısıtlı olduğu durumlarda veya


çok spesifik donanım işlemleri için tercih edilirdi. Günümüzde ise genellikle sistem programlaması, donanım sürücüleri, gerçek zamanlı uygulamalar ve yüksek performans gerektiren bilgisayar oyunları gibi alanlarda kullanılmaktadır.


Assembly dili öğrenmek, programcıya bilgisayarın nasıl çalıştığına dair derin bir anlayış kazandırır ve daha verimli programlama teknikleri geliştirmesine yardımcı olur. Ancak, bu dilin karmaşıklığı ve öğrenme eğrisi nedeniyle, genellikle belirli ihtiyaçları olan deneyimli programcılar tarafından tercih edilir.


Assembly diliyle çalışmanın temelini, işlemci mimarisine ve makine talimatlarına aşina olmak oluşturur. Her işlemci mimarisi, kendine özgü bir set komutları (instruction set) içerir. Bu komutlar, genellikle oldukça düşük seviyeli ve basit işlemlerdir, örneğin bir hafıza konumundan diğerine veri taşımak, aritmetik işlemler yapmak veya mantıksal işlemler gerçekleştirmek. Assembly dili, bu talimatları insan tarafından okunabilir bir biçimde ifade eder.


Assembly dilinin temel kavramları şunlardır:


Registerlar: CPU'nun içinde hızlı erişim için kullanılan küçük hafıza alanlarıdır. Bu registerlar, veri depolama, adres gösterme veya aritmetik işlemler için kullanılır.


Opcode (Operation Code): Her bir assembly talimatının işlemciye ne yapması gerektiğini belirten bir koddur. Örneğin, MOV, ADD, SUB gibi.


Operandlar: Opcode'ların üzerinde işlem yapacağı verilerdir. Bunlar doğrudan sayılar (literals), hafıza adresleri veya registerlar olabilir.


Sembolik Adresleme: Programcının hafıza adreslerini isimlendirmesine izin verir, böylece kod daha okunabilir ve yönetilebilir hale gelir.


Assembly Direktifleri: Assembler'a yönergeler sağlar. Bunlar, kodun nasıl derleneceğini veya monte edileceğini kontrol eden komutlardır.


Makro Komutlar: Birden çok assembly talimatını tek bir komut olarak gruplamaya olanak tanır, böylece kod tekrarı azaltılır ve okunabilirlik artar.


Assembly dilinin kullanımı günümüzde daha sınırlı olsa da, bazı durumlarda hala vazgeçilmezdir. Örneğin, donanım seviyesinde hata ayıklama, reverse engineering, sistem güvenliği ve optimizasyon gibi alanlarda oldukça önemlidir. Ayrıca, yüksek seviye programlama dillerinin altında yatan temelleri anlamak için de değerlidir. Yüksek seviye dillerin sağladığı abstraksiyonların altındaki donanım işlemlerini kavramak, bir programcının daha derin teknik bilgi ve beceri kazanmasını sağlar.



Örnek bir assembly kodu ve satır satır açıklaması


Assembly kodunun örnek bir parçasını ve her bir satırın açıklamasını aşağıda bulabilirsiniz. Bu örnek, x86 mimarisini temel alır ve basit bir toplama işlemi gerçekleştirir. x86 mimarisi, Intel ve AMD tarafından üretilen işlemcilerde yaygın olarak kullanılan bir mimaridir.


section .data       ; Veri bölümü başlangıcı

num1    db  5       ; num1 adında bir bayt (byte) tanımla ve değerini 5 yap

num2    db  3       ; num2 adında bir bayt tanımla ve değerini 3 yap


section .text       ; Kod bölümü başlangıcı

global _start       ; _start etiketini global yap, yani programın başlangıç noktası


_start:             ; Programın başladığı yer

    mov al, [num1]  ; num1'in değerini al baytında sakla

    add al, [num2]  ; al baytındaki değeri num2'nin değeri ile topla

    mov [num1], al  ; Sonucu num1'in adresine geri yaz


    ; Programı sonlandır (Linux sistemlerde)

    mov eax, 1      ; Sistemi sonlandırma çağrısının kodu

    mov ebx, 0      ; Çıkış kodu olarak 0 (başarılı sonlandırma)

    int 0x80        ; Kesme (interrupt) çağrısını yaparak sistemi sonlandır

Her bir satırın açıklaması:


section .data: Veri bölümünün başlangıcını belirtir. Burada sabit değerler ve değişkenler tanımlanır.


num1 db 5: num1 adında bir bayt boyutunda değişken tanımlar ve değerini 5 olarak ayarlar.


num2 db 3: num2 adında başka bir bayt boyutunda değişken tanımlar ve değerini 3 olarak ayarlar.


section .text: Kod bölümünün başlangıcını işaret eder. Burada programın asıl işlevsel kodları bulunur.


global _start: _start etiketini global yapar. Bu, programın çalıştırılacağı başlangıç noktasını belirtir.


_start:: Programın çalışmaya başladığı yer. Bu etiket kodun geri kalanını takip eder.


mov al, [num1]: num1de saklı olan değeri al registerına kopyalar.


add al, [num2]: al registerındaki değere num2deki değeri ekler.


mov [num1], al: Sonuç olarak elde ed


ilen değeri num1in saklandığı yere geri yazar. Bu, al registerındaki değeri num1 değişkeninin hafıza adresine kopyalar.


mov eax, 1: Bu ve sonraki iki satır, Linux işletim sistemi üzerinde programın düzgün bir şekilde sonlandırılması için gerekli işlemleri yapar. Burada eax registerına 1 değeri atanır, bu da sistem çağrısının (system call) çıkış (exit) fonksiyonunu temsil eder.


mov ebx, 0: Çıkış kodu olarak 0 değeri ebx registerına atanır. 0 genellikle başarılı bir çıkışı gösterir.


int 0x80: Bu satır bir kesme (interrupt) çağrısını tetikler. Bu kesme, eaxde tanımlanan sistem çağrısını (bu durumda programın sonlandırılması) işletim sistemine bildirir.


Bu örnek, Assembly diliyle yazılmış oldukça basit bir programın nasıl çalıştığını gösterir. Assembly dilinde, işlemler genellikle çok düşük seviyede ve doğrudan donanımla ilgili olarak gerçekleştirilir. Bu sebeple, Assembly dili öğrenmek ve kullanmak, yüksek seviye programlama dillerine kıyasla daha karmaşık ve detay odaklıdır. Yüksek seviye diller genelde bu tür düşük seviye işlemleri gizler ve programcıya daha soyut bir çalışma ortamı sunar. Bununla birlikte, Assembly dilinde programlama yapmak, bilgisayarın nasıl çalıştığına dair derin bir anlayış kazandırır ve performans kritik uygulamalarda çok detaylı optimizasyonlar yapma imkanı sunar.

Rastgele İçerik

© tüm hakları saklıdır
made with by templateszoo