RAM / OOM hatasını birleştirme


11

Bu soru oldukça uzundur, bu yüzden en üstteki soruları soracağım ve sonra sorulara gelme yöntemimi inceleyeceğim:

  1. Yeterli bitişik RAM olmadığı için (Busybox tabanlı) rm yürütülmedi mi?
  2. Öyleyse, sistemin yeniden başlatılmasına başvurmadan DMA'yı birleştirmek için hafif bir yöntem var mı?
  3. Değilse, buna ne sebep oldu? Gelecekte bunun olmasını nasıl önleyebilirim?

Test sistemimiz son birkaç gündür oldukça yoğun bir şekilde çalıştıktan sonra - sisteme telnet yaptım ve test sonuçlarını kontrol ettim. Bazı verileri silmeye geldiğimde, sistem komut satırını döndürdü (komut doğru yürütülmüş gibi). Dizini başka bir sonuç kümesi için kontrol etmeye geldiğimde, dosyanın hala var olduğunu gördüm (ls kullanarak).

Bundan sonra kabuk komutlarımın beklendiği gibi çalışmadığını fark ettim.

RM doğru bir şekilde yürütülemediğinde dmesg'den bir çıktı ile başlayacağım :

6821 (rm) işleminden 61440 uzunluğunun tahsisi başarısız oldu

İşlemci başına DMA:

İşlemci 0: hi: 0, btch: 1 usd: 0

Active_anon: 0 active_file: 1 inactive_anon: 0 inactive_file: 0 kullanılamaz: 6 kirli: 0 geri yazma: 0 kararsız: 0 ücretsiz: 821 slab: 353 eşlenmiş: 0 sayfa tablosu: 0 geri dönme: 0

DMA içermez: 3284kB min: 360kB düşük: 448kB yüksek: 540kB aktif_anon: 0kB inactive_anon: 0kB active_file: 4kB inactive_file: 0kB kullanılamaz: 24kB mevcut: 8128kB sayfa Hayır

lowmem_reserve []: 0 0 0

DMA: 31 * 4kB 47 * 8kB 42 * 16kB 64 * 32kB 1 * 64kB 0 * 128kB 0 * 256kB 0 * 512kB 0 * 1024kB 0 * 2048kB 0 * 4096kB = 3284kB

Toplam 14 sayfa

İşlem verileri için RAM ayrılamıyor, errno 12

Başlangıçta, bitişik belleğin en büyük bölümünde programı çalıştıramayacağımı düşündüm. DMA çok parçalanmıştı ve sistemi belleği birleştirmek için bir yol bulmalıydım.

Sonra hızlı bir matematik / akıl sağlığı kontrolü yaptım ve programın tek 64kB bitişik bellek yuvasında çalışabilmesi gerektiğini fark ettim. Rm, 61440 bayt (60kB) talep ediyordu.

Eski bir "manuel dolandırmak" yaptım ve sistemi yeniden başlattım. Sytem I proc / buddyinfo çıktısını yeniden başlattığımda:

Node 0, zone DMA 2 8 3 12 0 1 0 1 0 1 0

Hangi harita şüpheli:

  • 2 x 4 kB
  • 8 x 8 kB
  • 3 x 16 kB
  • 12 x 32 kB
  • 1 x 128 kB
  • 1 x 512 kB

Ancak, yukarıdaki değerler listesini özetliyorsa, / proc / meminfo çıktısıyla eşleşmez :

MemTotal:           6580 kB
MemFree:            3164 kB
Buffers:               0 kB
Cached:              728 kB
SwapCached:            0 kB
Active:              176 kB
Inactive:            524 kB
Active(anon):          0 kB
Inactive(anon):        0 kB
Active(file):        176 kB
Inactive(file):      524 kB`
Unevictable:           0 kB
Mlocked:               0 kB
MmapCopy:            844 kB
SwapTotal:             0 kB
SwapFree:              0 kB
Dirty:                 0 kB
Writeback:             0 kB
AnonPages:             0 kB
Mapped:                0 kB
Slab:               1268 kB
SReclaimable:        196 kB
SUnreclaim:         1072 kB
PageTables:            0 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:        3288 kB
Committed_AS:          0 kB
VmallocTotal:          0 kB
VmallocUsed:           0 kB
VmallocChunk:          0 kB

Özetlemek gerekirse, sorularım:

  1. Rm yeterli bitişik RAM olmadığı için yürütülmedi mi?
  2. Öyleyse, sistemin yeniden başlatılmasına başvurmadan DMA'yı birleştirmek için hafif bir yöntem var mı?
  3. Değilse, buna ne sebep oldu? Gelecekte bunun olmasını nasıl önleyebilirim?

UClinux 2.6.30 sürümünü çalıştıran Lantronix'in XPort Pro'sunu (8MB, Linux OS) kullanıyorum. Kullanılan kabuk sustur.


Küçük nokta: bellek parçaları listenizden 1 x 2048 kB çıkardınız. Bunu dahil ederseniz, toplam / proc / meminfo'da listelenen 3164 kB'ye çok yakın olan 3192 kB'dir.
Alex Selby

Yanıtlar:


11

2. soruda (belleği birleştirmek), https://www.kernel.org/doc/Documentation/sysctl/vm.txt adresinden alıntı :

compact_memory

Yalnızca CONFIG_COMPACTION ayarlandığında kullanılabilir. Dosyaya 1 yazıldığında, tüm bölgeler, boş bellek mümkün olduğunda bitişik bloklar halinde kullanılabilecek şekilde sıkıştırılır. Bu, örneğin büyük sayfaların tahsisinde önemli olabilir, ancak işlemler aynı zamanda belleği gerektiği gibi doğrudan sıkıştırır.

bu, aşağıdaki komutun (kök ayrıcalıklarıyla yürütüldüğünü ve yukarıda belirtilen çekirdek seçeneğinin etkinleştirilmiş olduğunu gösterir)

echo 1 > /proc/sys/vm/compact_memory

çekirdeğe belleği mümkün olduğunca birleştirmeye çalışmasını söylemelidir. Örneğin bazı RHEL6 sürümlerinde, çekirdeğin çökmesine neden olabilir ...


1
Geri dönüp eski bir soruya yorum yapmak için zaman harcadığınız için teşekkür ederiz!
OldTinfoil

7

Biraz zaman aldı ama alt sorularımın hepsine cevap verene kadar cevaplamaya devam edeceğimi düşündüm.

Yine de başlamadan önce, "parçalara ayırma" çalışma belleği söz konusu olduğunda doğru terimin "çalışma belleği" olarak sıkıştırıldığından bahsedeceğim.

1. Yeterli bitişik RAM olmadığı için rm yürütülmedi mi?

Sonuç olarak haklıydım - rm yürütmedi çünkü yetersiz bitişik RAM vardı. Sistem RAM'i alıp parçalara ayırıyor, bu yüzden onu vazgeçilmez kılıyor.

2. Öyleyse, sistemin yeniden başlatılmasına başvurmadan DMA'yı birleştirmek için hafif bir yöntem var mı?

Gömülü sistemi yeniden başlatmanın dışında, belleği sıkıştırmanın bir yolu olmadığı anlaşılıyor. MMU'suz bir sistem söz konusu olduğunda, önleme oyunun adıdır.

Bir parçam, yazılımda MMU'yu taklit etmek için linux çekirdeğini hacklemek mümkünse düşünürüm. Mümkünse, birisi zaten yapardı. Onun tamamen yeni bir konsept olduğunu hayal bile edemiyorum;)

3. Gelecekte nasıl olmasını nasıl önleyebilirim?

Bu proje için, her ihtiyaç duyulduğunda programı manuel olarak başlatmak için cron kullanıyordum. Bunu yapmanın çok daha iyi bir yolu, programı başlangıçta çağırmak ve daha sonra gerekli olana kadar programı uykuya zorlamaktır. Bu şekilde, belleğin her kullanımda ayrılması gerekmez. Böylece parçalanma azalır.

Projenin ilk yinelemesinde, kritik komutları (rm gibi) gerçekleştirmek için kabuk komut dosyası çağrılarıma güveniyorduk. İhtiyacımız olmasaydı tekerleği yeniden icat etme ihtiyacını görmedik.

Bununla birlikte, MMU'suz bir sistem için kabuktan mümkün olduğunca kaçınmanızı tavsiye ederim -

( Soru , yürütürsen ne olur ls -la /path/to/directory/ | grep file-i-seek?)

( Yanıt : yeni bir alt işlem başlatır)

C programınızda bazı temel kabuk komut dosyası işlevlerini uygulamanız gerekiyorsa, BusyBox'ta kullanılan kaynak kodunu kontrol etmenizi öneririz . Muhtemelen gömülü sisteminizde C kullanacaksınız.


Geri gelmek ve bulgularınızı paylaşmak için zaman ayırdığınız için teşekkür ederiz.
Caleb

3
[Bunun eski olduğunu anlıyorum] Bir MMU'yu taklit etmek zor ... MMU olmadan, her program doğrudan fiziksel veri yollarını bellek veri yolunda göründüğü gibi kullanır. Bir tanesini taklit edebilirsiniz, ancak her bellek erişimine müdahale etmeniz gerekir (gerçek bir MMU'nun yaptığı gibi). Performans korkunç olurdu. Alternatif olarak, dolaylı işaretçiler kullanabilirsiniz (Mac OS Classic'in yaptığı gibi, "tutamaklar" olarak adlandırılır), ancak daha sonra tamamen zor bir API'niz ve pre-emption karşısında çok zor bir API'niz var (Mac OS Classic, kooperatif çoklu görevini kullandı) .
derobert

Geri döndüğünüz ve bu yanıtı yazmak için zaman harcadığınız için teşekkür ederiz. MacOS classic'in bunu yaptığını bilmiyordum.
OldTinfoil
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.