POSIX asenkron G / Ç'nin (AIO) durumu nedir?


94

POSIX AIO tesislerini değişen miktarlarda ayrıntıyla açıklayan web'de dağınık sayfalar vardır. Hiçbiri çok yeni değil. Tam olarak ne tarif ettikleri belli değil. Örneğin, buradaki Linux çekirdeği eşzamansız G / Ç desteği için "resmi" (?) Web sitesi soketlerin çalışmadığını söylüyor, ancak Ubuntu 8.04.1 iş istasyonumdaki "aio.h" kılavuz sayfalarının tümü şunu ima ediyor gibi görünüyor: rastgele dosya tanımlayıcıları için çalışır. Daha sonra kütüphane katmanında daha az dokümantasyonla çalışan başka bir proje var .

Bilmek isterdim:

  • POSIX AIO'nun amacı nedir? Bulabildiğim en açık uygulama örneğinin soketleri desteklemediğini söylediği için, her şey bana tuhaf geliyor. Yalnızca eşzamansız disk G / Ç için mi? Öyleyse, neden hiper genel API? Değilse, disk G / Ç neden saldırıya uğrayan ilk şey?
  • Bakabileceğim örnek tam POSIX AIO programları nerede var ?
  • Bunu gerçekten kullanan var mı?
  • Hangi platformlar POSIX AIO'yu destekler? Bunun hangi kısımlarını destekliyorlar? Hiç kimse <aio.h>vaat ediyor gibi görünen "herhangi bir FD'ye herhangi bir I / O'yu" gerçekten destekliyor mu?

Kullanabileceğim diğer çoklama mekanizmaları mükemmel derecede iyi, ancak etrafta dolaşan rastgele bilgi parçaları beni meraklandırdı.

Yanıtlar:


28

Ağ G / Ç, AIO için bir öncelik değildir çünkü POSIX ağ sunucularını yazan herkes, olay tabanlı, engellemeyen bir yaklaşım kullanır. Eski tarz Java "milyarlarca iş parçacığı engelleme" yaklaşımı korkunç derecede berbat.

Disk yazma G / Ç zaten arabelleğe alınmıştır ve disk okuma G / Ç, posix_fadvise gibi işlevler kullanılarak arabelleğe önceden getirilebilir. Bu, AIO için tek yararlı amaç olarak doğrudan, arabelleğe alınmamış disk G / Ç'sini bırakır.

Doğrudan, arabelleğe alınmamış G / Ç yalnızca işlem veritabanları için gerçekten yararlıdır ve bunlar, disk G / Ç'lerini yönetmek için kendi iş parçacıklarını veya işlemlerini yazma eğilimindedir.

Böylece, sonunda POSIX AIO'yu herhangi bir yararlı amaca hizmet etmeyecek durumda bırakır . Onu kullanma.


8
Ağ (NFS, Samba) dosya sistemlerinden okuma / yazma ne olacak?
Alex B

1
iyi. Önbelleğe gitmelerine izin verirsem, en tepelerde dirty_ratio'ya ulaşacak ve diğerlerini engelleyecek birkaç büyük aptal yazarım var. Onlara sadece doğrudan IO kullanırsam, bu çok yavaş. Eğer 1 iş parçacığım olsaydı kendi başıma idare edebilirdim, ancak 1 basamakta farklı IO önceliklerini desteklemek zor olacak. AIO çalışsaydı, AIO + CFQ gerçekten iyi bir kombinasyon gibi görünürdü
n-alexander

37
Katılmıyorum. Disk G / Ç arabelleğe alınma eğilimindedir, ancak engelleme olabilir. Bir FD dosyasını yoklarken (), bloke edecek olsa bile her zaman FD'nin okunabilir olduğunu bildirir. Bu, iş parçacıkları veya AIO kullanılmadığı sürece disk dosyalarında olaylı bir şekilde bloke olmayan işlemleri gerçekleştirmeyi imkansız kılar.
Hongli

2
@Matt: Datagram soketleri için sıralama önemli değildir. @Zan: eşzamansız G / Ç, gerçek zamanlı veri akışını önceden arabelleğe almak için çok iyidir, örneğin medya oynatıcılar.
Ben Voigt

13
AIO'nun olay tabanlı sistemlerde işe yaramaz olduğu doğru değil. Recv () 'ye olay bazlı bildirim ile yapamayacağınız uygun AIO ile sıfır kopya ağına gerçekten ulaşabilirsiniz. Diğer şeyler, bunu çoğunlukla teorik bir sınırlama yapmak için komplo kurabilir, ancak bence uygun AIO (Windows'ta a la OVERLAPPED) eksikliği Linux'taki son büyük deliklerden biridir.
Jon Watte

70

Soket giriş / çıkışlarını verimli bir şekilde yapmak, kqueue, epoll, IO tamamlama portları ve benzerleri ile çözüldü. Eşzamansız dosya G / Ç yapmak bir nevi geç gelen bir durumdur (pencerelerin örtüşen G / Ç ve posix AIO için solaris erken desteği dışında).

Soket G / Ç yapmak istiyorsanız, yukarıdaki mekanizmalardan birini kullanmanız muhtemelen daha iyidir.

Bu nedenle, AIO'nun temel amacı, eşzamansız disk G / Ç sorununu çözmektir. Bu, büyük olasılıkla Mac OS X'in soketleri değil, yalnızca AIO'yu desteklemesinin nedenidir (çünkü kqueue bunu zaten çok daha iyi yapar).

Yazma işlemleri genellikle çekirdek tarafından önbelleğe alınır ve daha sonra temizlenir. Örneğin, sürücünün okuma kafası bloğun yazılacağı yerden geçerken.

Bununla birlikte, okuma işlemleri için, çekirdeğin okumalarınızı önceliklendirmesini ve sıralamasını istiyorsanız, AIO gerçekten tek seçenektir. İşte neden kernal (teorik olarak) bunu herhangi bir kullanıcı seviyesindeki uygulamadan daha iyi yapabilir:

  • Çekirdek, yalnızca uygulama disk işlerinizi değil, tüm disk G / Ç'lerini görür ve bunları küresel düzeyde sipariş edebilir
  • Çekirdek (olabilir) disk okuma kafasının nerede olduğunu bilebilir ve kafayı en kısa mesafeye taşımak için kendisine ilettiğiniz okuma işlerini en uygun sırada seçebilir
  • Çekirdek, okuma işlemlerinizi daha da optimize etmek için yerel komut kuyruğundan yararlanabilir.
  • Lio_listio () kullanarak sistem çağrısı başına readv () ile olduğundan daha fazla okuma işlemi gerçekleştirebilirsiniz, özellikle de okumalarınız (mantıksal olarak) bitişik değilse, sistem çağrısı ek yükünden küçük bir miktar tasarruf edebilirsiniz.
  • Bir okuma veya yazma çağrısını engellemek için fazladan bir iş parçacığına ihtiyacınız olmadığı için programınız AIO ile biraz daha basit olabilir.

Bununla birlikte, posix AIO'nun oldukça garip bir arayüzü var, örneğin:

  • Olay geri aramalarının tek etkili ve iyi desteklenen yolu sinyaller yoluyladır, bu da işlem-global sinyal ad alanından sinyal numaralarının kullanılması anlamına geldiği için bir kitaplıkta kullanılmasını zorlaştırır. İşletim sisteminiz gerçek zamanlı sinyalleri desteklemiyorsa, bu aynı zamanda hangisinin gerçekten bittiğini bulmak için tüm bekleyen isteklerinizi gözden geçirmeniz gerektiği anlamına gelir (bu, örneğin Linux değil, Mac OS X için geçerlidir). Çok iş parçacıklı bir ortamda sinyalleri yakalamak da bazı zor kısıtlamalara neden olur. Tipik olarak sinyal işleyicinin içindeki olaya tepki veremezsiniz, ancak bir sinyal yükseltmeniz, bir boruya yazmanız veya signalfd () (linux üzerinde) kullanmanız gerekir.
  • lio_suspend (), select () ile aynı sorunlara sahiptir, iş sayısıyla pek iyi ölçeklenmez.
  • lio_listio (), uygulandığı haliyle, geçebileceğiniz oldukça sınırlı sayıda işe sahiptir ve bu sınırı taşınabilir bir şekilde bulmak önemsiz değildir. Başarısız olabilecek sysconf (_SC_AIO_LISTIO_MAX) 'ı çağırmanız gerekir, bu durumda zorunlu olarak tanımlanmayan AIO_LISTIO_MAX tanımlamasını kullanabilirsiniz, ancak daha sonra destekleneceği garantili olarak tanımlanan 2'yi kullanabilirsiniz.

Posix AIO kullanan gerçek dünya uygulamasına gelince, destek sunarken bir performans ölçümü de yayınlayan lighttpd'ye (lighty) göz atabilirsiniz .

Çoğu posix platformu şimdiye kadar posix AIO'yu desteklemektedir (Linux, BSD, Solaris, AIX, tru64). Windows, örtüşen dosya G / Ç'si aracılığıyla bunu destekler. Anladığım kadarıyla yalnızca Solaris, Windows ve Linux eşzamansız'ı gerçekten destekliyor. dosya G / Ç'sini sürücüye kadar tamamlarken, diğer işletim sistemleri asenkronu taklit eder. Çekirdek iş parçacıklı G / Ç. Linux istisna olarak, glibc'deki posix AIO uygulaması, kullanıcı seviyesi iş parçacıklarıyla eşzamansız işlemleri taklit ederken, yerel eşzamansız G / Ç arabirimi (io_submit () vb.), Sürücünün desteklediğini varsayarsak, sürücüye kadar tamamen eşzamansızdır. .

İşletim sistemleri arasında herhangi bir fd için posix AIO'yu desteklememenin, ancak bunu normal dosyalarla kısıtlamanın oldukça yaygın olduğuna inanıyorum.


Windows, Win32 ilk çıktığından beri disk dosyalarını destekleyen OVERLAPPED I / O'ya sahipti. Hiç de yeni değil. Ve POSIX üzerinde, sinyal ad alanı süreç-global değil, evre başına. Sinyaller belirli iş parçacıklarına gönderilir (ya da bunun bir istisnasıdır, kesin olarak hatırlayamıyorum?).
Ben Voigt

1
AIO'nun sinyallerini hangi iş parçacığına göndereceğini belirlemenin bir yolu yoktur. Linux'ta, bunu çoğunlukla aio _ * () komutunu yayınlayan iş parçacığına gönderiyor gibi görünüyor , ancak her zaman değil (buna bulduğum tek çözüm birden çok sinyal fd oluşturmaktı). Birkaç yıl önce çekirdek posta listesinde bunu ekleyecek bir linux yaması vardı, ama asla giremedi ve POSIX'in bir uzantısı olacaktı. Mac OS X'te sinyaller çoğunlukla ana iş parçacığına iletiliyor gibi görünüyor (benim deneyimime göre). POSIX'in belirli bir davranış gerektirdiğini düşünmüyorum, eğer öyleyse, spesifikasyonun bir kısmını görmek isterim.
Arvid

5
glibc'nin aio_read / write uygulaması kullanıcı alanında evreler kullanır, dolayısıyla burada çekirdek evreleri bile kullanılmaz.
Marenz

"Her zaman tipik" ne anlama geliyor? Yazılar, herhangi bir yöntem için veya AIO kullanılırken çekirdek tarafından önbelleğe alınır? Görünüşe göre yazılıma yazma işleminin başarıyla tamamlandığından emin olmanın bir yolu olmalı; aksi takdirde bütünlük ve işlem hedefleri karşılanamaz.
MikeB

AIO'yu kullanabileceğiniz başka bir canlı örnek nginx'tir. Tüm modlar desteklenmektedir. Kullanıcı alanı iş parçacıklarına aktarmayı tercih ederseniz, normalde bunu doğrudan GÇ'den çok daha kötü bulursunuz, ancak Linux yerel AIO, doğrudan GÇ ile eşittir. AIO'nun önemli ölçüde yararlı olabileceği durum, ciddi sayfa önbelleği baskısıdır. Async ve Direct IO'lar
fitil


2

Aio_write - glibc'de gerçeklenmiştir; aio_read veya aio_write işlevinin ilk çağrısı, bu iş parçacığına bir dizi kullanıcı modu evresi, aio_write veya aio_read post istekleri oluşturur, evre pread / pwrite yapar ve tamamlandığında cevap bloke edilmiş çağrı dizisine geri gönderilir.

Ayrıca 'gerçek' aio var - çekirdek seviyesi tarafından destekleniyor (bunun için libaio gerekiyor, http://linux.die.net/man/2/io_submit io_submit çağrısına bakın ); bunun için de O_DIRECT'e ihtiyacınız var (ayrıca tüm dosya sistemleri tarafından desteklenmeyebilir, ancak büyük olanlar onu destekler)

buraya bakın:

http://lse.sourceforge.net/io/aio.html

http://linux.die.net/man/2/io_submit

Linux'ta POSIX AIO ve libaio arasındaki fark nedir?


İle ilgili eksikliklerin çoğu aio_writeyukarıda stackoverflow.com/a/5307557/13564
Glyph
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.