<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://program.sonsuz.us/feed.xml" rel="self" type="application/atom+xml" /><link href="https://program.sonsuz.us/" rel="alternate" type="text/html" /><updated>2026-09-27T12:05:42+00:00</updated><id>https://program.sonsuz.us/feed.xml</id><title type="html">SonsuzUs</title><subtitle>Programlama ve Yazılım</subtitle><author><name>Sonsuz Us</name></author><entry><title type="html">eBPF ile Çekirdeği Yeniden Derlemeden Ağ Paketlerini Manipüle Etmek</title><link href="https://program.sonsuz.us/posts/ebpf-ile-cekirdegi-yeniden-derlemeden-ag-paketlerini-manipule-etmek/" rel="alternate" type="text/html" title="eBPF ile Çekirdeği Yeniden Derlemeden Ağ Paketlerini Manipüle Etmek" /><published>2026-09-27T00:00:00+00:00</published><updated>2026-09-27T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/ebpf-ile-cekirdegi-yeniden-derlemeden-ag-paketlerini-manipule-etmek</id><content type="html" xml:base="https://program.sonsuz.us/posts/ebpf-ile-cekirdegi-yeniden-derlemeden-ag-paketlerini-manipule-etmek/"><![CDATA[<p>Linux ağ yığınında paketleri yakalamak, filtrelemek veya yönlendirmek eskiden çekirdek modülü geliştirmeyi ve bazen çekirdeği yeniden derlemeyi gerektiriyordu. eBPF sayesinde artık doğrulanmış küçük programları çekirdek içinde güvenli biçimde çalıştırabiliyoruz. Böylece DDoS filtrelerinden gecikme ölçümüne kadar pek çok işi, kaynak koduna neşter vurmadan gerçekleştirmek mümkün.</p>

<p>``</p>

<h2 id="ebpf-tam-olarak-nedir">eBPF tam olarak nedir?</h2>

<p>eBPF, kullanıcı alanında hazırlanan programların Linux çekirdeğindeki belirli kancalara yüklenmesini sağlayan bir çalışma ortamıdır. İsmindeki BPF, tarihsel olarak “Berkeley Packet Filter” anlamına gelse de teknoloji bugün ağ paketlerinin çok ötesine uzanır: sistem çağrıları, süreçler, dosya erişimleri ve performans olayları da izlenebilir.</p>

<p>“Çekirdeğe dokunmadan” ifadesi, kodun çekirdek dışında çalıştığı anlamına gelmez. eBPF programı çekirdek bağlamında çalışır; ancak çekirdek kaynak kodunu değiştirmeye veya özel bir modül yüklemeye gerek bırakmaz. Program yüklenmeden önce <strong>verifier</strong> tarafından incelenir. Geçersiz bellek erişimi, güvensiz işaretçi kullanımı veya sonlanmama riski varsa program reddedilir.</p>

<table>
  <thead>
    <tr>
      <th>Yaklaşım</th>
      <th>Çalışma noktası</th>
      <th style="text-align: right">Performans</th>
      <th>Risk ve esneklik</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Kullanıcı alanı yakalama</td>
      <td>Ağ yığınından sonra</td>
      <td style="text-align: right">Orta</td>
      <td>Güvenli, kopyalama maliyetli</td>
    </tr>
    <tr>
      <td>Netfilter/iptables</td>
      <td>Çekirdek ağ yığını</td>
      <td style="text-align: right">Yüksek</td>
      <td>Kurallarla sınırlı</td>
    </tr>
    <tr>
      <td>Çekirdek modülü</td>
      <td>Çekirdek içinde</td>
      <td style="text-align: right">Çok yüksek</td>
      <td>Hata tüm sistemi etkileyebilir</td>
    </tr>
    <tr>
      <td>eBPF/XDP</td>
      <td>Sürücüye çok yakın</td>
      <td style="text-align: right">Çok yüksek</td>
      <td>Verifier ile denetimli</td>
    </tr>
  </tbody>
</table>

<h2 id="xdp-neden-bu-kadar-hızlı">XDP neden bu kadar hızlı?</h2>

<p>XDP, yani <strong>eXpress Data Path</strong>, paketi ağ sürücüsünden gelir gelmez işleyebilir. Paket henüz <code class="language-plaintext highlighter-rouge">sk_buff</code> yapısına dönüştürülmeden karar verildiği için ayırma, kopyalama ve ağ yığını maliyetleri azaltılır.</p>

<p>Bir paketin yaklaşık işlem maliyetini şöyle düşünebiliriz:</p>

\[T_{toplam} = T_{alma} + T_{ayrıştırma} + T_{karar} + T_{yönlendirme}\]

<p>XDP özellikle $T_{ayrıştırma}$ ve $T_{yönlendirme}$ bileşenlerini küçültür. Program paketi kabul etmek için <code class="language-plaintext highlighter-rouge">XDP_PASS</code>, düşürmek için <code class="language-plaintext highlighter-rouge">XDP_DROP</code>, başka arayüze göndermek için <code class="language-plaintext highlighter-rouge">XDP_REDIRECT</code> döndürebilir.</p>

<p>Aşağıdaki orta düzey örnek, IPv4 UDP paketlerini erken aşamada düşürür:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;linux/bpf.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;linux/if_ether.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;linux/ip.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;linux/udp.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;bpf/bpf_helpers.h&gt;</span><span class="cp">
</span>
<span class="n">SEC</span><span class="p">(</span><span class="s">"xdp"</span><span class="p">)</span>
<span class="kt">int</span> <span class="nf">drop_udp</span><span class="p">(</span><span class="k">struct</span> <span class="n">xdp_md</span> <span class="o">*</span><span class="n">ctx</span><span class="p">)</span>
<span class="p">{</span>
    <span class="kt">void</span> <span class="o">*</span><span class="n">data</span> <span class="o">=</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)(</span><span class="kt">long</span><span class="p">)</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">data</span><span class="p">;</span>
    <span class="kt">void</span> <span class="o">*</span><span class="n">data_end</span> <span class="o">=</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)(</span><span class="kt">long</span><span class="p">)</span><span class="n">ctx</span><span class="o">-&gt;</span><span class="n">data_end</span><span class="p">;</span>
    <span class="k">struct</span> <span class="n">ethhdr</span> <span class="o">*</span><span class="n">eth</span> <span class="o">=</span> <span class="n">data</span><span class="p">;</span>

    <span class="k">if</span> <span class="p">((</span><span class="kt">void</span> <span class="o">*</span><span class="p">)(</span><span class="n">eth</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">data_end</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">XDP_ABORTED</span><span class="p">;</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">eth</span><span class="o">-&gt;</span><span class="n">h_proto</span> <span class="o">!=</span> <span class="n">__constant_htons</span><span class="p">(</span><span class="n">ETH_P_IP</span><span class="p">))</span>
        <span class="k">return</span> <span class="n">XDP_PASS</span><span class="p">;</span>

    <span class="k">struct</span> <span class="n">iphdr</span> <span class="o">*</span><span class="n">ip</span> <span class="o">=</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)(</span><span class="n">eth</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">((</span><span class="kt">void</span> <span class="o">*</span><span class="p">)(</span><span class="n">ip</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">data_end</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">XDP_ABORTED</span><span class="p">;</span>

    <span class="k">return</span> <span class="n">ip</span><span class="o">-&gt;</span><span class="n">protocol</span> <span class="o">==</span> <span class="n">IPPROTO_UDP</span> <span class="o">?</span> <span class="n">XDP_DROP</span> <span class="o">:</span> <span class="n">XDP_PASS</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">char</span> <span class="n">LICENSE</span><span class="p">[]</span> <span class="n">SEC</span><span class="p">(</span><span class="s">"license"</span><span class="p">)</span> <span class="o">=</span> <span class="s">"GPL"</span><span class="p">;</span>
</code></pre></div></div>

<p>Sınır kontrolleri yalnızca iyi programlama alışkanlığı değildir; verifier, <code class="language-plaintext highlighter-rouge">data_end</code> kontrolü bulunmayan paket erişimini kabul etmez. Kod Clang ile eBPF bytecode’una çevrilip bir arayüze bağlanabilir:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>clang <span class="nt">-O2</span> <span class="nt">-g</span> <span class="nt">-target</span> bpf <span class="nt">-c</span> filter.c <span class="nt">-o</span> filter.o
<span class="nb">sudo </span>ip <span class="nb">link set </span>dev eth0 xdp obj filter.o sec xdp
<span class="nb">sudo </span>ip <span class="nb">link set </span>dev eth0 xdp off
</code></pre></div></div>

<p>İlk komut programı derler, ikincisi <code class="language-plaintext highlighter-rouge">eth0</code> arayüzüne yükler, sonuncusu ise bağlantıyı kaldırır. Uzaktan bağlı bir sunucuda bütün UDP trafiğini düşürmeden önce DNS ve VPN kullanımını düşünmek iyi fikirdir; aksi hâlde güvenlik demosu hızla bağlantı kesme demosuna dönüşebilir.</p>

<h2 id="haritalar-ve-gözlemlenebilirlik">Haritalar ve gözlemlenebilirlik</h2>

<p>eBPF haritaları, çekirdek ve kullanıcı alanı arasında paylaşılan anahtar-değer depolarıdır. IP başına paket sayacı tutmak, engelli adresleri dinamik olarak güncellemek veya CPU başına istatistik toplamak için kullanılabilirler. Üretimde C ile doğrudan uğraşmak yerine libbpf, BCC, bpftrace, Cilium ve Rust tabanlı Aya gibi araçlardan yararlanılabilir.</p>

<p>TC kancaları paket değişikliği ve trafik şekillendirme konusunda daha esnekken XDP mümkün olan en erken kararı hedefler. Sonuç olarak eBPF, klasik çekirdek modüllerinin bütün risklerini üstlenmeden çekirdek hızına yaklaşan, programlanabilir bir ağ güvenliği ve izleme katmanı sunar.</p>

<p><img src="/img/ebpf-ile-cekirdegi-78.svg" alt="ebpf-ile-cekirdegi-78" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="ebpf" /><category term="linux" /><category term="xdp" /><category term="ağ güvenliği" /><category term="paket işleme" /><category term="gözlemlenebilirlik" /><summary type="html"><![CDATA[Linux ağ yığınında paketleri yakalamak, filtrelemek veya yönlendirmek eskiden çekirdek modülü geliştirmeyi ve bazen çekirdeği yeniden derlemeyi gerektiriyordu. eBPF sayesinde artık doğrulanmış küçük programları çekirdek içinde güvenli biçimde çalıştırabiliyoruz. Böylece DDoS filtrelerinden gecikme ölçümüne kadar pek çok işi, kaynak koduna neşter vurmadan gerçekleştirmek mümkün.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/ebpf-ile-cekirdegi-78.png" /><media:content medium="image" url="https://program.sonsuz.us/img/ebpf-ile-cekirdegi-78.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">FUSE ile Python Kullanarak Kendi Sanal Dosya Sisteminizi Yazın</title><link href="https://program.sonsuz.us/posts/fuse-ile-python-kullanarak-kendi-sanal-dosya-sisteminizi-yazin/" rel="alternate" type="text/html" title="FUSE ile Python Kullanarak Kendi Sanal Dosya Sisteminizi Yazın" /><published>2026-09-27T00:00:00+00:00</published><updated>2026-09-27T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/fuse-ile-python-kullanarak-kendi-sanal-dosya-sisteminizi-yazin</id><content type="html" xml:base="https://program.sonsuz.us/posts/fuse-ile-python-kullanarak-kendi-sanal-dosya-sisteminizi-yazin/"><![CDATA[<p>Dosya sistemi yazmak denildiğinde akla çekirdek kodu, korkutucu C işaretçileri ve bilgisayarı yeniden başlatma ritüelleri gelebilir. FUSE sayesinde bunların çoğuna gerek kalmadan Python veya Go ile dosya işlemlerine kendi kurallarımızı uygulayabiliriz. Örneğin içeriğini çalışma anında üreten, buluttaki verileri dosya gibi gösteren ya da tüm yazılanları otomatik şifreleyen bir sistem geliştirebiliriz.
``</p>
<h2 id="fuse-tam-olarak-nedir">FUSE tam olarak nedir?</h2>

<p>FUSE, yani <strong>Filesystem in Userspace</strong>, dosya sistemi mantığının kullanıcı alanında çalışan normal bir program tarafından uygulanmasını sağlayan Linux altyapısıdır. Uygulamalar yine <code class="language-plaintext highlighter-rouge">open</code>, <code class="language-plaintext highlighter-rouge">read</code>, <code class="language-plaintext highlighter-rouge">write</code> ve <code class="language-plaintext highlighter-rouge">stat</code> gibi standart sistem çağrılarını kullanır. Çekirdekteki FUSE sürücüsü bu istekleri bizim sürecimize iletir, cevabı alır ve uygulamaya döndürür.</p>

<p>Akış kabaca şöyledir:</p>

<ol>
  <li>Kullanıcı <code class="language-plaintext highlighter-rouge">/mnt/ozel/merhaba.txt</code> dosyasını okur.</li>
  <li>İşletim sistemi isteği FUSE sürücüsüne gönderir.</li>
  <li>FUSE, Python programımızdaki <code class="language-plaintext highlighter-rouge">read()</code> metodunu çağırır.</li>
  <li>Metodun ürettiği veri kullanıcıya teslim edilir.</li>
</ol>

<p>Bir işlemin toplam gecikmesini basitçe $T = T_{kernel} + T_{iletisim} + T_{uygulama}$ şeklinde düşünebiliriz. Kullanıcı alanına geçiş ek maliyet oluşturduğu için FUSE her senaryoda yerel dosya sistemleri kadar hızlı değildir; fakat geliştirme kolaylığı çoğu özel proje için daha değerlidir.</p>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Çekirdek dosya sistemi</th>
      <th>FUSE dosya sistemi</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Geliştirme dili</td>
      <td>Genellikle C</td>
      <td>Python, Go, Rust, C++</td>
    </tr>
    <tr>
      <td>Hata etkisi</td>
      <td>Sistemi çökertebilir</td>
      <td>Genellikle süreç kapanır</td>
    </tr>
    <tr>
      <td>Performans</td>
      <td>Çok yüksek</td>
      <td>Ek iletişim maliyeti var</td>
    </tr>
    <tr>
      <td>Geliştirme kolaylığı</td>
      <td>Zor</td>
      <td>Görece kolay</td>
    </tr>
    <tr>
      <td>Kullanım alanı</td>
      <td>Genel amaçlı depolama</td>
      <td>Özel ve sanal sistemler</td>
    </tr>
  </tbody>
</table>

<h2 id="python-ile-çalışan-küçük-bir-örnek">Python ile çalışan küçük bir örnek</h2>

<p>Ubuntu tabanlı bir sistemde gerekli paketleri şu şekilde kurabiliriz:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>apt <span class="nb">install </span>fuse3 libfuse3-dev
python3 <span class="nt">-m</span> pip <span class="nb">install </span>fusepy
<span class="nb">mkdir</span> <span class="nt">-p</span> /tmp/benimfs
</code></pre></div></div>

<p>Aşağıdaki dosya sistemi yalnızca <code class="language-plaintext highlighter-rouge">merhaba.txt</code> isimli sanal bir dosya sunar. Dosyanın fiziksel diskte bulunması gerekmez; içerik Python tarafından anlık üretilir.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="n">fuse</span> <span class="kn">import</span> <span class="n">FUSE</span><span class="p">,</span> <span class="n">Operations</span>
<span class="kn">import</span> <span class="n">errno</span>
<span class="kn">import</span> <span class="n">os</span>

<span class="k">class</span> <span class="nc">BenimFS</span><span class="p">(</span><span class="n">Operations</span><span class="p">):</span>
    <span class="n">mesaj</span> <span class="o">=</span> <span class="sa">b</span><span class="sh">"</span><span class="s">Merhaba, bu veri sanal dosya sisteminden geliyor!</span><span class="se">\n</span><span class="sh">"</span>

    <span class="k">def</span> <span class="nf">getattr</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">path</span><span class="p">,</span> <span class="n">fh</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">path</span> <span class="o">==</span> <span class="sh">"</span><span class="s">/</span><span class="sh">"</span><span class="p">:</span>
            <span class="k">return</span> <span class="p">{</span>
                <span class="sh">"</span><span class="s">st_mode</span><span class="sh">"</span><span class="p">:</span> <span class="mo">0o40555</span><span class="p">,</span>
                <span class="sh">"</span><span class="s">st_nlink</span><span class="sh">"</span><span class="p">:</span> <span class="mi">2</span>
            <span class="p">}</span>

        <span class="k">if</span> <span class="n">path</span> <span class="o">==</span> <span class="sh">"</span><span class="s">/merhaba.txt</span><span class="sh">"</span><span class="p">:</span>
            <span class="k">return</span> <span class="p">{</span>
                <span class="sh">"</span><span class="s">st_mode</span><span class="sh">"</span><span class="p">:</span> <span class="mo">0o100444</span><span class="p">,</span>
                <span class="sh">"</span><span class="s">st_nlink</span><span class="sh">"</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
                <span class="sh">"</span><span class="s">st_size</span><span class="sh">"</span><span class="p">:</span> <span class="nf">len</span><span class="p">(</span><span class="n">self</span><span class="p">.</span><span class="n">mesaj</span><span class="p">)</span>
            <span class="p">}</span>

        <span class="k">raise</span> <span class="nc">OSError</span><span class="p">(</span><span class="n">errno</span><span class="p">.</span><span class="n">ENOENT</span><span class="p">,</span> <span class="n">os</span><span class="p">.</span><span class="nf">strerror</span><span class="p">(</span><span class="n">errno</span><span class="p">.</span><span class="n">ENOENT</span><span class="p">))</span>

    <span class="k">def</span> <span class="nf">readdir</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">path</span><span class="p">,</span> <span class="n">fh</span><span class="p">):</span>
        <span class="k">return</span> <span class="p">[</span><span class="sh">"</span><span class="s">.</span><span class="sh">"</span><span class="p">,</span> <span class="sh">"</span><span class="s">..</span><span class="sh">"</span><span class="p">,</span> <span class="sh">"</span><span class="s">merhaba.txt</span><span class="sh">"</span><span class="p">]</span>

    <span class="k">def</span> <span class="nf">open</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">path</span><span class="p">,</span> <span class="n">flags</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">path</span> <span class="o">!=</span> <span class="sh">"</span><span class="s">/merhaba.txt</span><span class="sh">"</span><span class="p">:</span>
            <span class="k">raise</span> <span class="nc">OSError</span><span class="p">(</span><span class="n">errno</span><span class="p">.</span><span class="n">ENOENT</span><span class="p">,</span> <span class="sh">"</span><span class="s">Dosya bulunamadı</span><span class="sh">"</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">flags</span> <span class="o">&amp;</span> <span class="p">(</span><span class="n">os</span><span class="p">.</span><span class="n">O_WRONLY</span> <span class="o">|</span> <span class="n">os</span><span class="p">.</span><span class="n">O_RDWR</span><span class="p">):</span>
            <span class="k">raise</span> <span class="nc">OSError</span><span class="p">(</span><span class="n">errno</span><span class="p">.</span><span class="n">EACCES</span><span class="p">,</span> <span class="sh">"</span><span class="s">Dosya salt okunur</span><span class="sh">"</span><span class="p">)</span>
        <span class="k">return</span> <span class="mi">0</span>

    <span class="k">def</span> <span class="nf">read</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">path</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="n">offset</span><span class="p">,</span> <span class="n">fh</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">self</span><span class="p">.</span><span class="n">mesaj</span><span class="p">[</span><span class="n">offset</span><span class="p">:</span><span class="n">offset</span> <span class="o">+</span> <span class="n">size</span><span class="p">]</span>

<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="sh">"</span><span class="s">__main__</span><span class="sh">"</span><span class="p">:</span>
    <span class="nc">FUSE</span><span class="p">(</span><span class="nc">BenimFS</span><span class="p">(),</span> <span class="sh">"</span><span class="s">/tmp/benimfs</span><span class="sh">"</span><span class="p">,</span> <span class="n">foreground</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">getattr()</code> dosyanın türünü, izinlerini ve boyutunu bildirir. <code class="language-plaintext highlighter-rouge">readdir()</code> dizin listesini üretir. <code class="language-plaintext highlighter-rouge">open()</code> erişim kurallarını denetlerken <code class="language-plaintext highlighter-rouge">read()</code> istenen aralıktaki baytları döndürür. Programı <code class="language-plaintext highlighter-rouge">python3 benimfs.py</code> ile çalıştırdıktan sonra başka bir terminalde <code class="language-plaintext highlighter-rouge">cat /tmp/benimfs/merhaba.txt</code> komutu kullanılabilir. Ayırmak için <code class="language-plaintext highlighter-rouge">fusermount3 -u /tmp/benimfs</code> yeterlidir.</p>

<h2 id="tasarımda-dikkat-edilmesi-gerekenler">Tasarımda dikkat edilmesi gerekenler</h2>

<p>Gerçek bir projede eşzamanlı erişim, önbellekleme, dosya tanıtıcıları, kullanıcı kimlikleri ve hata kodları hesaba katılmalıdır. <code class="language-plaintext highlighter-rouge">read()</code> metodunun tüm içeriği değil, yalnızca <code class="language-plaintext highlighter-rouge">offset</code> ile başlayan <code class="language-plaintext highlighter-rouge">size</code> baytı döndürmesi özellikle önemlidir. Aksi hâlde büyük dosyalarda beklenmedik sonuçlar oluşabilir.</p>

<table>
  <thead>
    <tr>
      <th>Amaç</th>
      <th>Uygulanabilecek kural</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Şifreli kasa</td>
      <td><code class="language-plaintext highlighter-rouge">write()</code> sırasında şifreleme</td>
    </tr>
    <tr>
      <td>Bulut sürücüsü</td>
      <td><code class="language-plaintext highlighter-rouge">read()</code> sırasında API isteği</td>
    </tr>
    <tr>
      <td>Denetim sistemi</td>
      <td>Her erişimi günlüğe kaydetme</td>
    </tr>
    <tr>
      <td>Dinamik rapor</td>
      <td>Dosya açıldığında içerik üretme</td>
    </tr>
  </tbody>
</table>

<p>FUSE; prototipler, eğitim araçları, arşiv görüntüleyicileri ve uzak depolama istemcileri için güçlü bir oyun alanıdır. Çekirdeğe dalmadan işletim sisteminin dosya soyutlamasını kullanabilir, hatta bir REST API’yi klasör ve dosyalardan oluşan doğal bir arayüze dönüştürebilirsiniz.</p>

<p><img src="/img/fuse-ile-python-34.svg" alt="fuse-ile-python-34" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Proje" /><category term="fuse" /><category term="python" /><category term="dosya-sistemi" /><category term="linux" /><category term="sanal-dosya-sistemi" /><category term="sistem-programlama" /><summary type="html"><![CDATA[Dosya sistemi yazmak denildiğinde akla çekirdek kodu, korkutucu C işaretçileri ve bilgisayarı yeniden başlatma ritüelleri gelebilir. FUSE sayesinde bunların çoğuna gerek kalmadan Python veya Go ile dosya işlemlerine kendi kurallarımızı uygulayabiliriz. Örneğin içeriğini çalışma anında üreten, buluttaki verileri dosya gibi gösteren ya da tüm yazılanları otomatik şifreleyen bir sistem geliştirebiliriz.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/fuse-ile-python-34.png" /><media:content medium="image" url="https://program.sonsuz.us/img/fuse-ile-python-34.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">İşletim Sistemlerinde Page Cache: Disk Okumaları Neden Sandığımızdan Hızlıdır?</title><link href="https://program.sonsuz.us/posts/isletim-sistemlerinde-page-cache-disk-okumalari-neden-sandigimizdan-hizlidir/" rel="alternate" type="text/html" title="İşletim Sistemlerinde Page Cache: Disk Okumaları Neden Sandığımızdan Hızlıdır?" /><published>2026-09-27T00:00:00+00:00</published><updated>2026-09-27T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/isletim-sistemlerinde-page-cache-disk-okumalari-neden-sandigimizdan-hizlidir</id><content type="html" xml:base="https://program.sonsuz.us/posts/isletim-sistemlerinde-page-cache-disk-okumalari-neden-sandigimizdan-hizlidir/"><![CDATA[<p>Bir dosyayı ilk kez açarken kısa bir bekleme yaşayıp ikinci açılışta şaşırtıcı bir hız görmüş olabilirsiniz. Dosya diskte durduğu hâlde bilgisayarınız nasıl bir anda hızlandı? Çoğu zaman cevap daha hızlı bir disk değil, işletim sisteminin boş RAM alanını akıllıca değerlendirdiği <strong>page cache</strong> mekanizmasıdır.</p>

<p>``</p>

<h2 id="page-cache-nedir">Page cache nedir?</h2>

<p>İşletim sistemi, depolama aygıtındaki dosyaları doğrudan uygulamaların yönetmesine izin vermez. Uygulama bir dosya istediğinde çekirdek, veriyi belirli büyüklükteki bellek sayfaları hâlinde okur. Okunan sayfalar yalnızca programa verilmez; aynı zamanda RAM içindeki page cache alanında tutulur.</p>

<p>Aynı dosya yeniden istendiğinde çekirdek önce önbelleği kontrol eder. Gerekli sayfalar RAM’deyse diske erişmeden sonucu döndürür. Buna <strong>cache hit</strong>, verinin bulunamayıp diskten okunmasına ise <strong>cache miss</strong> denir.</p>

<table>
  <thead>
    <tr>
      <th>Durum</th>
      <th>Veri kaynağı</th>
      <th style="text-align: right">Yaklaşık gecikme</th>
      <th>Sonuç</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Cache hit</td>
      <td>RAM</td>
      <td style="text-align: right">nanosaniye–mikrosaniye</td>
      <td>Çok hızlı okuma</td>
    </tr>
    <tr>
      <td>SSD okuması</td>
      <td>SSD</td>
      <td style="text-align: right">onlarca–yüzlerce mikrosaniye</td>
      <td>Hızlı ama RAM’den yavaş</td>
    </tr>
    <tr>
      <td>HDD okuması</td>
      <td>Mekanik disk</td>
      <td style="text-align: right">milisaniye</td>
      <td>Kafa hareketi nedeniyle yavaş</td>
    </tr>
  </tbody>
</table>

<p><img src="/img/isletim-sistemlerinde-page-33.svg" alt="isletim-sistemlerinde-page-33" /></p>

<p>Basitleştirilmiş toplam erişim süresi şöyle düşünülebilir:</p>

\[T_{ortalama} = H \cdot T_{RAM} + (1-H) \cdot T_{disk}\]

<p>Buradaki $H$, önbellek isabet oranıdır. $H$ değeri 1’e yaklaştıkça ortalama erişim süresi RAM hızına yaklaşır. Küçük görünen bir isabet oranı artışı bile yoğun dosya kullanan sunucularda büyük performans farkı yaratabilir.</p>

<h2 id="boş-ram-neden-gerçekten-boş-değildir">“Boş RAM” neden gerçekten boş değildir?</h2>

<p>Görev yöneticisinde RAM’in büyük bölümünün kullanıldığını görmek her zaman sorun anlamına gelmez. Modern işletim sistemleri kullanılmayan belleği boş bırakmak yerine dosya önbelleği olarak değerlendirir. Çünkü kullanılmayan RAM, performans açısından kaçırılmış bir fırsattır.</p>

<p>Bir uygulama daha fazla belleğe ihtiyaç duyduğunda önbellekteki temiz sayfalar kolayca bırakılabilir. Bu nedenle page cache, uygulamaların belleğini “çalmaz”; ihtiyaç ortaya çıkana kadar boş kapasiteyi ödünç alır.</p>

<p>Linux çıktılarındaki <code class="language-plaintext highlighter-rouge">free</code>, <code class="language-plaintext highlighter-rouge">buff/cache</code> ve özellikle <code class="language-plaintext highlighter-rouge">available</code> değerleri bu yüzden birlikte değerlendirilmelidir:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Belleğin uygulamalar ve önbellek arasında nasıl dağıldığını gösterir.</span>
free <span class="nt">-h</span>

<span class="c"># Bir dosyayı okuyarak gerçek süreyi ölçer.</span>
<span class="nb">time cat </span>buyuk-dosya.bin <span class="o">&gt;</span> /dev/null

<span class="c"># Aynı komut ikinci kez çalıştırıldığında veri büyük olasılıkla cache'tedir.</span>
<span class="nb">time cat </span>buyuk-dosya.bin <span class="o">&gt;</span> /dev/null
</code></pre></div></div>

<p>İkinci çalıştırmanın daha hızlı olması, dosyanın değiştiği veya <code class="language-plaintext highlighter-rouge">cat</code> programının özel bir numara yaptığı anlamına gelmez. İlk komut dosya sayfalarını RAM’e taşımış, ikinci komut ise hazır bulunan sayfaları kullanmıştır. Dosya RAM kapasitesinden büyükse veya sistem yoğun bellek baskısı altındaysa fark azalabilir.</p>

<h2 id="yazma-işlemlerinde-de-görev-alır-mı">Yazma işlemlerinde de görev alır mı?</h2>

<p>Evet. Bir uygulama dosyaya yazdığında veri çoğu zaman önce bellekteki sayfalara aktarılır. Değiştirilmiş ve henüz diske gönderilmemiş sayfalara <strong>dirty page</strong> denir. Çekirdek bunları daha sonra toplu biçimde diske yazar. Böylece uygulama her küçük değişiklik için fiziksel disk işlemini beklemez.</p>

<table>
  <thead>
    <tr>
      <th>Sayfa türü</th>
      <th>Anlamı</th>
      <th>Bellekten hemen atılabilir mi?</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Clean page</td>
      <td>Diskteki kopyayla aynı</td>
      <td>Evet</td>
    </tr>
    <tr>
      <td>Dirty page</td>
      <td>Henüz diske yazılmamış değişiklik içerir</td>
      <td>Önce yazılmalıdır</td>
    </tr>
  </tbody>
</table>

<p>Bu yaklaşım performansı artırsa da elektrik kesintisi gibi durumlarda henüz kalıcı depolamaya ulaşmamış veriler kaybolabilir. Veritabanları bu nedenle <code class="language-plaintext highlighter-rouge">fsync</code> benzeri çağrılarla kritik verinin diske ulaştığından emin olur.</p>

<h2 id="page-cache-her-şeyi-hızlandırır-mı">Page cache her şeyi hızlandırır mı?</h2>

<p>Page cache sihirli değildir. İlk okuma yine depolama aygıtının hızına bağlıdır. Çok büyük veri kümeleri önbelleğe sığmayabilir; başka uygulamalar da sık kullanılan sayfaları dışarı itebilir. Ayrıca bazı veritabanları ve özel uygulamalar, kendi önbelleklerini yönetmek için doğrudan I/O kullanabilir.</p>

<p>Yine de günlük kullanımda programların hızlı açılması, kaynak kodlarının çabuk derlenmesi ve aynı videonun tekrar akıcı oynatılması çoğunlukla bu görünmez yardımcı sayesinde gerçekleşir. Kısacası yüksek RAM kullanımı her zaman kötü değildir: İşletim sistemi belleği dosyalarla dolduruyorsa, RAM’iniz tembellik etmek yerine gelecekteki disk okumalarını hızlandırıyordur.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="işletim sistemi" /><category term="page cache" /><category term="ram" /><category term="disk" /><category term="linux" /><category term="performans" /><summary type="html"><![CDATA[Bir dosyayı ilk kez açarken kısa bir bekleme yaşayıp ikinci açılışta şaşırtıcı bir hız görmüş olabilirsiniz. Dosya diskte durduğu hâlde bilgisayarınız nasıl bir anda hızlandı? Çoğu zaman cevap daha hızlı bir disk değil, işletim sisteminin boş RAM alanını akıllıca değerlendirdiği page cache mekanizmasıdır.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/isletim-sistemlerinde-page-33.png" /><media:content medium="image" url="https://program.sonsuz.us/img/isletim-sistemlerinde-page-33.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">L1/L2 Cache Dostu Kod: Döngüler ve Veri Yapılarıyla Performansı Katlamak</title><link href="https://program.sonsuz.us/posts/l1l2-cache-dostu-kod-donguler-ve-veri-yapilariyla-performansi-katlamak/" rel="alternate" type="text/html" title="L1/L2 Cache Dostu Kod: Döngüler ve Veri Yapılarıyla Performansı Katlamak" /><published>2026-09-27T00:00:00+00:00</published><updated>2026-09-27T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/l1l2-cache-dostu-kod-donguler-ve-veri-yapilariyla-performansi-katlamak</id><content type="html" xml:base="https://program.sonsuz.us/posts/l1l2-cache-dostu-kod-donguler-ve-veri-yapilariyla-performansi-katlamak/"><![CDATA[<p>Modern işlemciler son derece hızlıdır; ancak ihtiyaç duydukları veriyi ana bellekten beklemek zorunda kaldıklarında pahalı bir spor arabayı trafik ışığında bekletmeye dönüşürler. Döngülerimizi ve veri yapılarımızı işlemci önbelleğine uygun tasarlamak, daha yüksek saat hızına ihtiyaç duymadan programı birkaç kat hızlandırabilir.</p>

<p><img src="/img/l1l2-cache-dostu-54.svg" alt="l1l2-cache-dostu-54" /></p>

<p>``</p>

<h2 id="i̇şlemci-neden-önbelleğe-ihtiyaç-duyar">İşlemci neden önbelleğe ihtiyaç duyar?</h2>

<p>CPU ile RAM aynı hızda çalışmaz. İşlemci bir komutu birkaç çevrimde tamamlayabilirken RAM erişimi yüzlerce çevrim sürebilir. Bu farkı azaltmak için işlemci ile RAM arasına küçük fakat hızlı önbellek katmanları yerleştirilir.</p>

<table>
  <thead>
    <tr>
      <th>Katman</th>
      <th style="text-align: right">Yaklaşık kapasite</th>
      <th style="text-align: right">Göreli hız</th>
      <th>Özellik</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>L1 cache</td>
      <td style="text-align: right">32–128 KB</td>
      <td style="text-align: right">En hızlı</td>
      <td>Genellikle çekirdeğe özeldir</td>
    </tr>
    <tr>
      <td>L2 cache</td>
      <td style="text-align: right">256 KB–2 MB</td>
      <td style="text-align: right">Çok hızlı</td>
      <td>L1’den büyük, biraz daha yavaş</td>
    </tr>
    <tr>
      <td>L3 cache</td>
      <td style="text-align: right">Birkaç MB</td>
      <td style="text-align: right">Orta</td>
      <td>Çekirdekler arasında paylaşılabilir</td>
    </tr>
    <tr>
      <td>RAM</td>
      <td style="text-align: right">GB düzeyi</td>
      <td style="text-align: right">Yavaş</td>
      <td>Büyük veri deposudur</td>
    </tr>
  </tbody>
</table>

<p>Aranan veri önbellekte bulunursa <strong>cache hit</strong>, bulunamazsa <strong>cache miss</strong> oluşur. Basitleştirilmiş ortalama erişim süresi şöyle düşünülebilir:</p>

\[T_{ortalama} = h \cdot T_{cache} + (1-h) \cdot T_{RAM}\]

<p>Burada $h$ cache hit oranıdır. RAM çok daha yavaş olduğundan, $h$ değerindeki küçük bir artış bile toplam süreyi ciddi biçimde azaltabilir.</p>

<h2 id="mekânsal-ve-zamansal-yerellik">Mekânsal ve zamansal yerellik</h2>

<p>Önbellek RAM’den tek bir değişken getirmez; genellikle 64 baytlık bir <strong>cache line</strong> taşır. Bir elemana eriştiğimizde komşu elemanlar da gelir. Ardışık elemanları kullanmak <strong>mekânsal yerellik</strong>, aynı veriyi kısa süre içinde tekrar kullanmak ise <strong>zamansal yerellik</strong> sağlar.</p>

<p>C ve C++ gibi dillerde iki boyutlu diziler satır öncelikli saklanır. Bu nedenle döngü sırası önemlidir:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#define N 2048
</span><span class="kt">int</span> <span class="n">matrix</span><span class="p">[</span><span class="n">N</span><span class="p">][</span><span class="n">N</span><span class="p">];</span>
<span class="kt">long</span> <span class="kt">long</span> <span class="n">toplam</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>

<span class="c1">// Cache dostu: Bellekte ardışık elemanlar okunur.</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">N</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">N</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">toplam</span> <span class="o">+=</span> <span class="n">matrix</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">];</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>İç döngüde <code class="language-plaintext highlighter-rouge">j</code> değiştiği için <code class="language-plaintext highlighter-rouge">matrix[i][j]</code> elemanları art arda okunur. Döngüleri ters çevirmek ise her erişimde farklı bir satıra sıçrayabilir:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Cache açısından zayıf: Büyük adımlarla bellekte gezinir.</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">N</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">N</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">toplam</span> <span class="o">+=</span> <span class="n">matrix</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">];</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Her iki kod da aynı matematiksel sonucu üretir ve zaman karmaşıklıkları $O(N^2)$ olur. Buna rağmen gerçek çalışma süreleri dramatik biçimde farklılaşabilir. Big-O, bellek erişim maliyetini tek başına anlatmaz.</p>

<h2 id="veri-yapısının-dizilişi-aos-ve-soa">Veri yapısının dizilişi: AoS ve SoA</h2>

<p>Bir oyundaki parçacıkları düşünelim:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">struct</span> <span class="n">Parca</span> <span class="p">{</span>
    <span class="kt">float</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">z</span><span class="p">;</span>
    <span class="kt">float</span> <span class="n">hiz</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">renk</span><span class="p">;</span>
<span class="p">};</span>

<span class="k">struct</span> <span class="n">Parca</span> <span class="n">parcalar</span><span class="p">[</span><span class="mi">1000000</span><span class="p">];</span>
</code></pre></div></div>

<p>Bu yaklaşım <strong>Array of Structures (AoS)</strong> olarak adlandırılır. Yalnızca konumları güncelliyorsak kullanılmayan <code class="language-plaintext highlighter-rouge">renk</code> gibi alanlar da cache line içine taşınır. Alternatif <strong>Structure of Arrays (SoA)</strong> düzeninde alanlar ayrılır:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">struct</span> <span class="n">Parcalar</span> <span class="p">{</span>
    <span class="kt">float</span> <span class="n">x</span><span class="p">[</span><span class="mi">1000000</span><span class="p">];</span>
    <span class="kt">float</span> <span class="n">y</span><span class="p">[</span><span class="mi">1000000</span><span class="p">];</span>
    <span class="kt">float</span> <span class="n">z</span><span class="p">[</span><span class="mi">1000000</span><span class="p">];</span>
    <span class="kt">float</span> <span class="n">hiz</span><span class="p">[</span><span class="mi">1000000</span><span class="p">];</span>
    <span class="kt">int</span> <span class="n">renk</span><span class="p">[</span><span class="mi">1000000</span><span class="p">];</span>
<span class="p">};</span>
</code></pre></div></div>

<table>
  <thead>
    <tr>
      <th>Düzen</th>
      <th>Güçlü olduğu durum</th>
      <th>Zayıf olduğu durum</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>AoS</td>
      <td>Bir nesnenin tüm alanları birlikte kullanılıyorsa</td>
      <td>Yalnızca birkaç alan işleniyorsa</td>
    </tr>
    <tr>
      <td>SoA</td>
      <td>Aynı alan topluca işleniyorsa, SIMD kullanılıyorsa</td>
      <td>Tek nesnenin tüm alanlarına sık erişiliyorsa</td>
    </tr>
  </tbody>
</table>

<h2 id="büyük-veriyi-bloklar-hâlinde-işlemek">Büyük veriyi bloklar hâlinde işlemek</h2>

<p>Matris çarpımı gibi algoritmalarda veri L1 veya L2’ye sığmayabilir. <strong>Blocking</strong> ya da <strong>tiling</strong>, problemi önbelleğe sığan küçük parçalara ayırır:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">const</span> <span class="kt">int</span> <span class="n">B</span> <span class="o">=</span> <span class="mi">32</span><span class="p">;</span>

<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">ii</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">ii</span> <span class="o">&lt;</span> <span class="n">N</span><span class="p">;</span> <span class="n">ii</span> <span class="o">+=</span> <span class="n">B</span><span class="p">)</span>
    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">kk</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">kk</span> <span class="o">&lt;</span> <span class="n">N</span><span class="p">;</span> <span class="n">kk</span> <span class="o">+=</span> <span class="n">B</span><span class="p">)</span>
        <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">ii</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">ii</span> <span class="o">+</span> <span class="n">B</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
            <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">k</span> <span class="o">=</span> <span class="n">kk</span><span class="p">;</span> <span class="n">k</span> <span class="o">&lt;</span> <span class="n">kk</span> <span class="o">+</span> <span class="n">B</span><span class="p">;</span> <span class="n">k</span><span class="o">++</span><span class="p">)</span>
                <span class="n">sonuc</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+=</span> <span class="n">matrix</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">k</span><span class="p">]</span> <span class="o">*</span> <span class="n">vektor</span><span class="p">[</span><span class="n">k</span><span class="p">];</span>
</code></pre></div></div>

<p>Blok boyutu donanıma ve veri tipine göre ölçülerek seçilmelidir. Gereğinden büyük bloklar önbellekten taşar; çok küçük bloklar ise döngü yönetimi maliyetini artırır.</p>

<p>Sonuç olarak ardışık erişim, tekrar kullanılan veriyi yakın tutma, uygun veri düzeni ve bloklama cache hit oranını yükseltir. En doğru optimizasyon için tahminde bulunmak yerine <code class="language-plaintext highlighter-rouge">perf</code>, Valgrind Cachegrind veya işlemci performans sayaçlarıyla cache miss değerlerini ölçmek gerekir. Çünkü hızlı kod yalnızca daha az işlem yapan değil, işlemciyi verisiz bırakmayan koddur.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="işlemci" /><category term="önbellek" /><category term="cache" /><category term="performans" /><category term="bellek" /><category term="c" /><category term="optimizasyon" /><summary type="html"><![CDATA[Modern işlemciler son derece hızlıdır; ancak ihtiyaç duydukları veriyi ana bellekten beklemek zorunda kaldıklarında pahalı bir spor arabayı trafik ışığında bekletmeye dönüşürler. Döngülerimizi ve veri yapılarımızı işlemci önbelleğine uygun tasarlamak, daha yüksek saat hızına ihtiyaç duymadan programı birkaç kat hızlandırabilir.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/l1l2-cache-dostu-54.png" /><media:content medium="image" url="https://program.sonsuz.us/img/l1l2-cache-dostu-54.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Linux Çekirdeğinde Cgroups v2: Kaynak İzolasyonunun Modern Mimarisi</title><link href="https://program.sonsuz.us/posts/linux-cekirdeginde-cgroups-v2-kaynak-izolasyonunun-modern-mimarisi/" rel="alternate" type="text/html" title="Linux Çekirdeğinde Cgroups v2: Kaynak İzolasyonunun Modern Mimarisi" /><published>2026-09-27T00:00:00+00:00</published><updated>2026-09-27T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/linux-cekirdeginde-cgroups-v2-kaynak-izolasyonunun-modern-mimarisi</id><content type="html" xml:base="https://program.sonsuz.us/posts/linux-cekirdeginde-cgroups-v2-kaynak-izolasyonunun-modern-mimarisi/"><![CDATA[<p>Bir konteynere “en fazla 512 MB bellek kullan” veya “işlemcinin yalnızca yarısını tüket” dediğimizde bu kuralları Docker’ın sihirli değneği değil, Linux çekirdeğinin <strong>control groups</strong> mekanizması uygular. Cgroups v2, ilk sürümün yıllar içinde karmaşıklaşan yapısını tek bir hiyerarşide birleştirerek kaynak yönetimini daha tutarlı, güvenli ve öngörülebilir hâle getirir.
``</p>
<h2 id="cgroups-neyi-çözer">Cgroups neyi çözer?</h2>

<p>Cgroups, süreçleri gruplandırır ve CPU, bellek, disk G/Ç ya da süreç sayısı gibi kaynakları bu gruplar üzerinden denetler. Namespace’ler bir konteynerin <em>neyi görebildiğini</em>, cgroups ise <em>ne kadar tüketebildiğini</em> belirler. Dolayısıyla ikisi tamamlayıcıdır: namespace izolasyon perdesiyken cgroups kaynak bütçesidir.</p>

<p>Bir grubun CPU kullanım oranı basitçe</p>

\[R = \frac{Q}{P}\]

<p>ile düşünülebilir. Burada $Q$ izin verilen CPU süresi, $P$ ise periyottur. Örneğin <code class="language-plaintext highlighter-rouge">cpu.max</code> dosyasına <code class="language-plaintext highlighter-rouge">50000 100000</code> yazılması, grubun her 100 milisaniyede en fazla 50 milisaniye CPU kullanabilmesi, yani yaklaşık $R=0.5$ CPU kapasitesi anlamına gelir.</p>

<h2 id="v1-neden-yorucuydu">v1 neden yorucuydu?</h2>

<p>Cgroups v1’de her denetleyici bağımsız bir hiyerarşiye bağlanabiliyordu. Aynı süreç CPU ağacında bir grupta, bellek ağacında başka bir grupta bulunabiliyordu. Esneklik gibi görünen bu model; Docker, systemd ve Kubernetes gibi araçlar aynı makinede çalıştığında yönetim karmaşasına, belirsiz yetki devrine ve tutarsız kaynak davranışlarına yol açıyordu.</p>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Cgroups v1</th>
      <th>Cgroups v2</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Hiyerarşi</td>
      <td>Denetleyici başına ayrı olabilir</td>
      <td>Tek ve birleşik</td>
    </tr>
    <tr>
      <td>Süreç organizasyonu</td>
      <td>Farklı ağaçlarda farklı üyelik</td>
      <td>Tek cgroup üyeliği</td>
    </tr>
    <tr>
      <td>Yetki devri</td>
      <td>Karmaşık ve riskli</td>
      <td>Kontrollü delegation</td>
    </tr>
    <tr>
      <td>Bellek denetimi</td>
      <td>Daha parçalı davranış</td>
      <td>Tutarlı limit ve basınç modeli</td>
    </tr>
    <tr>
      <td>Arayüz</td>
      <td>Denetleyiciler arasında düzensiz</td>
      <td>Standartlaştırılmış dosyalar</td>
    </tr>
  </tbody>
</table>

<h2 id="birleşik-hiyerarşi-nasıl-çalışır">Birleşik hiyerarşi nasıl çalışır?</h2>

<p>v2 çoğunlukla <code class="language-plaintext highlighter-rouge">/sys/fs/cgroup</code> altında tek bir ağaç sunar. Bir sürecin kimliği <code class="language-plaintext highlighter-rouge">cgroup.procs</code>, kullanılabilir denetleyiciler <code class="language-plaintext highlighter-rouge">cgroup.controllers</code>, alt gruplara aktarılacak denetleyiciler ise <code class="language-plaintext highlighter-rouge">cgroup.subtree_control</code> üzerinden yönetilir.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Sistemde etkin olan v2 denetleyicilerini gösterir.</span>
<span class="nb">cat</span> /sys/fs/cgroup/cgroup.controllers

<span class="c"># Yeni bir uygulama grubu oluşturur.</span>
<span class="nb">sudo mkdir</span> /sys/fs/cgroup/demo

<span class="c"># Kabuğun PID'sini gruba taşır.</span>
<span class="nb">echo</span> <span class="nv">$$</span> | <span class="nb">sudo tee</span> /sys/fs/cgroup/demo/cgroup.procs
</code></pre></div></div>

<p>v2’nin önemli kurallarından biri <strong>no internal process constraint</strong> ilkesidir. Kaynak denetleyicileri alt gruplara dağıtan bir cgroup, normalde aynı anda doğrudan süreç barındırmaz. Başka bir deyişle dallar organizasyon, yapraklar iş yükü içindir. Bu kural, ebeveyn ve çocuk gruplar arasında kaynak hesabının bulanıklaşmasını önler.</p>

<h2 id="bellek-cpu-ve-süreç-sınırları">Bellek, CPU ve süreç sınırları</h2>

<p>Bellek tarafında <code class="language-plaintext highlighter-rouge">memory.max</code> kesin tavanı, <code class="language-plaintext highlighter-rouge">memory.high</code> ise çekirdeğin agresif geri kazanım uygulamaya başlayacağı yumuşak eşiği ifade eder. Böylece uygulamayı anında öldürmeden önce baskı oluşturmak mümkündür. <code class="language-plaintext highlighter-rouge">memory.current</code> mevcut tüketimi gösterirken <code class="language-plaintext highlighter-rouge">memory.events</code>, OOM gibi olayları sayar.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Kesin bellek limitini 512 MiB yapar.</span>
<span class="nb">echo </span>536870912 | <span class="nb">sudo tee</span> /sys/fs/cgroup/demo/memory.max

<span class="c"># Yaklaşık yarım CPU ve en fazla 100 süreç tanımlar.</span>
<span class="nb">echo</span> <span class="s1">'50000 100000'</span> | <span class="nb">sudo tee</span> /sys/fs/cgroup/demo/cpu.max
<span class="nb">echo </span>100 | <span class="nb">sudo tee</span> /sys/fs/cgroup/demo/pids.max
</code></pre></div></div>

<p>CPU paylaşım önceliği için v1’deki <code class="language-plaintext highlighter-rouge">cpu.shares</code> yerine daha anlaşılır bir aralığa sahip <code class="language-plaintext highlighter-rouge">cpu.weight</code> kullanılır. G/Ç denetimi de <code class="language-plaintext highlighter-rouge">io.max</code> ve <code class="language-plaintext highlighter-rouge">io.weight</code> gibi tutarlı adlarla sunulur.</p>

<h2 id="docker-açısından-anlamı">Docker açısından anlamı</h2>

<p>Docker’daki <code class="language-plaintext highlighter-rouge">--memory</code>, <code class="language-plaintext highlighter-rouge">--cpus</code> ve <code class="language-plaintext highlighter-rouge">--pids-limit</code> seçenekleri sonuçta bu dosyalara dönüştürülür. Modern systemd sürümleri de servisleri cgroup ağacında doğal olarak düzenler. Tek hiyerarşi sayesinde orkestratör, çalışma zamanı ve init sistemi aynı kaynak ağacını paylaşabilir; “bu süreci aslında kim yönetiyor?” bilmecesi büyük ölçüde ortadan kalkar.</p>

<p>Cgroups v2 yalnızca temizlenmiş bir arayüz değildir. Tutarlı muhasebe, güvenli yetki devri, gelişmiş bellek baskısı ve sade hiyerarşi sayesinde konteyner izolasyonunu daha sağlam bir çekirdek sözleşmesine dönüştürür. Kısacası v1 kaynaklara ayrı ayrı kilit vuruyordu; v2 ise bütün binaya düzenli bir erişim planı çiziyor.</p>

<p><img src="/img/linux-cekirdeginde-cgroups-17.svg" alt="linux-cekirdeginde-cgroups-17" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="linux" /><category term="cgroups" /><category term="docker" /><category term="konteyner" /><category term="çekirdek" /><category term="devops" /><summary type="html"><![CDATA[Bir konteynere “en fazla 512 MB bellek kullan” veya “işlemcinin yalnızca yarısını tüket” dediğimizde bu kuralları Docker’ın sihirli değneği değil, Linux çekirdeğinin control groups mekanizması uygular. Cgroups v2, ilk sürümün yıllar içinde karmaşıklaşan yapısını tek bir hiyerarşide birleştirerek kaynak yönetimini daha tutarlı, güvenli ve öngörülebilir hâle getirir.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/linux-cekirdeginde-cgroups-17.png" /><media:content medium="image" url="https://program.sonsuz.us/img/linux-cekirdeginde-cgroups-17.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Meta-Learning: Öğrenmeyi Öğrenen Modellerin Kısa Tarihi</title><link href="https://program.sonsuz.us/posts/meta-learning-ogrenmeyi-ogrenen-modellerin-kisa-tarihi/" rel="alternate" type="text/html" title="Meta-Learning: Öğrenmeyi Öğrenen Modellerin Kısa Tarihi" /><published>2026-09-27T00:00:00+00:00</published><updated>2026-09-27T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/meta-learning-ogrenmeyi-ogrenen-modellerin-kisa-tarihi</id><content type="html" xml:base="https://program.sonsuz.us/posts/meta-learning-ogrenmeyi-ogrenen-modellerin-kisa-tarihi/"><![CDATA[<p>Geleneksel makine öğrenmesinde her yeni problem için veri toplar, modeli eğitir ve sabırla sonuç bekleriz. Meta-learning ise bu rutine küçük bir itiraz getirir: Model yalnızca görevleri çözmesin, yeni bir görevi nasıl hızlı öğreneceğini de keşfetsin. Böylece binlerce örnek yerine birkaç örnekle uyum sağlayabilen, deyim yerindeyse eğitim salonunda nasıl antrenman yapacağını öğrenen sistemler ortaya çıkar.</p>

<p><img src="/img/meta-learning-ogrenmeyi-67.svg" alt="meta-learning-ogrenmeyi-67" /></p>

<p>``</p>

<h2 id="fikir-nereden-çıktı">Fikir nereden çıktı?</h2>

<p>“Öğrenmeyi öğrenme” düşüncesi yapay zekâdan daha eskidir. Psikoloji, insanların önceki deneyimlerinden yararlanarak yeni becerileri daha hızlı kazandığını uzun süredir inceliyordu. Makine öğrenmesinde ise erken dönem çalışmalar, algoritmaların kendi öğrenme kurallarını ayarlayıp ayarlayamayacağı sorusuna odaklandı.</p>

<p>1990’larda sinir ağlarının ağırlık güncellemelerini başka ağlarla yönetme fikri belirginleşti. 2000’lerde çoklu görev öğrenmesi ve aktarım öğrenmesi güçlü temeller sağladı. 2010’ların ortasında derin öğrenme, büyük veri kümeleri ve GPU’larla birleşince meta-learning uygulanabilir hâle geldi. 2016 tarihli Matching Networks ve 2017’de yayımlanan MAML, alanın en etkili dönüm noktaları arasında yer aldı.</p>

<table>
  <thead>
    <tr>
      <th>Yaklaşım</th>
      <th>Temel amaç</th>
      <th>Yeni görevde gereken</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Klasik eğitim</td>
      <td>Tek görevi iyi çözmek</td>
      <td>Çok veri ve yeniden eğitim</td>
    </tr>
    <tr>
      <td>Transfer learning</td>
      <td>Önceden öğrenilmiş özellikleri aktarmak</td>
      <td>İnce ayar ve orta miktarda veri</td>
    </tr>
    <tr>
      <td>Few-shot learning</td>
      <td>Birkaç örnekle tahmin yapmak</td>
      <td>Küçük destek kümesi</td>
    </tr>
    <tr>
      <td>Meta-learning</td>
      <td>Uyum sağlama sürecini öğrenmek</td>
      <td>Birkaç örnek ve az sayıda güncelleme</td>
    </tr>
  </tbody>
</table>

<h2 id="görevler-üzerinden-öğrenmek">Görevler üzerinden öğrenmek</h2>

<p>Normal eğitimde veri noktaları örneklenir. Meta-learning eğitiminde ise <strong>görevler</strong> örneklenir. Her görev genellikle iki parçaya ayrılır:</p>

<ul>
  <li><strong>Destek kümesi:</strong> Modelin göreve uyum sağladığı az sayıdaki örnek.</li>
  <li><strong>Sorgu kümesi:</strong> Uyumun gerçekten işe yarayıp yaramadığını ölçen örnekler.</li>
</ul>

<p>Bir görev $T_i$ için destek kaybı $L_{S_i}$ olsun. Modelin başlangıç parametreleri $θ$ ise tek adımlık uyarlama şöyle yazılabilir:</p>

\[θ'_i = θ - α ∇_θ L_{S_i}(θ)\]

<p>Burada $α$ iç döngünün öğrenme oranıdır. Meta-model, uyarlanmış parametrelerin sorgu kümelerindeki toplam hatasını azaltmaya çalışır:</p>

\[min_θ Σ_i L_{Q_i}(θ'_i)\]

<p>İşin sihri burada yatar: Sistem yalnızca doğru cevabı değil, birkaç gradyan adımından sonra iyi sonuç verecek bir <strong>başlangıç noktası</strong> öğrenir. MAML’ın modelden bağımsız sayılmasının nedeni de bu fikrin sınıflandırma, regresyon veya pekiştirmeli öğrenme gibi farklı alanlara uygulanabilmesidir.</p>

<h2 id="üç-ana-meta-learning-ailesi">Üç ana meta-learning ailesi</h2>

<table>
  <thead>
    <tr>
      <th>Aile</th>
      <th>Öğrendiği şey</th>
      <th>Bilinen örnek</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Optimizasyon tabanlı</td>
      <td>Hızlı uyarlanabilir parametreler</td>
      <td>MAML, Reptile</td>
    </tr>
    <tr>
      <td>Metrik tabanlı</td>
      <td>Örnekler arasındaki benzerlik uzayı</td>
      <td>Prototypical Networks</td>
    </tr>
    <tr>
      <td>Model tabanlı</td>
      <td>Bellek veya öğrenme mekanizması</td>
      <td>Memory-Augmented Networks</td>
    </tr>
  </tbody>
</table>

<p>Metrik tabanlı yöntemlerde her sınıfın prototipi hesaplanabilir. $k$ sınıfına ait destek temsillerinin ortalaması:</p>

\[c_k = (1 / \vert S_k\vert ) Σ_{x ∈ S_k} f_θ(x)\]

<p>Yeni örnek, temsili hangi $c_k$ noktasına daha yakınsa o sınıfa atanır. Bir bakıma model, “Bu fotoğraf hangi aile albümüne daha çok benziyor?” diye sorar.</p>

<h2 id="maml-mantığının-küçük-bir-kod-karşılığı">MAML mantığının küçük bir kod karşılığı</h2>

<p>Aşağıdaki PyTorch taslağı, tek görev için iç güncelleme yapar ve sorgu kaybını hesaplar. <code class="language-plaintext highlighter-rouge">create_graph=True</code>, dış döngünün iç güncelleme üzerinden türev alabilmesini sağlar:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="n">torch</span>
<span class="kn">from</span> <span class="n">torch.func</span> <span class="kn">import</span> <span class="n">functional_call</span>

<span class="n">support_logits</span> <span class="o">=</span> <span class="nf">model</span><span class="p">(</span><span class="n">x_support</span><span class="p">)</span>
<span class="n">support_loss</span> <span class="o">=</span> <span class="nf">loss_fn</span><span class="p">(</span><span class="n">support_logits</span><span class="p">,</span> <span class="n">y_support</span><span class="p">)</span>

<span class="n">params</span> <span class="o">=</span> <span class="nf">dict</span><span class="p">(</span><span class="n">model</span><span class="p">.</span><span class="nf">named_parameters</span><span class="p">())</span>
<span class="n">grads</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">autograd</span><span class="p">.</span><span class="nf">grad</span><span class="p">(</span>
    <span class="n">support_loss</span><span class="p">,</span>
    <span class="n">params</span><span class="p">.</span><span class="nf">values</span><span class="p">(),</span>
    <span class="n">create_graph</span><span class="o">=</span><span class="bp">True</span>
<span class="p">)</span>

<span class="n">fast_params</span> <span class="o">=</span> <span class="p">{</span>
    <span class="n">name</span><span class="p">:</span> <span class="n">param</span> <span class="o">-</span> <span class="n">inner_lr</span> <span class="o">*</span> <span class="n">grad</span>
    <span class="nf">for </span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">param</span><span class="p">),</span> <span class="n">grad</span> <span class="ow">in</span> <span class="nf">zip</span><span class="p">(</span><span class="n">params</span><span class="p">.</span><span class="nf">items</span><span class="p">(),</span> <span class="n">grads</span><span class="p">)</span>
<span class="p">}</span>

<span class="n">query_logits</span> <span class="o">=</span> <span class="nf">functional_call</span><span class="p">(</span><span class="n">model</span><span class="p">,</span> <span class="n">fast_params</span><span class="p">,</span> <span class="p">(</span><span class="n">x_query</span><span class="p">,))</span>
<span class="n">outer_loss</span> <span class="o">=</span> <span class="nf">loss_fn</span><span class="p">(</span><span class="n">query_logits</span><span class="p">,</span> <span class="n">y_query</span><span class="p">)</span>

<span class="n">optimizer</span><span class="p">.</span><span class="nf">zero_grad</span><span class="p">()</span>
<span class="n">outer_loss</span><span class="p">.</span><span class="nf">backward</span><span class="p">()</span>
<span class="n">optimizer</span><span class="p">.</span><span class="nf">step</span><span class="p">()</span>
</code></pre></div></div>

<p>Gerçek uygulamada bu işlem birçok görev için tekrarlanır ve sorgu kayıpları ortalanır. Hesaplama maliyeti özellikle ikinci dereceden türevler nedeniyle yükselebilir; First-Order MAML ve Reptile gibi yöntemler bu yükü azaltmayı hedefler.</p>

<h2 id="neden-önemli">Neden önemli?</h2>

<p>Meta-learning; nadir hastalıkların sınıflandırılması, yeni robot hareketleri, kişiselleştirilmiş öneriler ve az kaynaklı diller gibi verinin pahalı olduğu alanlarda değerlidir. Yine de görev dağılımı kötü seçilirse model yeni koşullara uyum sağlayamaz. Kısacası öğrenmeyi öğrenen bir sistem de öğretmeninin hazırladığı müfredat kadar iyidir. Meta-learning’in büyük vaadi, her şeyi bilen modeller değil; bilmediği bir şeyle karşılaştığında ne yapacağını daha çabuk anlayan modeller üretmesidir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="meta-learning" /><category term="yapay zeka" /><category term="makine öğrenmesi" /><category term="few-shot learning" /><category term="maml" /><category term="derin öğrenme" /><summary type="html"><![CDATA[Geleneksel makine öğrenmesinde her yeni problem için veri toplar, modeli eğitir ve sabırla sonuç bekleriz. Meta-learning ise bu rutine küçük bir itiraz getirir: Model yalnızca görevleri çözmesin, yeni bir görevi nasıl hızlı öğreneceğini de keşfetsin. Böylece binlerce örnek yerine birkaç örnekle uyum sağlayabilen, deyim yerindeyse eğitim salonunda nasıl antrenman yapacağını öğrenen sistemler ortaya çıkar.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/meta-learning-ogrenmeyi-67.png" /><media:content medium="image" url="https://program.sonsuz.us/img/meta-learning-ogrenmeyi-67.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Mutex vs Spinlock: Beklemek mi, Boşuna Dönmek mi Daha Maliyetli?</title><link href="https://program.sonsuz.us/posts/mutex-vs-spinlock-beklemek-mi-bosuna-donmek-mi-daha-maliyetli/" rel="alternate" type="text/html" title="Mutex vs Spinlock: Beklemek mi, Boşuna Dönmek mi Daha Maliyetli?" /><published>2026-09-27T00:00:00+00:00</published><updated>2026-09-27T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/mutex-vs-spinlock-beklemek-mi-bosuna-donmek-mi-daha-maliyetli</id><content type="html" xml:base="https://program.sonsuz.us/posts/mutex-vs-spinlock-beklemek-mi-bosuna-donmek-mi-daha-maliyetli/"><![CDATA[<p>Çok çekirdekli bir sistemde iki iş parçacığı aynı veriye uzandığında küçük bir trafik kavşağı oluşur. Mutex kırmızı ışıkta motoru kapatıp beklemeye, spinlock ise ışık yeşile dönene kadar gaza basmadan motoru çalıştırmaya benzer. Hangisinin daha hızlı olduğu, kilidin ne kadar süre tutulduğuna ve işletim sisteminin bekletme maliyetine bağlıdır.</p>

<p>``</p>

<h2 id="temel-fark-uyku-mu-aktif-bekleme-mi">Temel fark: Uyku mu, aktif bekleme mi?</h2>

<p>Bir <strong>mutex</strong> alınamıyorsa bekleyen iş parçacığı çoğunlukla işletim sistemi tarafından uyutulur. Böylece işlemci başka işler çalıştırabilir. Ancak uyutma ve yeniden uyandırma; sistem çağrıları, zamanlayıcı müdahalesi ve bağlam değişimi gibi maliyetler doğurur.</p>

<p>Bir <strong>spinlock</strong> ise iş parçacığını uyutmaz. İş parçacığı kilidi tekrar tekrar kontrol ederek işlemci üzerinde aktif kalır. Kilit birkaç nanosaniye sonra açılacaksa bu yaklaşım oldukça hızlıdır. Bekleme uzarsa işlemci zamanı ve enerji boşa harcanır.</p>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Mutex</th>
      <th>Spinlock</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Bekleme biçimi</td>
      <td>İş parçacığını uyutabilir</td>
      <td>Aktif döngüde bekler</td>
    </tr>
    <tr>
      <td>CPU tüketimi</td>
      <td>Beklerken düşüktür</td>
      <td>Beklerken yüksektir</td>
    </tr>
    <tr>
      <td>Kısa kritik bölüm</td>
      <td>Ek yük oluşturabilir</td>
      <td>Genellikle avantajlıdır</td>
    </tr>
    <tr>
      <td>Uzun kritik bölüm</td>
      <td>Genellikle avantajlıdır</td>
      <td>Oldukça maliyetlidir</td>
    </tr>
    <tr>
      <td>Tek çekirdekli sistem</td>
      <td>Kullanılabilir</td>
      <td>Çoğu durumda anlamsızdır</td>
    </tr>
    <tr>
      <td>Kesme bağlamı</td>
      <td>Genellikle uygun değildir</td>
      <td>Çekirdek kodunda kullanılabilir</td>
    </tr>
  </tbody>
</table>

<p><img src="/img/mutex-vs-spinlock-63.svg" alt="mutex-vs-spinlock-63" /></p>

<h2 id="maliyetin-matematiği">Maliyetin matematiği</h2>

<p>Spinlock seçiminin mantıklı olması için bekleme maliyetinin uyutma maliyetinden küçük olması beklenir. Basitleştirilmiş karar koşulu şöyledir:</p>

\[T_{bekleme} &lt; T_{uyutma} + T_{uyandırma}\]

<p>Kilit ortalama $T_k$ süre tutuluyor ve kilidi dolu bulma olasılığı $P_c$ ise spinlock için yaklaşık bekleme maliyeti $P_c \times T_k$ olarak düşünülebilir. Mutex tarafında ise bağlam değiştirme maliyeti devreye girer. Modern sistemlerde bu değerler sabit değildir; çekirdek sayısı, önbellek mimarisi ve sistem yükü sonucu değiştirir.</p>

<p>Spinlock yalnızca döngü maliyeti de değildir. Kilit değişkeninin farklı çekirdeklerin önbellekleri arasında taşınması <strong>cache coherence</strong> trafiği oluşturur. Çok sayıda çekirdek aynı bellek satırını izliyorsa küçücük bir atomik değişken, sistemin en popüler dedikodu konusu hâline gelebilir.</p>

<h2 id="c-ile-iki-yaklaşım">C++ ile iki yaklaşım</h2>

<p>Aşağıdaki basit spinlock, <code class="language-plaintext highlighter-rouge">atomic_flag</code> kullanarak kilidi atomik biçimde almaya çalışır. <code class="language-plaintext highlighter-rouge">yield</code>, işletim sistemine başka bir iş parçacığını çalıştırabileceğini söyler; fakat kilidi gerçek anlamda uyuyan bir mutex hâline getirmez.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;atomic&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;thread&gt;</span><span class="cp">
</span>
<span class="k">class</span> <span class="nc">SpinLock</span> <span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="n">atomic_flag</span> <span class="n">locked</span> <span class="o">=</span> <span class="n">ATOMIC_FLAG_INIT</span><span class="p">;</span>

<span class="nl">public:</span>
    <span class="kt">void</span> <span class="n">lock</span><span class="p">()</span> <span class="p">{</span>
        <span class="k">while</span> <span class="p">(</span><span class="n">locked</span><span class="p">.</span><span class="n">test_and_set</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">memory_order_acquire</span><span class="p">))</span> <span class="p">{</span>
            <span class="n">std</span><span class="o">::</span><span class="n">this_thread</span><span class="o">::</span><span class="n">yield</span><span class="p">();</span>
        <span class="p">}</span>
    <span class="p">}</span>

    <span class="kt">void</span> <span class="nf">unlock</span><span class="p">()</span> <span class="p">{</span>
        <span class="n">locked</span><span class="p">.</span><span class="n">clear</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">memory_order_release</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<p>Aynı kritik bölüm standart mutex ile daha güvenli ve okunaklı biçimde korunabilir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;mutex&gt;</span><span class="cp">
</span>
<span class="n">std</span><span class="o">::</span><span class="n">mutex</span> <span class="n">mutex</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">counter</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>

<span class="kt">void</span> <span class="nf">increment</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="n">lock_guard</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">mutex</span><span class="o">&gt;</span> <span class="n">guard</span><span class="p">(</span><span class="n">mutex</span><span class="p">);</span>
    <span class="o">++</span><span class="n">counter</span><span class="p">;</span> <span class="c1">// Paylaşılan veriyi güvenle günceller.</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">std::lock_guard</code>, fonksiyondan istisnayla çıkılsa bile mutex kilidini otomatik bırakır. Üretim kodunda bu RAII yaklaşımı, elle <code class="language-plaintext highlighter-rouge">lock</code> ve <code class="language-plaintext highlighter-rouge">unlock</code> çağırmaktan daha güvenlidir.</p>

<h2 id="hangisini-ne-zaman-seçmeli">Hangisini ne zaman seçmeli?</h2>

<p>Kritik bölüm birkaç atomik işlem kadar kısaysa, çekirdek sayısı yeterliyse ve çakışma düşükse spinlock avantaj sağlayabilir. İşlem bloklayıcı G/Ç yapıyor, bellek ayırıyor veya süresi öngörülemeyen başka kodlar çağırıyorsa mutex daha doğru seçimdir. Spinlock tutulurken uyumak ise performans felaketinin davetiyesidir.</p>

<p>Modern mutex uygulamalarının önce kısa süre dönüp sonra uyuyan <strong>adaptif</strong> stratejiler kullanabildiğini de unutmayın. Dolayısıyla teorik tahmin tek başına yeterli değildir. Gerçek iş yükünü benchmark ve profiler ile ölçün. En hızlı kilit bazen spinlock, bazen mutex; çoğu zamansa paylaşılan veriyi azaltarak hiç ihtiyaç duymadığınız kilittir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="mutex" /><category term="spinlock" /><category term="eşzamanlılık" /><category term="çok çekirdekli programlama" /><category term="performans" /><category term="c++" /><summary type="html"><![CDATA[Çok çekirdekli bir sistemde iki iş parçacığı aynı veriye uzandığında küçük bir trafik kavşağı oluşur. Mutex kırmızı ışıkta motoru kapatıp beklemeye, spinlock ise ışık yeşile dönene kadar gaza basmadan motoru çalıştırmaya benzer. Hangisinin daha hızlı olduğu, kilidin ne kadar süre tutulduğuna ve işletim sisteminin bekletme maliyetine bağlıdır.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/mutex-vs-spinlock-63.png" /><media:content medium="image" url="https://program.sonsuz.us/img/mutex-vs-spinlock-63.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">OOM Killer’ın Karar Mekanizması: Linux Kurbanını Nasıl Seçer?</title><link href="https://program.sonsuz.us/posts/oom-killerin-karar-mekanizmasi-linux-kurbanini-nasil-secer/" rel="alternate" type="text/html" title="OOM Killer’ın Karar Mekanizması: Linux Kurbanını Nasıl Seçer?" /><published>2026-09-27T00:00:00+00:00</published><updated>2026-09-27T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/oom-killerin-karar-mekanizmasi-linux-kurbanini-nasil-secer</id><content type="html" xml:base="https://program.sonsuz.us/posts/oom-killerin-karar-mekanizmasi-linux-kurbanini-nasil-secer/"><![CDATA[<p>Bir Linux sunucusunda RAM ve kullanılabilir takas alanı tükendiğinde sistem tatsız bir seçimle karşılaşır: Ya tüm makine kilitlenecek ya da bazı süreçler feda edilecektir. Kernel’ın OOM (Out of Memory) Killer bileşeni ikinci yolu seçer. Ancak süreçleri rastgele avlamaz; bellek tüketimi, yönetici tercihleri ve sürecin sistem açısından önemi gibi etkenlerden bir “kötülük” puanı üretir.</p>

<p><img src="/img/oom-killerin-karar-51.svg" alt="oom-killerin-karar-51" /></p>

<p>``</p>

<h2 id="oom-ne-zaman-devreye-girer">OOM ne zaman devreye girer?</h2>

<p>Linux önce boş sayfaları, dosya önbelleklerini ve gerekirse swap alanını kullanır. Bellek ayırma isteği bu yöntemlerle karşılanamazsa OOM koşulu oluşabilir. Bununla birlikte her başarısız tahsis doğrudan küresel bir katliam başlatmaz. Sorun yalnızca belirli bir cgroup’un limitinde yaşanıyorsa <strong>cgroup OOM</strong>, belirli NUMA düğümleriyle sınırlıysa ilgili bellek politikası kapsamında OOM gerçekleşebilir.</p>

<p>Amaç, en az sistem hasarıyla yeterli belleği geri kazandırmaktır. Basitleştirilmiş düşünce şu şekilde ifade edilebilir:</p>

\[\text{badness} \approx \frac{\text{sürecin kullandığı bellek}}{\text{erişebildiği toplam bellek}} \times 1000 + \text{yönetici ayarı}\]

<p>Bu, kernel kaynak kodunun birebir formülü değildir; karar mantığını anlamaya yarayan bir modeldir. Modern Linux sürümlerinde süreç veya thread grubu tarafından kullanılan RAM ve swap miktarı önemli bir başlangıç noktasıdır. Puan, OOM olayının kapsamındaki kullanılabilir bellek üzerinden değerlendirilir.</p>

<h2 id="puanları-nerede-görürüz">Puanları nerede görürüz?</h2>

<p>Kernel her süreç için <code class="language-plaintext highlighter-rouge">/proc</code> altında iki önemli arayüz sunar:</p>

<table>
  <thead>
    <tr>
      <th>Dosya</th>
      <th>Anlamı</th>
      <th style="text-align: right">Tipik aralık</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">/proc/PID/oom_score</code></td>
      <td>Kernel’ın kullanıcıya gösterdiği güncel OOM puanı</td>
      <td style="text-align: right">0–1000</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">/proc/PID/oom_score_adj</code></td>
      <td>Yöneticinin puana uyguladığı tercih</td>
      <td style="text-align: right">-1000–1000</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">/proc/PID/status</code></td>
      <td>RSS, thread ve süreç bilgileri</td>
      <td style="text-align: right">Değişken</td>
    </tr>
  </tbody>
</table>

<p><code class="language-plaintext highlighter-rouge">oom_score</code> ne kadar yüksekse süreç o kadar iştah açıcı bir kurbandır. <code class="language-plaintext highlighter-rouge">oom_score_adj</code> ise terazinin kefesine yöneticinin parmağını koyar. Pozitif değer sürecin öldürülme olasılığını artırır; negatif değer koruma sağlar. <code class="language-plaintext highlighter-rouge">-1000</code>, süreci OOM seçiminden muaf tutmak için kullanılan özel değerdir.</p>

<p>Aşağıdaki komutlar çalışan kabuğun ayarlarını inceler:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">PID</span><span class="o">=</span><span class="nv">$$</span>
<span class="nb">cat</span> /proc/<span class="nv">$PID</span>/oom_score
<span class="nb">cat</span> /proc/<span class="nv">$PID</span>/oom_score_adj

<span class="c"># Süreci daha kolay feda edilebilir yapar.</span>
<span class="nb">echo </span>500 | <span class="nb">sudo tee</span> /proc/<span class="nv">$PID</span>/oom_score_adj
</code></pre></div></div>

<p>Son komut yalnızca puan ayarını değiştirir; süreci hemen öldürmez. Ayrıca başka bir kullanıcının sürecini değiştirmek veya negatif değer vermek için uygun yetkiler gerekir.</p>

<h2 id="en-çok-ram-kullanan-kesin-ölür-mü">En çok RAM kullanan kesin ölür mü?</h2>

<p>Hayır. Bellek tüketimi güçlü bir etkendir fakat tek etken değildir. Aynı miktarda bellek kullanan iki süreç, farklı <code class="language-plaintext highlighter-rouge">oom_score_adj</code> değerleri yüzünden tamamen farklı muamele görebilir. Kernel thread’leri ve OOM için uygun olmayan görevler de seçim dışında kalabilir. Geçmiş kernel sürümlerindeki nice değeri, çalışma süresi veya ayrıcalık gibi ölçütlere dayanan eski açıklamalar ise modern çekirdekler için yanıltıcı olabilir.</p>

<table>
  <thead>
    <tr>
      <th>Süreç</th>
      <th style="text-align: right">Bellek</th>
      <th style="text-align: right"><code class="language-plaintext highlighter-rouge">oom_score_adj</code></th>
      <th>Beklenen risk</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Veritabanı</td>
      <td style="text-align: right">4 GB</td>
      <td style="text-align: right">-800</td>
      <td>Düşük</td>
    </tr>
    <tr>
      <td>Worker</td>
      <td style="text-align: right">2 GB</td>
      <td style="text-align: right">500</td>
      <td>Yüksek</td>
    </tr>
    <tr>
      <td>Web sunucusu</td>
      <td style="text-align: right">1 GB</td>
      <td style="text-align: right">0</td>
      <td>Orta</td>
    </tr>
  </tbody>
</table>

<p>OOM Killer kurbanı seçtikten sonra genellikle sürece <code class="language-plaintext highlighter-rouge">SIGKILL</code> gönderir. Süreç temizlik kodu çalıştıramaz; kernel onun bellek alanlarının serbest kalmasını bekler. Olayın izi çoğunlukla kernel günlüğündedir:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>journalctl <span class="nt">-k</span> <span class="nt">-g</span> <span class="s1">'Out of memory\|Killed process'</span>
dmesg <span class="nt">-T</span> | <span class="nb">grep</span> <span class="nt">-Ei</span> <span class="s1">'out of memory|killed process'</span>
</code></pre></div></div>

<h2 id="pratik-savunma-stratejisi">Pratik savunma stratejisi</h2>

<p>Kritik servisleri körlemesine <code class="language-plaintext highlighter-rouge">-1000</code> ile korumak caziptir, fakat herkes dokunulmaz olursa kernel uygun kurban bulamaz. Daha sağlıklı yaklaşım; servisleri cgroup veya systemd bellek limitleriyle ayırmak, geçici worker süreçlerine pozitif ayar vermek ve kritik veritabanlarına ölçülü koruma sağlamaktır. <code class="language-plaintext highlighter-rouge">systemd</code> tarafında <code class="language-plaintext highlighter-rouge">OOMScoreAdjust=</code>, <code class="language-plaintext highlighter-rouge">MemoryHigh=</code> ve <code class="language-plaintext highlighter-rouge">MemoryMax=</code> seçenekleri bu politikanın kurulmasına yardımcı olur.</p>

<p>Kısacası OOM Killer kötü niyetli bir cellat değil, belleksiz kalmış sistemin son çare hakemidir. Puanlama mekanizmasını anlamak, kurban listesini tesadüfe bırakmak yerine sistemin hangi yükü önce bırakacağını bilinçli biçimde tasarlamanızı sağlar.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="linux" /><category term="oom-killer" /><category term="bellek-yönetimi" /><category term="kernel" /><category term="devops" /><category term="sistem-programlama" /><summary type="html"><![CDATA[Bir Linux sunucusunda RAM ve kullanılabilir takas alanı tükendiğinde sistem tatsız bir seçimle karşılaşır: Ya tüm makine kilitlenecek ya da bazı süreçler feda edilecektir. Kernel’ın OOM (Out of Memory) Killer bileşeni ikinci yolu seçer. Ancak süreçleri rastgele avlamaz; bellek tüketimi, yönetici tercihleri ve sürecin sistem açısından önemi gibi etkenlerden bir “kötülük” puanı üretir.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/oom-killerin-karar-51.png" /><media:content medium="image" url="https://program.sonsuz.us/img/oom-killerin-karar-51.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Ring 0’dan Ring 3’e: Kullanıcı Modu ve Çekirdek Modu Arasındaki Duvar</title><link href="https://program.sonsuz.us/posts/ring-0dan-ring-3e-kullanici-modu-ve-cekirdek-modu-arasindaki-duvar/" rel="alternate" type="text/html" title="Ring 0’dan Ring 3’e: Kullanıcı Modu ve Çekirdek Modu Arasındaki Duvar" /><published>2026-09-27T00:00:00+00:00</published><updated>2026-09-27T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/ring-0dan-ring-3e-kullanici-modu-ve-cekirdek-modu-arasindaki-duvar</id><content type="html" xml:base="https://program.sonsuz.us/posts/ring-0dan-ring-3e-kullanici-modu-ve-cekirdek-modu-arasindaki-duvar/"><![CDATA[<p>Bir müzik uygulamasının yanlışlıkla diskin tamamını silmesini veya sıradan bir oyunun klavye sürücüsünü yeniden programlamasını istemeyiz. İşletim sistemleri bu felaketleri yalnızca yazılım kurallarıyla değil, işlemcinin uyguladığı <strong>ayrıcalık seviyeleriyle</strong> engeller. x86 mimarisinde bunlar Ring 0 ile Ring 3 arasında numaralandırılan güvenlik halkalarıdır: Sayı küçüldükçe yetki büyür, sorumluluk ağırlaşır.
``</p>

<h2 id="halkaların-temel-mantığı">Halkaların temel mantığı</h2>

<p>İşlemci, çalışan kodun hangi ayrıcalık seviyesinde olduğunu takip eder. x86 terminolojisinde mevcut seviye <strong>CPL</strong> (Current Privilege Level) olarak adlandırılır. Kaynakların ve kod bölümlerinin erişim seviyesi ise <strong>DPL</strong> (Descriptor Privilege Level) gibi alanlarla belirtilir.</p>

<p>Basitleştirilmiş erişim düşüncesi şu eşitsizlikle anlatılabilir:</p>

\[P_{etkin} \leq P_{gerekli}\]

<p>Burada küçük sayı daha yüksek yetkiyi temsil eder. Dolayısıyla Ring 0 kodu pek çok ayrıcalıklı kaynağa ulaşabilirken Ring 3 kodu aynı işlemi yapmaya çalıştığında işlemci bir koruma hatası üretir.</p>

<table>
  <thead>
    <tr>
      <th>Halka</th>
      <th>Tipik kullanım</th>
      <th style="text-align: right">Yetki düzeyi</th>
      <th>Modern sistemlerde durum</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Ring 0</td>
      <td>Çekirdek ve temel sürücüler</td>
      <td style="text-align: right">En yüksek</td>
      <td>Yoğun biçimde kullanılır</td>
    </tr>
    <tr>
      <td>Ring 1</td>
      <td>Yardımcı sistem servisleri</td>
      <td style="text-align: right">Yüksek</td>
      <td>Genellikle kullanılmaz</td>
    </tr>
    <tr>
      <td>Ring 2</td>
      <td>Bazı sürücüler</td>
      <td style="text-align: right">Orta</td>
      <td>Genellikle kullanılmaz</td>
    </tr>
    <tr>
      <td>Ring 3</td>
      <td>Tarayıcı, oyun, editör</td>
      <td style="text-align: right">En düşük</td>
      <td>Kullanıcı uygulamalarının evidir</td>
    </tr>
  </tbody>
</table>

<p>Linux, Windows ve çoğu genel amaçlı işletim sistemi pratikte iki seviyeli bir model kullanır: çekirdek Ring 0’da, uygulamalar Ring 3’te çalışır. Ring 1 ve Ring 2 donanımda bulunsa da taşınabilirlik ve tasarım sadeliği nedeniyle çoğunlukla boş bırakılır.</p>

<h2 id="duvar-işlemci-seviyesinde-nasıl-kurulur">Duvar işlemci seviyesinde nasıl kurulur?</h2>

<p>Duvarın ilk tuğlası <strong>ayrıcalıklı komutlardır</strong>. Kesme sistemini kapatan <code class="language-plaintext highlighter-rouge">cli</code>, kontrol yazmaçlarını değiştiren talimatlar veya sayfa tablolarını yöneten işlemler Ring 3’te yürütülemez. Bir uygulama bunları denerse CPU işlemi reddeder ve çekirdeğe bir istisna bildirir.</p>

<p>İkinci tuğla <strong>bellek korumasıdır</strong>. Sanal bellekteki her sayfa için sayfa tablosu girdileri bulunur. x86 mimarisindeki U/S biti, sayfanın kullanıcı modundan erişilebilir olup olmadığını belirtir:</p>

<table>
  <thead>
    <tr>
      <th style="text-align: right">U/S biti</th>
      <th>Ring 3 erişimi</th>
      <th>Ring 0 erişimi</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: right">0</td>
      <td>Yasak</td>
      <td>İzinli</td>
    </tr>
    <tr>
      <td style="text-align: right">1</td>
      <td>İzinlere bağlı</td>
      <td>İzinlere bağlı</td>
    </tr>
  </tbody>
</table>

<p>Buna yazılabilirlik ve çalıştırılabilirlik bitleri de eklenir. Böylece bir süreç başka bir sürecin ya da çekirdeğin belleğine yalnızca adresini tahmin ederek ulaşamaz.</p>

<h2 id="uygulamalar-hizmeti-nasıl-ister">Uygulamalar hizmeti nasıl ister?</h2>

<p>Ring 3 tamamen çaresiz değildir; çekirdekten kontrollü biçimde yardım ister. Bunun kapısı <strong>sistem çağrısıdır</strong>. x86-64 sistemlerinde <code class="language-plaintext highlighter-rouge">syscall</code> komutu işlemciyi önceden belirlenmiş çekirdek giriş noktasına taşır, ayrıcalık seviyesini değiştirir ve kullanıcı bağlamının geri yüklenebilmesi için gerekli bilgileri saklar.</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;unistd.h&gt;</span><span class="cp">
</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">const</span> <span class="kt">char</span> <span class="n">mesaj</span><span class="p">[]</span> <span class="o">=</span> <span class="s">"Merhaba, cekirdek!</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
    <span class="n">write</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">mesaj</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">mesaj</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span>
    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Buradaki <code class="language-plaintext highlighter-rouge">write</code>, ekrana doğrudan erişmez. Standart kütüphane uygun sistem çağrısını başlatır; çekirdek dosya tanımlayıcısını ve kullanıcı belleğindeki adresi doğrular. İstek güvenliyse terminal sürücüsüne kadar uzanan işi çekirdek gerçekleştirir.</p>

<p>Geçişin maliyeti kabaca şöyle düşünülebilir:</p>

\[T_{toplam} = T_{geçiş} + T_{doğrulama} + T_{işlem} + T_{dönüş}\]

<p>Bu nedenle her küçük işlem için sistem çağrısı yapmak yerine tamponlama kullanılır. Örneğin yüzlerce karakter tek tek değil, bir blok hâlinde yazılabilir.</p>

<h2 id="kesintiler-hatalar-ve-kontrollü-dönüş">Kesintiler, hatalar ve kontrollü dönüş</h2>

<p>Donanım kesintileri ve sayfa hataları da kontrolü çekirdeğe aktarabilir. İşlemci, <strong>IDT</strong> içindeki hedef kapının yetki kurallarını denetler; rastgele bir adrese sıçramaz. Çekirdek olayı işledikten sonra özel dönüş talimatlarıyla Ring 3 bağlamını geri yükler.</p>

<p>Sonuç olarak kullanıcı modu ile çekirdek modu arasındaki duvar basit bir programlama geleneği değildir. Ayrıcalıklı komutlar, sayfa tabloları, kesme kapıları ve sistem çağrısı mekanizması birlikte çalışır. Uygulama kontrolden çıksa bile işlemci ona nazikçe ama kesin biçimde şunu söyler: Donanıma dokunmak istiyorsan önce çekirdekten izin al.</p>

<p><img src="/img/ring-0dan-ring-41.svg" alt="ring-0dan-ring-41" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="işletim sistemi" /><category term="çekirdek" /><category term="işlemci mimarisi" /><category term="güvenlik" /><category term="x86" /><category term="sistem programlama" /><summary type="html"><![CDATA[Bir müzik uygulamasının yanlışlıkla diskin tamamını silmesini veya sıradan bir oyunun klavye sürücüsünü yeniden programlamasını istemeyiz. İşletim sistemleri bu felaketleri yalnızca yazılım kurallarıyla değil, işlemcinin uyguladığı ayrıcalık seviyeleriyle engeller. x86 mimarisinde bunlar Ring 0 ile Ring 3 arasında numaralandırılan güvenlik halkalarıdır: Sayı küçüldükçe yetki büyür, sorumluluk ağırlaşır.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/ring-0dan-ring-41.png" /><media:content medium="image" url="https://program.sonsuz.us/img/ring-0dan-ring-41.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Swarm Intelligence: Parçacık Sürü Optimizasyonunun Yapay Zekâdaki Yeri</title><link href="https://program.sonsuz.us/posts/swarm-intelligence-parcacik-suru-optimizasyonunun-yapay-zekadaki-yeri/" rel="alternate" type="text/html" title="Swarm Intelligence: Parçacık Sürü Optimizasyonunun Yapay Zekâdaki Yeri" /><published>2026-09-27T00:00:00+00:00</published><updated>2026-09-27T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/swarm-intelligence-parcacik-suru-optimizasyonunun-yapay-zekadaki-yeri</id><content type="html" xml:base="https://program.sonsuz.us/posts/swarm-intelligence-parcacik-suru-optimizasyonunun-yapay-zekadaki-yeri/"><![CDATA[<p>Doğada merkezi bir yönetici olmadan sergilenen kolektif davranışlar, şaşırtıcı derecede başarılı sonuçlar üretir. Kuşlar yiyecek ararken birbirlerinin hareketlerinden yararlanır, balıklar tehlikeden birlikte kaçar ve karıncalar en kısa yolu kimse onlara harita vermeden bulur. <strong>Parçacık Sürü Optimizasyonu</strong> (Particle Swarm Optimization veya PSO), bu sosyal davranışı matematiksel bir optimizasyon yöntemine dönüştürür.</p>

<p>``</p>

<h2 id="sürü-zekâsı-nedir">Sürü zekâsı nedir?</h2>

<p>Sürü zekâsı, basit kuralları izleyen çok sayıda bireyin etkileşiminden ortaya çıkan kolektif problem çözme yeteneğidir. Buradaki temel fikir, tek bir bireyin kusursuz olmasına gerek olmadığıdır. Bireyler kendi deneyimlerini grubun deneyimiyle birleştirdiğinde etkili bir arama mekanizması oluşur.</p>

<p>PSO, 1995 yılında James Kennedy ve Russell Eberhart tarafından geliştirilmiştir. Algoritmada her olası çözüm bir <strong>parçacık</strong>, tüm parçacıklar ise bir <strong>sürü</strong> olarak temsil edilir. Parçacıklar çözüm uzayında dolaşarak amaç fonksiyonunun en iyi değerini arar.</p>

<table>
  <thead>
    <tr>
      <th>Doğadaki kavram</th>
      <th>PSO karşılığı</th>
      <th>Görevi</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Kuş</td>
      <td>Parçacık</td>
      <td>Aday çözümü temsil eder</td>
    </tr>
    <tr>
      <td>Kuşun konumu</td>
      <td>Çözüm vektörü</td>
      <td>Parametrelerin mevcut değerlerini taşır</td>
    </tr>
    <tr>
      <td>Uçuş yönü</td>
      <td>Hız vektörü</td>
      <td>Sonraki hareketi belirler</td>
    </tr>
    <tr>
      <td>Bulunan yiyecek</td>
      <td>En iyi çözüm</td>
      <td>Amaç fonksiyonunun optimumuna karşılık gelir</td>
    </tr>
    <tr>
      <td>Sürü iletişimi</td>
      <td>Küresel en iyi bilgi</td>
      <td>Parçacıkları umut vadeden bölgeye yönlendirir</td>
    </tr>
  </tbody>
</table>

<h2 id="pso-nasıl-çalışır">PSO nasıl çalışır?</h2>

<p>Her parçacığın bir konumu $x_i$ ve hızı $v_i$ bulunur. Ayrıca parçacık, şimdiye kadar keşfettiği en iyi konumu $p_i$ olarak hatırlar. Sürünün bulduğu en iyi konum ise $g$ ile gösterilir.</p>

<p>Hız güncelleme denklemi şöyledir:</p>

\[v_i(t+1)=w v_i(t)+c_1r_1(p_i-x_i(t))+c_2r_2(g-x_i(t))\]

<p>Yeni konum da şu şekilde hesaplanır:</p>

\[x_i(t+1)=x_i(t)+v_i(t+1)\]

<p>Burada $w$ eylemsizlik katsayısıdır ve parçacığın önceki yönünü ne kadar koruyacağını belirler. $c_1$ bilişsel katsayıdır; parçacığın kendi deneyimine bağlılığını temsil eder. $c_2$ sosyal katsayıdır ve sürünün keşfine verilen önemi kontrol eder. $r_1$ ile $r_2$, $[0,1]$ aralığında rastgele sayılardır. Bu rastlantısallık, bütün parçacıkların erkenden aynı noktaya yığılmasını önlemeye yardımcı olur.</p>

<table>
  <thead>
    <tr>
      <th>Katsayı tercihi</th>
      <th>Baskın davranış</th>
      <th>Olası sonuç</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Yüksek $w$</td>
      <td>Geniş alanları keşfetme</td>
      <td>Optimumu kaçırma riski azalabilir</td>
    </tr>
    <tr>
      <td>Yüksek $c_1$</td>
      <td>Bireysel hareket</td>
      <td>Parçacıklar bağımsız davranır</td>
    </tr>
    <tr>
      <td>Yüksek $c_2$</td>
      <td>Sürüye uyum</td>
      <td>Hızlı yakınsama sağlanır</td>
    </tr>
    <tr>
      <td>Dengeli değerler</td>
      <td>Keşif ve sömürü dengesi</td>
      <td>Genellikle daha kararlı sonuç alınır</td>
    </tr>
  </tbody>
</table>

<h2 id="python-ile-basit-bir-uygulama">Python ile basit bir uygulama</h2>

<p>Aşağıdaki örnek, $f(x)=x^2$ fonksiyonunun minimumunu arar. Teorik minimum $x=0$ noktasındadır.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="n">random</span>

<span class="n">parcacik_sayisi</span> <span class="o">=</span> <span class="mi">20</span>
<span class="n">konumlar</span> <span class="o">=</span> <span class="p">[</span><span class="n">random</span><span class="p">.</span><span class="nf">uniform</span><span class="p">(</span><span class="o">-</span><span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">)</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">parcacik_sayisi</span><span class="p">)]</span>
<span class="n">hizlar</span> <span class="o">=</span> <span class="p">[</span><span class="n">random</span><span class="p">.</span><span class="nf">uniform</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">parcacik_sayisi</span><span class="p">)]</span>
<span class="n">kisisel_en_iyi</span> <span class="o">=</span> <span class="n">konumlar</span><span class="p">.</span><span class="nf">copy</span><span class="p">()</span>

<span class="k">def</span> <span class="nf">uygunluk</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
    <span class="k">return</span> <span class="n">x</span> <span class="o">**</span> <span class="mi">2</span>

<span class="n">kuresel_en_iyi</span> <span class="o">=</span> <span class="nf">min</span><span class="p">(</span><span class="n">kisisel_en_iyi</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">uygunluk</span><span class="p">)</span>

<span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="mi">100</span><span class="p">):</span>
    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">parcacik_sayisi</span><span class="p">):</span>
        <span class="n">r1</span><span class="p">,</span> <span class="n">r2</span> <span class="o">=</span> <span class="n">random</span><span class="p">.</span><span class="nf">random</span><span class="p">(),</span> <span class="n">random</span><span class="p">.</span><span class="nf">random</span><span class="p">()</span>
        <span class="n">hizlar</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span>
            <span class="mf">0.7</span> <span class="o">*</span> <span class="n">hizlar</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
            <span class="o">+</span> <span class="mf">1.5</span> <span class="o">*</span> <span class="n">r1</span> <span class="o">*</span> <span class="p">(</span><span class="n">kisisel_en_iyi</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">-</span> <span class="n">konumlar</span><span class="p">[</span><span class="n">i</span><span class="p">])</span>
            <span class="o">+</span> <span class="mf">1.5</span> <span class="o">*</span> <span class="n">r2</span> <span class="o">*</span> <span class="p">(</span><span class="n">kuresel_en_iyi</span> <span class="o">-</span> <span class="n">konumlar</span><span class="p">[</span><span class="n">i</span><span class="p">])</span>
        <span class="p">)</span>
        <span class="n">konumlar</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+=</span> <span class="n">hizlar</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>

        <span class="k">if</span> <span class="nf">uygunluk</span><span class="p">(</span><span class="n">konumlar</span><span class="p">[</span><span class="n">i</span><span class="p">])</span> <span class="o">&lt;</span> <span class="nf">uygunluk</span><span class="p">(</span><span class="n">kisisel_en_iyi</span><span class="p">[</span><span class="n">i</span><span class="p">]):</span>
            <span class="n">kisisel_en_iyi</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">konumlar</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>

    <span class="n">kuresel_en_iyi</span> <span class="o">=</span> <span class="nf">min</span><span class="p">(</span><span class="n">kisisel_en_iyi</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">uygunluk</span><span class="p">)</span>

<span class="nf">print</span><span class="p">(</span><span class="sh">"</span><span class="s">Bulunan minimum noktası:</span><span class="sh">"</span><span class="p">,</span> <span class="n">kuresel_en_iyi</span><span class="p">)</span>
</code></pre></div></div>

<p>Kod, parçacıkları rastgele başlatır; ardından hız ve konumlarını 100 tur boyunca günceller. Her turda bireysel ve küresel rekorlar yenilenir. Sonuç genellikle sıfıra oldukça yakın çıkar.</p>

<h2 id="yapay-zekâdaki-kullanım-alanları">Yapay zekâdaki kullanım alanları</h2>

<p>PSO; sinir ağlarının ağırlıklarını ayarlamak, özellik seçmek, hiperparametre optimizasyonu yapmak, robot rotaları planlamak ve enerji sistemlerini düzenlemek için kullanılabilir. Türev bilgisi istememesi, karmaşık ve doğrusal olmayan problemlerde önemli bir avantajdır. Buna karşılık doğru katsayılar seçilmezse yerel optimuma erken yakınsayabilir ve yüksek boyutlarda maliyetli hâle gelebilir.</p>

<p>Kısacası PSO, “en iyi çözümü tek başına bul” yaklaşımı yerine “deneyimini paylaş ve birlikte ara” der. Bazen karmaşık bir problemi çözmek için gereken şey daha güçlü bir birey değil, daha iyi iletişim kuran bir sürüdür.</p>

<p><img src="/img/swarm-intelligence-parcacik-75.svg" alt="swarm-intelligence-parcacik-75" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="yapay zekâ" /><category term="pso" /><category term="sürü zekâsı" /><category term="optimizasyon" /><category term="sezgisel algoritmalar" /><category term="makine öğrenmesi" /><summary type="html"><![CDATA[Doğada merkezi bir yönetici olmadan sergilenen kolektif davranışlar, şaşırtıcı derecede başarılı sonuçlar üretir. Kuşlar yiyecek ararken birbirlerinin hareketlerinden yararlanır, balıklar tehlikeden birlikte kaçar ve karıncalar en kısa yolu kimse onlara harita vermeden bulur. Parçacık Sürü Optimizasyonu (Particle Swarm Optimization veya PSO), bu sosyal davranışı matematiksel bir optimizasyon yöntemine dönüştürür.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/swarm-intelligence-parcacik-75.png" /><media:content medium="image" url="https://program.sonsuz.us/img/swarm-intelligence-parcacik-75.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>