Kami sedang mengkompilasi aplikasi C / C ++ tertanam yang digunakan dalam perangkat terlindung di lingkungan yang dibombardir dengan radiasi pengion . Kami menggunakan GCC dan kompilasi silang untuk ARM. Ketika digunakan, aplikasi kita menghasilkan beberapa data yang salah dan sering crash lebih dari yang kita inginkan. Perangkat keras dirancang untuk lingkungan ini, dan aplikasi kami telah berjalan di platform ini selama beberapa tahun.
Apakah ada perubahan yang dapat kita lakukan pada kode kita, atau perbaikan waktu kompilasi yang dapat dilakukan untuk mengidentifikasi / memperbaiki kesalahan lunak dan kerusakan memori yang disebabkan oleh gangguan peristiwa tunggal ? Apakah ada pengembang lain yang berhasil mengurangi efek berbahaya kesalahan lunak pada aplikasi yang sudah berjalan lama?
Jawaban:
Bekerja sekitar 4-5 tahun dengan pengembangan perangkat lunak / firmware dan pengujian lingkungan satelit mini *, saya ingin berbagi pengalaman saya di sini.
* ( satelit miniatur jauh lebih rentan terhadap gangguan peristiwa tunggal daripada satelit yang lebih besar karena ukurannya yang relatif kecil dan terbatas untuk komponen elektroniknya )
Sekarang, situasi ini biasanya ditangani di tingkat perangkat keras dan perangkat lunak. Di sini, sesuai permintaan Anda, saya akan membagikan apa yang dapat kami lakukan di tingkat perangkat lunak.
... tujuan pemulihan ... . Memberikan kemampuan untuk memperbarui / mengkompilasi ulang / merombak perangkat lunak / firmware Anda di lingkungan nyata. Ini adalah fitur yang hampir harus dimiliki untuk semua perangkat lunak / firmware di lingkungan yang sangat terionisasi. Tanpa ini, Anda bisa memiliki perangkat lunak / perangkat keras yang berlebihan sebanyak yang Anda inginkan tetapi pada satu titik, mereka semua akan meledak. Jadi, siapkan fitur ini!
... versi minimum yang berfungsi ... Miliki responsif, banyak salinan, versi minimum perangkat lunak / firmware dalam kode Anda. Ini seperti Safe mode di Windows. Alih-alih hanya memiliki satu versi perangkat lunak Anda yang berfungsi penuh, miliki lebih dari satu salinan versi minimum perangkat lunak / firmware Anda. Salinan minimum biasanya memiliki ukuran yang jauh lebih sedikit daripada salinan lengkap dan hampir selalu hanya memiliki dua atau tiga fitur berikut:
... salin ... di suatu tempat ... Memiliki perangkat lunak / firmware yang berlebihan di suatu tempat.
Anda dapat, dengan atau tanpa perangkat keras yang berlebihan, mencoba untuk memiliki perangkat lunak / firmware yang berlebihan di ARM UC Anda. Ini biasanya dilakukan dengan memiliki dua atau lebih perangkat lunak / firmware yang identik di alamat terpisah yang saling mengirimkan detak jantung - tetapi hanya satu yang akan aktif pada satu waktu. Jika satu atau lebih perangkat lunak / firmware diketahui tidak responsif, alihkan ke perangkat lunak / firmware lain. Manfaat menggunakan pendekatan ini adalah kita dapat memiliki penggantian fungsional segera setelah kesalahan terjadi - tanpa kontak dengan sistem / pihak eksternal apa pun yang bertanggung jawab untuk mendeteksi dan memperbaiki kesalahan (dalam kasus satelit, biasanya Mission Control Center ( MCC)).
Sebenarnya, tanpa perangkat keras yang berlebihan, kelemahan melakukan ini adalah Anda sebenarnya tidak bisa menghilangkan semua titik kegagalan. Paling tidak, Anda masih memiliki satu titik kegagalan, yaitu sakelar itu sendiri (atau sering kali merupakan awal dari kode). Namun demikian, untuk perangkat yang dibatasi oleh ukuran di lingkungan yang sangat terionisasi (seperti satelit pico / femto), pengurangan titik kegagalan tunggal menjadi satu titik tanpa perangkat keras tambahan masih layak dipertimbangkan. Suatu hari nanti, potongan kode untuk peralihan tentu akan jauh lebih sedikit daripada kode untuk seluruh program - secara signifikan mengurangi risiko mendapatkan Single Event di dalamnya.
Tetapi jika Anda tidak melakukan ini, Anda harus memiliki setidaknya satu salinan di sistem eksternal Anda yang dapat bersentuhan dengan perangkat dan memperbarui perangkat lunak / firmware (dalam kasus satelit, itu lagi-lagi pusat kendali misi).
... situasi salah yang terdeteksi .. Kesalahan harus dapat dideteksi , biasanya oleh sirkuit koreksi / deteksi kesalahan perangkat keras atau oleh sepotong kecil kode untuk koreksi / deteksi kesalahan. Yang terbaik adalah meletakkan kode tersebut kecil, banyak, dan independen dari perangkat lunak / firmware utama. Tugas utamanya hanya untuk memeriksa / mengoreksi. Jika sirkuit perangkat keras / firmware diandalkan(seperti radiasi lebih keras dari yang lainnya - atau memiliki beberapa sirkuit / logika), maka Anda dapat mempertimbangkan untuk melakukan koreksi kesalahan dengan itu. Tetapi jika tidak, lebih baik menjadikannya sebagai deteksi kesalahan. Koreksi dapat dilakukan dengan sistem / perangkat eksternal. Untuk koreksi kesalahan, Anda dapat mempertimbangkan untuk menggunakan algoritma koreksi kesalahan dasar seperti Hamming / Golay23, karena mereka dapat diimplementasikan lebih mudah baik di sirkuit / perangkat lunak. Tetapi pada akhirnya tergantung pada kemampuan tim Anda. Untuk deteksi kesalahan, biasanya CRC digunakan.
... perangkat keras yang mendukung pemulihan Sekarang, sampai pada aspek yang paling sulit tentang masalah ini. Pada akhirnya, pemulihan membutuhkan perangkat keras yang bertanggung jawab atas pemulihan agar setidaknya berfungsi. Jika perangkat keras rusak secara permanen (biasanya terjadi setelah dosis Total pengion mencapai tingkat tertentu), maka (sayangnya) tidak ada cara bagi perangkat lunak untuk membantu dalam pemulihan. Dengan demikian, perangkat keras adalah masalah yang paling penting bagi perangkat yang terpapar pada tingkat radiasi tinggi (seperti satelit).
Selain saran untuk mengantisipasi kesalahan firmware di atas karena gangguan peristiwa tunggal, saya juga ingin menyarankan Anda untuk:
Deteksi kesalahan dan / atau algoritma koreksi kesalahan dalam protokol komunikasi antar subsistem. Ini adalah hal lain yang hampir harus dimiliki untuk menghindari sinyal tidak lengkap / salah yang diterima dari sistem lain
Saring dalam bacaan ADC Anda. Jangan tidak menggunakan ADC membaca langsung. Saring dengan filter median, filter berarti, atau filter lainnya - jangan pernah mempercayai nilai bacaan tunggal. Sampel lebih banyak, tidak kurang - cukup.
sumber
NASA memiliki makalah tentang perangkat lunak yang dikeraskan dengan radiasi . Ini menjelaskan tiga tugas utama:
Perhatikan bahwa kecepatan pemindaian memori harus cukup sering sehingga kesalahan multi-bit jarang terjadi, karena sebagian besar memori ECC dapat pulih dari kesalahan single-bit, bukan kesalahan multi-bit.
Pemulihan kesalahan yang kuat mencakup transfer aliran kontrol (biasanya memulai kembali proses pada titik sebelum kesalahan), rilis sumber daya, dan pemulihan data.
Rekomendasi utama mereka untuk pemulihan data adalah untuk menghindari kebutuhan akan hal itu, dengan meminta data antara diperlakukan sebagai sementara, sehingga memulai kembali sebelum kesalahan juga mengembalikan data ke keadaan yang dapat diandalkan. Ini terdengar mirip dengan konsep "transaksi" dalam database.
Mereka membahas teknik yang sangat cocok untuk bahasa berorientasi objek seperti C ++. Sebagai contoh
Dan, kebetulan saja, NASA telah menggunakan C ++ untuk proyek-proyek besar seperti Mars Rover .
Mereka menghindari fitur C ++ tertentu yang dapat membuat masalah:
new
dandelete
)new
untuk menghindari kemungkinan korupsi tumpukan sistem).sumber
Berikut ini beberapa pemikiran dan ide:
Gunakan ROM lebih kreatif.
Simpan apa pun yang Anda bisa di ROM. Alih-alih menghitung, simpan tabel pencarian di ROM. (Pastikan kompiler Anda mengeluarkan tabel pencarian Anda ke bagian hanya baca! Cetak alamat memori saat runtime untuk memeriksa!) Simpan tabel vektor interupsi Anda di ROM. Tentu saja, jalankan beberapa tes untuk melihat seberapa andal ROM Anda dibandingkan dengan RAM Anda.
Gunakan RAM terbaik Anda untuk tumpukan.
SEU dalam stack mungkin merupakan sumber crash yang paling mungkin, karena di situlah hal-hal seperti variabel indeks, variabel status, alamat pengirim, dan pointer dari berbagai jenis biasanya hidup.
Terapkan timer-tick dan rutinitas timer watchdog.
Anda dapat menjalankan rutinitas "pemeriksaan kewarasan" setiap tanda centang waktu, serta rutin pengawas untuk menangani penguncian sistem. Kode utama Anda juga dapat secara bertahap menambah penghitung untuk menunjukkan kemajuan, dan rutinitas pemeriksaan kewarasan dapat memastikan ini telah terjadi.
Menerapkan kode koreksi kesalahan dalam perangkat lunak.
Anda dapat menambahkan redundansi ke data Anda untuk dapat mendeteksi dan / atau memperbaiki kesalahan. Ini akan menambah waktu pemrosesan, berpotensi membuat prosesor terkena radiasi untuk waktu yang lebih lama, sehingga meningkatkan kemungkinan kesalahan, jadi Anda harus mempertimbangkan pertukarannya.
Ingat cache.
Periksa ukuran cache CPU Anda. Data yang telah Anda akses atau modifikasi baru-baru ini mungkin akan berada dalam cache. Saya percaya Anda dapat menonaktifkan setidaknya beberapa cache (dengan biaya kinerja besar); Anda harus mencoba ini untuk melihat seberapa rentan cache terhadap SEU. Jika cache lebih sulit daripada RAM maka Anda dapat secara teratur membaca dan menulis ulang data penting untuk memastikannya tetap dalam cache dan membawa RAM kembali ke jalur.
Gunakan penangan kesalahan halaman dengan cerdik.
Jika Anda menandai halaman memori sebagai tidak ada, CPU akan mengeluarkan kesalahan halaman ketika Anda mencoba mengaksesnya. Anda dapat membuat penangan kesalahan halaman yang melakukan beberapa pengecekan sebelum melayani permintaan baca. (Sistem operasi PC menggunakan ini untuk memuat halaman secara transparan yang telah ditukar dengan disk.)
Gunakan bahasa rakitan untuk hal-hal penting (yang bisa menjadi segalanya).
Dengan bahasa assembly, Anda tahu apa yang ada di register dan apa yang ada di RAM; kamu tahu tabel RAM khusus apa yang digunakan CPU, dan Anda dapat mendesain berbagai hal secara tidak langsung agar risiko Anda tetap rendah.
Menggunakan
objdump
untuk benar-benar melihat bahasa assembly yang dihasilkan, dan cari tahu berapa banyak kode yang digunakan setiap rutinitas Anda.Jika Anda menggunakan OS besar seperti Linux maka Anda meminta masalah; ada begitu banyak kerumitan dan banyak hal yang salah.
Ingat itu adalah permainan probabilitas.
Seorang komentator berkata
Meskipun ini benar, kemungkinan kesalahan dalam (katakanlah) 100 byte kode dan data yang diperlukan untuk pemeriksaan rutin agar berfungsi dengan benar jauh lebih kecil daripada kemungkinan kesalahan di tempat lain. Jika ROM Anda cukup andal dan hampir semua kode / data sebenarnya dalam ROM maka peluang Anda bahkan lebih baik.
Gunakan perangkat keras yang berlebihan.
Gunakan 2 atau lebih pengaturan perangkat keras yang identik dengan kode yang sama. Jika hasilnya berbeda, reset harus dipicu. Dengan 3 perangkat atau lebih, Anda dapat menggunakan sistem "memilih" untuk mencoba mengidentifikasi mana yang telah dikompromikan.
sumber
Anda juga mungkin tertarik pada literatur yang kaya tentang masalah toleransi kesalahan algoritmik. Ini termasuk tugas lama: Tulis jenis yang mengurutkan inputnya dengan benar ketika jumlah perbandingan yang konstan akan gagal (atau, versi yang sedikit lebih jahat, ketika jumlah asimtotik skala perbandingan yang gagal seperti
log(n)
untukn
perbandingan).Tempat untuk mulai membaca adalah makalah Huang dan Abraham 1984 " Toleransi Kesalahan Berbasis Algoritma untuk Operasi Matriks ". Gagasan mereka samar-samar mirip dengan perhitungan terenkripsi homomorfik (tetapi tidak benar-benar sama, karena mereka berusaha deteksi / koreksi kesalahan di tingkat operasi).
Keturunan yang lebih baru dari makalah itu adalah Bosilca, Delmas, Dongarra, dan Langou " Toleransi kesalahan berbasis Algoritma yang diterapkan pada komputasi kinerja tinggi ".
sumber
Menulis kode untuk lingkungan radioaktif sebenarnya tidak berbeda dengan menulis kode untuk aplikasi penting.
Selain apa yang telah disebutkan, berikut adalah beberapa tips lain:
PENTING: Anda harus memastikan integritas register MCU internal. Semua register kontrol & status periferal perangkat keras yang dapat ditulisi mungkin terletak di memori RAM, dan karenanya rentan.
Untuk melindungi diri Anda dari kerusakan register, sebaiknya pilih mikrokontroler dengan fitur register "tulis-sekali" bawaan. Selain itu, Anda perlu menyimpan nilai default semua register perangkat keras di NVM dan menyalin nilai-nilai itu ke register Anda secara berkala. Anda dapat memastikan integritas variabel penting dengan cara yang sama.
Catatan: selalu gunakan pemrograman defensif. Berarti Anda harus mengatur semua register di MCU dan bukan hanya yang digunakan oleh aplikasi. Anda tidak ingin beberapa perangkat keras acak tiba-tiba terbangun.
Ada semua jenis metode untuk memeriksa kesalahan dalam RAM atau NVM: checksum, "pola berjalan", perangkat lunak ECC dll. Solusi terbaik saat ini adalah tidak menggunakan semua ini, tetapi menggunakan MCU dengan ECC dan cek serupa. Karena melakukan hal ini dalam perangkat lunak adalah hal yang kompleks, dan karena itu memeriksa kesalahan itu sendiri dapat menimbulkan bug dan masalah yang tidak terduga.
Memahami dan merangkul konsep pemrograman defensif. Ini berarti bahwa program Anda perlu menangani semua kasus yang mungkin, bahkan yang tidak dapat terjadi secara teori. Contohnya .
Firmware kritis-kualitas tinggi mendeteksi kesalahan sebanyak mungkin, dan kemudian mengabaikannya dengan cara yang aman.
PENTING: Jangan menerapkan ketergantungan nilai default variabel durasi penyimpanan statis. Artinya, jangan percayai konten default dari
.data
atau.bss
. Mungkin ada sejumlah waktu antara titik inisialisasi ke titik di mana variabel sebenarnya digunakan, mungkin ada banyak waktu untuk RAM rusak. Sebagai gantinya, tuliskan program sehingga semua variabel seperti itu diatur dari NVM di run-time, tepat sebelum waktu ketika variabel seperti itu digunakan untuk pertama kalinya.Dalam prakteknya ini berarti bahwa jika suatu variabel dideklarasikan pada ruang lingkup file atau sebagai
static
, Anda tidak boleh menggunakannya=
untuk menginisialisasi (atau Anda bisa, tetapi tidak ada gunanya, karena Anda tidak dapat mengandalkan nilai bagaimanapun). Selalu atur di run-time, sesaat sebelum digunakan. Jika mungkin untuk memperbarui variabel seperti itu berulang kali dari NVM, maka lakukanlah.Demikian pula dalam C ++, jangan mengandalkan konstruktor untuk variabel durasi penyimpanan statis. Mintalah konstruktor memanggil rutin "set-up" publik, yang juga dapat Anda hubungi nanti dalam waktu berjalan, langsung dari aplikasi pemanggil.
Jika memungkinkan, hapus kode start-up "copy-down" yang menginisialisasi
.data
dan.bss
(dan memanggil konstruktor C ++) seluruhnya, sehingga Anda mendapatkan kesalahan linker jika Anda menulis kode dengan mengandalkannya. Banyak kompiler memiliki opsi untuk melewati ini, biasanya disebut "minimal / start-up cepat" atau serupa.Ini berarti bahwa setiap pustaka eksternal harus diperiksa sehingga tidak mengandung ketergantungan seperti itu.
Terapkan dan tentukan status aman untuk program, ke tempat Anda akan kembali jika terjadi kesalahan kritis.
sumber
TRUE
menyamakannya untuk0xffffffff
kemudian digunakanPOPCNT
dengan ambang batas.%01010101010101010101010101010101
, XOR lalu POPCNT?.text
bagian Anda , mengubah kode op atau sejenisnya.Dimungkinkan untuk menggunakan C untuk menulis program yang berperilaku kuat di lingkungan seperti itu, tetapi hanya jika sebagian besar bentuk pengoptimalan kompiler dinonaktifkan. Mengoptimalkan kompiler dirancang untuk menggantikan banyak pola pengkodean yang tampaknya berlebihan dengan yang "lebih efisien", dan mungkin tidak memiliki petunjuk bahwa alasan programmer menguji
x==42
ketika kompiler tahu tidak ada cara yangx
mungkin bisa menahan hal lain adalah karena programmer ingin mencegah pelaksanaan kode tertentu denganx
memegang beberapa nilai lain - bahkan dalam kasus-kasus di mana satu-satunya cara itu bisa memegang nilai itu adalah jika sistem menerima semacam kesalahan listrik.Mendeklarasikan variabel sebagai
volatile
sering membantu, tetapi mungkin bukan obat mujarab. Yang paling penting, perhatikan bahwa pengkodean aman sering mengharuskan operasi berbahaya memiliki kunci perangkat keras yang memerlukan beberapa langkah untuk mengaktifkan, dan kode itu ditulis menggunakan pola:Jika kompiler menerjemahkan kode dengan cara yang relatif literal, dan jika semua pemeriksaan untuk status sistem diulang setelah
prepare_for_activation()
, sistem mungkin kuat terhadap hampir semua peristiwa kesalahan tunggal yang masuk akal, bahkan yang akan sewenang-wenang merusak program counter dan stack. Jika kesalahan terjadi tepat setelah panggilan keprepare_for_activation()
, itu akan menyiratkan bahwa aktivasi akan sesuai (karena tidak ada alasan lainprepare_for_activation()
akan dipanggil sebelum kesalahan). Jika kesalahan menyebabkan kode untuk mencapai secaraprepare_for_activation()
tidak tepat, tetapi tidak ada peristiwa kesalahan berikutnya, tidak akan ada jalan bagi kode untuk kemudian mencapai setelah konteks yang disebut kembali, tetapi panggilan untuk akan terjadi antara panggilan ke dantrigger_activation()
tanpa melewati pemeriksaan validasi atau memanggil cancel_preparations terlebih dahulu [jika stack glitches, eksekusi mungkin dilanjutkan ke suatu tempat sebelumtrigger_activation()
prepare_for_activation()
cancel_preparations()
prepare_for_activation()
trigger_activation()
, dengan demikian menjadikan panggilan terakhir tidak berbahaya.Kode seperti itu mungkin aman di C tradisional, tetapi tidak dengan kompiler C modern. Kompiler seperti itu bisa sangat berbahaya dalam lingkungan semacam itu karena agresif mereka berusaha untuk hanya memasukkan kode yang akan relevan dalam situasi yang dapat terjadi melalui beberapa mekanisme yang terdefinisi dengan baik dan yang konsekuensi yang dihasilkannya juga akan didefinisikan dengan baik. Kode yang tujuannya untuk mendeteksi dan membersihkan setelah kegagalan mungkin, dalam beberapa kasus, akhirnya memperburuk keadaan. Jika kompiler menentukan bahwa upaya pemulihan dalam beberapa kasus akan memicu perilaku tidak terdefinisi, dapat menyimpulkan bahwa kondisi yang memerlukan pemulihan seperti itu dalam kasus seperti itu tidak mungkin terjadi, sehingga menghilangkan kode yang akan memeriksa mereka.
sumber
-O0
atau saklar yang setara? GCC akan melakukan banyak hal aneh jika Anda mengizinkannya , tetapi jika Anda memintanya untuk tidak melakukannya, itu pada umumnya juga bisa sangat harfiah.-O2
.-O0
adalah ide yang buruk adalah karena ia mengeluarkan instruksi yang jauh lebih tidak berguna. Contoh: panggilan non-inline berisi instruksi untuk menyimpan register, melakukan panggilan, mengembalikan register. Semua ini bisa gagal. Instruksi yang tidak ada di sana tidak boleh gagal.-O0
adalah ide yang buruk: ia cenderung untuk menyimpan variabel dalam memori daripada dalam register. Sekarang tidak yakin bahwa memori lebih rentan terhadap SEU, tetapi data dalam penerbangan lebih rentan daripada data saat istirahat. Pergerakan data yang tidak berguna harus dihindari, dan-O2
membantu di sana.v1=v2+0xCAFEBABE
Dan semua pembaruan ke dua variabel dilakukan ...Ini adalah subjek yang sangat luas. Pada dasarnya, Anda tidak dapat benar-benar pulih dari kerusakan memori, tetapi setidaknya Anda dapat mencoba untuk segera gagal . Berikut beberapa teknik yang bisa Anda gunakan:
data konstan checksum . Jika Anda memiliki data konfigurasi yang tetap konstan untuk waktu yang lama (termasuk register perangkat keras yang telah Anda konfigurasi), hitung checksumnya pada inisialisasi dan verifikasi secara berkala. Ketika Anda melihat ketidakcocokan, saatnya untuk menginisialisasi ulang atau mengatur ulang.
variabel toko dengan redundansi . Jika Anda memiliki variabel penting
x
, menulis nilainya dix1
,x2
danx3
dan membacanya sebagai(x1 == x2) ? x2 : x3
.melaksanakan pemantauan aliran program . XOR bendera global dengan nilai unik dalam fungsi / cabang penting yang dipanggil dari loop utama. Menjalankan program di lingkungan yang bebas radiasi dengan cakupan uji hampir 100% akan memberi Anda daftar nilai bendera yang dapat diterima pada akhir siklus. Setel ulang jika Anda melihat penyimpangan.
pantau stack pointer . Di awal loop utama, bandingkan stack pointer dengan nilai yang diharapkan. Atur ulang pada penyimpangan.
sumber
Yang bisa membantu Anda adalah anjing penjaga . Watchdogs digunakan secara luas dalam komputasi industri pada 1980-an. Kegagalan perangkat keras jauh lebih umum saat itu - jawaban lain juga merujuk pada periode itu.
Watchdog adalah fitur perangkat keras / perangkat lunak gabungan. Perangkat keras adalah penghitung sederhana yang menghitung mundur dari angka (katakan 1023) ke nol. TTL atau logika lain dapat digunakan.
Perangkat lunak telah dirancang sedemikian rupa sehingga satu rutin memonitor operasi yang benar dari semua sistem penting. Jika rutin ini selesai dengan benar = menemukan komputer berfungsi dengan baik, ini akan mengatur penghitung kembali ke 1023.
Keseluruhan desain dibuat sedemikian rupa sehingga dalam keadaan normal, perangkat lunak mencegah bahwa penghitung perangkat keras akan mencapai nol. Jika penghitung mencapai nol, perangkat keras penghitung melakukan tugas satu-satunya dan mengatur ulang seluruh sistem. Dari perspektif penghitung, nol sama dengan 1024 dan penghitung terus menghitung mundur lagi.
Watchdog ini memastikan bahwa komputer yang terpasang dihidupkan ulang dalam banyak, banyak kasus kegagalan. Saya harus mengakui bahwa saya tidak terbiasa dengan perangkat keras yang dapat melakukan fungsi seperti itu di komputer saat ini. Antarmuka ke perangkat keras eksternal sekarang jauh lebih kompleks daripada sebelumnya.
Kerugian inheren dari pengawas adalah bahwa sistem tidak tersedia dari saat gagal sampai pengawas pengawas mencapai nol + waktu reboot. Sementara waktu itu umumnya jauh lebih pendek daripada intervensi eksternal atau manusia, peralatan yang didukung harus dapat melanjutkan tanpa kontrol komputer untuk jangka waktu itu.
sumber
Jawaban ini mengasumsikan Anda khawatir memiliki sistem yang berfungsi dengan benar, di atas dan di atas memiliki sistem yang biaya minimum atau cepat; kebanyakan orang yang bermain dengan radioaktif menghargai kebenaran / keamanan melebihi kecepatan / biaya
Beberapa orang telah menyarankan perubahan perangkat keras yang dapat Anda lakukan (baik - ada banyak hal baik di sini sebagai jawaban dan saya tidak bermaksud mengulang semuanya), dan yang lain menyarankan redundansi (hebat pada prinsipnya), tetapi saya tidak berpikir siapa pun telah menyarankan bagaimana redundansi itu dapat bekerja dalam praktik. Bagaimana Anda gagal? Bagaimana Anda tahu ketika ada sesuatu yang 'salah'? Banyak teknologi bekerja atas dasar semuanya akan bekerja, dan kegagalan adalah hal yang sulit untuk dihadapi. Namun, beberapa teknologi komputasi terdistribusi dirancang untuk skala yang diharapkan kegagalan (setelah semua dengan skala yang cukup, kegagalan satu simpul dari banyak node tidak dapat dihindari dengan MTBF untuk satu node); Anda dapat memanfaatkan ini untuk lingkungan Anda.
Berikut ini beberapa ide:
Pastikan seluruh perangkat keras Anda direplikasi
n
kali (di manan
lebih besar dari 2, dan lebih aneh), dan bahwa setiap elemen perangkat keras dapat berkomunikasi dengan masing-masing elemen perangkat keras lainnya. Ethernet adalah salah satu cara yang jelas untuk melakukan itu, tetapi ada banyak rute lain yang jauh lebih sederhana yang akan memberikan perlindungan yang lebih baik (misalnya BISA). Minimalkan komponen umum (bahkan catu daya). Ini dapat berarti pengambilan sampel input ADC di banyak tempat misalnya.Pastikan status aplikasi Anda berada di satu tempat, misalnya dalam mesin kondisi terbatas. Ini bisa sepenuhnya berbasis RAM, meskipun tidak menghalangi penyimpanan yang stabil. Dengan demikian akan disimpan di beberapa tempat.
Adopsi protokol kuorum untuk perubahan status. Lihat RAFT misalnya. Saat Anda bekerja di C ++, ada perpustakaan terkenal untuk ini. Perubahan pada FSM hanya akan dilakukan ketika mayoritas node setuju. Gunakan pustaka yang dikenal baik untuk tumpukan protokol dan protokol kuorum daripada menggulirnya sendiri, atau semua pekerjaan baik Anda tentang redundansi akan sia-sia ketika protokol kuorum ditutup.
Pastikan Anda melakukan checksum (mis. CRC / SHA) FSM Anda, dan simpan CRC / SHA di FSM itu sendiri (juga mentransmisikan dalam pesan, dan memeriksa sendiri pesan-pesan itu). Dapatkan node untuk memeriksa FSM mereka secara teratur terhadap checksum ini, checksum pesan masuk, dan periksa checksum mereka cocok dengan checksum kuorum.
Bangun sebanyak mungkin pemeriksaan internal lain ke dalam sistem Anda, buat simpul yang mendeteksi kegagalannya sendiri reboot (ini lebih baik daripada menjalankan separuh kerja asalkan Anda punya cukup simpul). Cobalah untuk membiarkan mereka dengan bersih menghapus diri mereka sendiri dari kuorum selama me-reboot jika-kalau mereka tidak muncul lagi. Pada saat reboot minta mereka memeriksa gambar perangkat lunak (dan apa pun yang mereka muat) dan lakukan tes RAM penuh sebelum memperkenalkan kembali diri mereka ke kuorum.
Gunakan perangkat keras untuk mendukung Anda, tetapi lakukan dengan hati-hati. Anda bisa mendapatkan ECC RAM, misalnya, dan secara teratur membaca / menulis melalui itu untuk memperbaiki kesalahan ECC (dan panik jika kesalahan tidak dapat diperbaiki). Namun (dari memori) RAM statis jauh lebih toleran terhadap radiasi pengion daripada DRAM, jadi mungkin lebih baik menggunakan DRAM statis sebagai gantinya. Lihat poin pertama di bawah 'hal-hal yang tidak akan saya lakukan' juga.
Katakanlah Anda memiliki kemungkinan kegagalan 1% dari setiap node yang diberikan dalam satu hari, dan mari kita berpura-pura Anda dapat membuat kegagalan sepenuhnya independen. Dengan 5 node, Anda akan membutuhkan tiga kegagalan dalam satu hari, yang merupakan peluang 0,00001%. Dengan lebih banyak, yah, Anda mendapatkan idenya.
Hal-hal yang tidak akan saya lakukan:
Meremehkan nilai tidak memiliki masalah untuk memulai. Kecuali jika berat menjadi masalah, balok besar logam di sekitar perangkat Anda akan menjadi solusi yang jauh lebih murah dan lebih andal daripada yang bisa dihasilkan oleh tim programmer. Kopling optik dari input EMI adalah masalah, dll. Apa pun, usahakan saat sumber komponen Anda untuk sumber yang dinilai terbaik terhadap radiasi pengion.
Gulung algoritme Anda sendiri . Orang-orang telah melakukan hal ini sebelumnya. Gunakan pekerjaan mereka. Toleransi kesalahan dan algoritma terdistribusi sulit. Gunakan pekerjaan orang lain jika memungkinkan.
Gunakan pengaturan kompiler yang rumit dalam naif harap Anda mendeteksi lebih banyak kegagalan. Jika Anda beruntung, Anda dapat mendeteksi lebih banyak kegagalan. Kemungkinan besar, Anda akan menggunakan jalur-kode di dalam kompiler yang kurang teruji, terutama jika Anda melakukannya sendiri.
Gunakan teknik yang belum teruji di lingkungan Anda. Kebanyakan orang yang menulis perangkat lunak ketersediaan tinggi harus mensimulasikan mode kegagalan untuk memeriksa HA mereka berfungsi dengan benar, dan akibatnya kehilangan banyak mode kegagalan. Anda berada dalam posisi 'beruntung' karena sering mengalami kegagalan sesuai permintaan. Jadi uji setiap teknik, dan pastikan aplikasinya benar-benar meningkatkan MTBF dengan jumlah yang melebihi kompleksitas untuk memperkenalkannya (dengan kompleksitas muncul bug). Terutama menerapkan ini pada saran saya algoritma kuorum saran dll
sumber
Karena Anda secara khusus meminta solusi perangkat lunak, dan Anda menggunakan C ++, mengapa tidak menggunakan operator yang berlebihan untuk membuat tipe data Anda sendiri yang aman? Sebagai contoh:
Alih-alih menggunakan
uint32_t
(dandouble
,int64_t
dll), buat milik AndaSAFE_uint32_t
yang berisi banyak (minimal 3) dari uint32_t. Kelebihan semua operasi yang Anda inginkan (* + - / << >> = ==! = Dll) untuk melakukan, dan membuat operasi kelebihan beban dilakukan secara independen pada setiap nilai internal, yaitu jangan lakukan sekali dan salin hasilnya. Baik sebelum dan sesudah, periksa apakah semua nilai internal cocok. Jika nilai tidak cocok, Anda dapat memperbarui yang salah ke nilai dengan yang paling umum. Jika tidak ada nilai yang paling umum, Anda dapat dengan aman memberi tahu bahwa ada kesalahan.Dengan cara ini tidak masalah jika terjadi korupsi di ALU, register, RAM, atau di bus, Anda masih akan memiliki beberapa upaya dan peluang yang sangat bagus untuk menangkap kesalahan. Namun perlu dicatat bahwa ini hanya berfungsi untuk variabel yang dapat Anda ganti - stack pointer Anda misalnya masih akan rentan.
Sebuah cerita sampingan: Saya mengalami masalah yang sama, juga pada chip ARM lama. Ternyata itu adalah toolchain yang menggunakan versi lama GCC yang, bersama dengan chip spesifik yang kami gunakan, memicu bug dalam kasus tepi tertentu yang akan (kadang-kadang) nilai-nilai korup diteruskan ke fungsi. Pastikan perangkat Anda tidak memiliki masalah sebelum menyalahkannya pada aktivitas radio, dan ya, terkadang itu adalah bug penyusun =)
sumber
Penafian: Saya bukan profesional radioaktivitas atau bekerja untuk aplikasi semacam ini. Tapi saya bekerja pada kesalahan lunak dan redundansi untuk arsip data kritis jangka panjang, yang agak terkait (masalah yang sama, tujuan yang berbeda).
Masalah utama dengan radioaktivitas menurut saya adalah radioaktivitas dapat mengubah bit, dengan demikian radioaktivitas dapat / akan merusak memori digital . Kesalahan ini biasanya disebut kesalahan lunak , bit busuk, dll.
Pertanyaannya kemudian: bagaimana menghitung dengan andal ketika ingatan Anda tidak bisa diandalkan?
Untuk secara signifikan mengurangi tingkat kesalahan lunak (dengan mengorbankan overhead komputasi karena sebagian besar akan menjadi solusi berbasis perangkat lunak), Anda dapat:
mengandalkan skema redundansi lama yang baik , dan lebih khusus lagi kode koreksi kesalahan yang lebih efisien (tujuan yang sama, tetapi algoritma lebih pintar sehingga Anda dapat memulihkan lebih banyak bit dengan redundansi lebih sedikit). Ini kadang-kadang (salah) juga disebut checksumming. Dengan solusi semacam ini, Anda harus menyimpan keadaan penuh program Anda kapan saja dalam variabel master / kelas (atau struct?), Menghitung ECC, dan memeriksa apakah ECC sudah benar sebelum melakukan sesuatu, dan jika tidak, perbaiki ladang. Namun solusi ini tidak menjamin bahwa perangkat lunak Anda dapat bekerja (hanya bahwa itu akan berfungsi dengan benar ketika itu bisa, atau berhenti bekerja jika tidak, karena ECC dapat memberi tahu Anda jika ada sesuatu yang salah, dan dalam hal ini Anda dapat menghentikan perangkat lunak Anda sehingga Anda jangan dapatkan hasil palsu).
atau Anda dapat menggunakan struktur data algoritmik tangguh, yang menjamin, hingga batas tertentu, bahwa program Anda masih akan memberikan hasil yang benar bahkan di hadapan kesalahan lunak. Algoritme ini dapat dilihat sebagai campuran dari struktur algoritmik umum dengan skema ECC yang dicampur secara asli, tetapi ini jauh lebih tangguh daripada itu, karena skema ketahanan terikat erat dengan struktur, sehingga Anda tidak perlu menyandikan prosedur tambahan untuk memeriksa ECC, dan biasanya mereka jauh lebih cepat. Struktur ini menyediakan cara untuk memastikan bahwa program Anda akan bekerja dalam kondisi apa pun, hingga batas teoritis kesalahan lunak. Anda juga dapat mencampur struktur tangguh ini dengan skema redundansi / ECC untuk keamanan tambahan (atau menyandikan struktur data terpenting Anda sebagai tangguh, dan sisanya, data yang dapat dibuang yang dapat Anda hitung ulang dari struktur data utama,
Jika Anda tertarik pada struktur data yang tangguh (yang merupakan bidang baru dalam bidang algoritme dan redundansi) yang baru namun menarik, saya sarankan Anda membaca dokumen berikut:
Pengenalan struktur data algoritma tangguh oleh Giuseppe F.Italiano, Universita di Roma "Tor Vergata"
Christiano, P., Demaine, ED, & Kishore, S. (2011). Struktur data toleran kesalahan lossless dengan overhead tambahan. Dalam Algoritma dan Struktur Data (hlm. 243-254). Springer Berlin Heidelberg.
Ferraro-Petrillo, U., Grandoni, F., & Italiano, GF (2013). Struktur data tahan terhadap kesalahan memori: studi eksperimental kamus. Jurnal Algoritma Eksperimental (JEA), 18, 1-6.
Italiano, GF (2010). Algoritma tangguh dan struktur data. Dalam Algoritma dan Kompleksitas (hal. 13-24). Springer Berlin Heidelberg.
Jika Anda tertarik untuk mengetahui lebih banyak tentang bidang struktur data yang tangguh, Anda dapat memeriksa karya-karya Giuseppe F. Italiano (dan mencari jalan melalui referensi) dan model Faulty-RAM (diperkenalkan di Finocchi et al. 2005; Finocchi dan Italiano 2008).
/ EDIT: Saya menggambarkan pencegahan / pemulihan dari kesalahan lunak terutama untuk memori RAM dan penyimpanan data, tapi saya tidak berbicara tentang kesalahan komputasi (CPU) . Jawaban lain sudah menunjuk menggunakan transaksi atom seperti dalam database, jadi saya akan mengusulkan skema lain yang lebih sederhana: redundansi dan suara terbanyak .
Idenya adalah Anda hanya melakukan x kali perhitungan yang sama untuk setiap perhitungan yang perlu Anda lakukan, dan menyimpan hasilnya dalam x variabel yang berbeda (dengan x> = 3). Anda kemudian dapat membandingkan variabel x Anda :
Skema redundansi ini sangat cepat dibandingkan dengan ECC (praktisnya O (1)) dan ini memberi Anda sinyal yang jelas ketika Anda perlu failafe . Suara mayoritas juga (hampir) dijamin tidak akan pernah menghasilkan output yang rusak dan juga untuk pulih dari kesalahan perhitungan kecil , karena probabilitas bahwa x perhitungan memberikan output yang sama sangat kecil (karena ada sejumlah besar kemungkinan output, hampir tidak mungkin untuk secara acak mendapatkan 3 kali sama, bahkan peluang lebih kecil jika x> 3).
Jadi dengan suara terbanyak Anda aman dari output yang rusak, dan dengan redundansi x == 3, Anda dapat memulihkan 1 kesalahan (dengan x == 4 itu akan menjadi 2 kesalahan yang dapat dipulihkan, dll. - persamaan yang tepat adalah di
nb_error_recoverable == (x-2)
mana x adalah angka pengulangan perhitungan karena Anda memerlukan setidaknya 2 perhitungan yang menyetujui untuk memulihkan menggunakan suara terbanyak).Kekurangannya adalah Anda perlu menghitung x kali alih-alih sekali, sehingga Anda memiliki biaya perhitungan tambahan, tetapi kompleksitas liniernya sehingga tanpa gejala Anda tidak kehilangan banyak manfaat yang Anda peroleh. Cara cepat untuk melakukan voting mayoritas adalah dengan menghitung mode pada array, tetapi Anda juga dapat menggunakan filter median.
Juga, jika Anda ingin memastikan bahwa perhitungan dilakukan dengan benar, jika Anda dapat membuat perangkat keras Anda sendiri, Anda dapat membuat perangkat Anda dengan x CPU, dan menghubungkan sistem sehingga perhitungan secara otomatis digandakan di seluruh x CPU dengan suara terbanyak dilakukan secara mekanis di akhir (menggunakan gerbang AND / OR misalnya). Ini sering diterapkan di pesawat terbang dan perangkat misi-kritis (lihat redundansi modular tiga ). Dengan cara ini, Anda tidak akan memiliki overhead komputasi (karena perhitungan tambahan akan dilakukan secara paralel), dan Anda memiliki lapisan perlindungan lain dari kesalahan lunak (karena duplikasi perhitungan dan suara terbanyak akan dikelola langsung oleh perangkat keras dan bukan oleh perangkat lunak - yang dapat lebih mudah rusak karena suatu program hanya disimpan dalam memori ...).
sumber
Satu hal yang sepertinya tidak ada yang disebutkan. Anda mengatakan Anda berkembang di GCC dan kompilasi silang ke ARM. Bagaimana Anda tahu bahwa Anda tidak memiliki kode yang membuat asumsi tentang RAM gratis, ukuran integer, ukuran pointer, berapa lama untuk melakukan operasi tertentu, berapa lama sistem akan berjalan terus menerus, atau berbagai hal seperti itu? Ini adalah masalah yang sangat umum.
Jawabannya biasanya pengujian unit otomatis. Tulis test harness yang menggunakan kode pada sistem pengembangan, kemudian jalankan test harness yang sama pada sistem target. Cari perbedaan!
Periksa juga errata pada perangkat yang disematkan. Anda mungkin menemukan sesuatu tentang "jangan lakukan ini karena akan macet, jadi aktifkan opsi kompiler dan kompiler akan mengatasinya".
Singkatnya, sumber crash Anda kemungkinan besar adalah bug dalam kode Anda. Sampai Anda benar-benar yakin ini bukan masalahnya, jangan khawatir tentang mode kegagalan yang lebih esoteris.
sumber
Anda ingin 3+ mesin budak dengan master di luar lingkungan radiasi. Semua I / O melewati master yang berisi mekanisme voting dan / atau coba lagi. Para budak harus memiliki masing-masing pengawas perangkat keras dan panggilan untuk menabrak mereka harus dikelilingi oleh CRC atau sejenisnya untuk mengurangi kemungkinan menabrak secara tidak sengaja. Bumping harus dikontrol oleh master, jadi koneksi yang hilang dengan master sama dengan reboot dalam beberapa detik.
Salah satu keuntungan dari solusi ini adalah Anda dapat menggunakan API yang sama untuk master seperti pada slave, sehingga redundansi menjadi fitur transparan.
Sunting: Dari komentar saya merasa perlu mengklarifikasi "ide CRC." Kemungkinan slave menabrak itu sendiri pengawas hampir nol jika Anda mengelilingi bump dengan CRC atau mencerna cek pada data acak dari master. Data acak itu hanya dikirim dari master ketika budak di bawah pengawasan selaras dengan yang lain. Data acak dan CRC / digest segera dibersihkan setelah setiap benjolan. Frekuensi benjolan induk-budak harus lebih dari dua kali lipat batas waktu pengawas. Data yang dikirim dari master dihasilkan secara unik setiap kali.
sumber
Bagaimana menjalankan banyak contoh aplikasi Anda. Jika crash disebabkan oleh perubahan bit memori acak, kemungkinan beberapa instance aplikasi Anda akan berhasil dan menghasilkan hasil yang akurat. Ini mungkin cukup mudah (untuk seseorang dengan latar belakang statistik) untuk menghitung berapa banyak contoh yang Anda butuhkan diberikan peluang kegagalan kecil untuk mencapai kesalahan keseluruhan sekecil yang Anda inginkan.
sumber
Apa yang Anda tanyakan adalah topik yang cukup kompleks - tidak mudah dijawab. Jawaban lain boleh saja, tetapi hanya mencakup sebagian kecil dari semua hal yang perlu Anda lakukan.
Seperti yang terlihat di komentar , tidak mungkin untuk memperbaiki masalah perangkat keras 100%, namun mungkin dengan kemungkinan besar untuk mengurangi atau menangkapnya menggunakan berbagai teknik.
Jika saya adalah Anda, saya akan membuat perangkat lunak dengan tingkat integritas tertinggi (SIL-4). Dapatkan dokumen IEC 61513 (untuk industri nuklir) dan ikuti.
sumber
Seseorang menyebutkan menggunakan chip yang lebih lambat untuk mencegah ion membalik bit dengan mudah. Dengan cara yang sama mungkin menggunakan cpu / ram khusus yang benar-benar menggunakan banyak bit untuk menyimpan bit tunggal. Dengan demikian memberikan toleransi kesalahan perangkat keras karena akan sangat tidak mungkin bahwa semua bit akan terbalik. Jadi 1 = 1111 tetapi perlu dipukul 4 kali untuk benar-benar terbalik. (4 mungkin angka yang buruk karena jika 2 bit dibalik sudah ambigu). Jadi jika Anda menggunakan 8, Anda mendapatkan ram 8 kali lebih sedikit dan beberapa waktu akses lebih lambat tetapi representasi data yang jauh lebih andal. Anda mungkin dapat melakukan ini baik pada tingkat perangkat lunak dengan kompiler khusus (mengalokasikan x jumlah lebih banyak ruang untuk semuanya) atau implementasi bahasa (menulis pembungkus untuk struktur data yang mengalokasikan hal-hal dengan cara ini).
sumber
Mungkin akan membantu untuk mengetahui apakah artinya perangkat keras "dirancang untuk lingkungan ini". Bagaimana cara mengoreksi dan / atau menunjukkan adanya kesalahan SEU?
Di satu proyek terkait eksplorasi ruang angkasa, kami memiliki MCU khusus, yang akan memunculkan pengecualian / interupsi pada kesalahan SEU, tetapi dengan beberapa penundaan, yaitu beberapa siklus mungkin lulus / instruksi dieksekusi setelah satu insn yang menyebabkan pengecualian SEU.
Yang paling rentan adalah cache data, sehingga seorang pawang akan membatalkan jalur cache yang menyinggung dan memulai kembali program. Hanya saja, karena sifat eksepsi yang tidak tepat, urutan insn yang dikepalai oleh kenaikan gaji insn mungkin tidak dapat dimulai kembali.
Kami mengidentifikasi urutan berbahaya (tidak dapat dimulai kembali) (seperti
lw $3, 0x0($2)
, diikuti oleh insn, yang memodifikasi$2
dan tidak bergantung pada data$3
), dan saya membuat modifikasi pada GCC, sehingga urutan tersebut tidak terjadi (misalnya sebagai upaya terakhir, memisahkan dua insn dengan anop
).Hanya sesuatu yang perlu dipertimbangkan ...
sumber
Jika perangkat keras Anda gagal maka Anda dapat menggunakan penyimpanan mekanis untuk memulihkannya. Jika basis kode Anda kecil dan memiliki ruang fisik maka Anda dapat menggunakan penyimpanan data mekanis.
Akan ada permukaan material yang tidak akan terpengaruh oleh radiasi. Beberapa gigi akan ada di sana. Pembaca mekanis akan berjalan pada semua gigi dan akan fleksibel untuk bergerak ke atas dan ke bawah. Turun berarti 0 dan naik berarti 1. Dari 0 dan 1 Anda dapat menghasilkan basis kode Anda.
sumber
Gunakan penjadwal siklik . Ini memberi Anda kemampuan untuk menambah waktu perawatan rutin untuk memeriksa kebenaran data penting. Masalah yang paling sering ditemui adalah korupsi stack. Jika perangkat lunak Anda bersifat siklus, Anda dapat menginisialisasi ulang tumpukan di antara siklus. Jangan menggunakan kembali tumpukan untuk panggilan interupsi, mengatur tumpukan terpisah dari setiap panggilan interupsi penting.
Mirip dengan konsep Watchdog adalah tenggat waktu. Mulai timer perangkat keras sebelum memanggil fungsi. Jika fungsi tidak kembali sebelum batas waktu berhenti, muat ulang tumpukan dan coba lagi. Jika masih gagal setelah mencoba 3/5, Anda perlu memuat ulang dari ROM.
Pisahkan perangkat lunak Anda menjadi bagian-bagian dan isolasi bagian-bagian ini untuk menggunakan area memori yang terpisah dan waktu eksekusi (Terutama di lingkungan kontrol). Contoh: akuisisi sinyal, pengambilan data sebelumnya, algoritma utama dan implementasi / transmisi hasil. Ini berarti kegagalan di satu bagian tidak akan menyebabkan kegagalan melalui sisa program. Jadi sementara kami memperbaiki akuisisi sinyal, sisa tugas berlanjut pada data basi.
Semuanya membutuhkan CRC. Jika Anda kehabisan RAM, bahkan. Teks Anda perlu CRC. Periksa CRC secara teratur jika Anda menggunakan penjadwal siklus. Beberapa kompiler (bukan GCC) dapat menghasilkan CRC untuk setiap bagian dan beberapa prosesor telah mendedikasikan perangkat keras untuk melakukan perhitungan CRC, tapi saya rasa itu akan jatuh di luar lingkup pertanyaan Anda. Memeriksa CRC juga meminta pengontrol ECC pada memori untuk memperbaiki kesalahan bit tunggal sebelum menjadi masalah.
sumber
Pertama, rancang aplikasi Anda di sekitar kegagalan . Pastikan bahwa sebagai bagian dari operasi aliran normal, ia mengharapkan untuk mengatur ulang (tergantung pada aplikasi Anda dan jenis kegagalan baik lunak atau keras). Ini sulit untuk sempurna: operasi kritis yang memerlukan tingkat transaksionalitas tertentu mungkin perlu diperiksa dan diubah pada tingkat perakitan sehingga gangguan pada titik kunci tidak dapat menghasilkan perintah eksternal yang tidak konsisten. Gagal cepat segera setelah kerusakan memori yang tidak dapat dipulihkan atau penyimpangan aliran kontrol terdeteksi. Gagal mencatat jika memungkinkan.
Kedua, jika memungkinkan, perbaiki korupsi dan lanjutkan . Ini berarti checksumming dan memperbaiki tabel konstan (dan kode program jika Anda bisa) sering; mungkin sebelum setiap operasi besar atau pada interupsi berjangka waktu, dan menyimpan variabel dalam struktur yang mengoreksi otomatis (lagi sebelum setiap op utama atau pada interupsi berjangka waktu mengambil suara mayoritas dari 3 dan mengoreksi jika merupakan penyimpangan tunggal). Log koreksi jika memungkinkan.
Ketiga, tes gagal . Siapkan lingkungan pengujian berulang yang membalik bit dalam memori psuedo-secara acak. Ini akan memungkinkan Anda untuk meniru situasi korupsi dan membantu merancang aplikasi Anda di sekitarnya.
sumber
Diberikan komentar supercat, kecenderungan kompiler modern, dan hal-hal lain, saya akan tergoda untuk kembali ke zaman kuno dan menulis seluruh kode dalam kumpulan dan alokasi memori statis di mana-mana. Untuk keandalan seperti ini, saya pikir perakitan tidak lagi menimbulkan perbedaan besar dalam biaya.
sumber
Berikut ini sejumlah besar balasan, tetapi saya akan mencoba meringkas ide-ide saya tentang ini.
Sesuatu macet atau tidak berfungsi dengan benar bisa merupakan hasil dari kesalahan Anda sendiri - maka itu harus mudah untuk diperbaiki ketika Anda menemukan masalahnya. Tetapi ada juga kemungkinan kegagalan perangkat keras - dan itu sulit jika tidak mustahil untuk diperbaiki secara keseluruhan.
Saya akan merekomendasikan pertama untuk mencoba menangkap situasi yang bermasalah dengan masuk (tumpukan, register, panggilan fungsi) - baik dengan masuk mereka di suatu tempat ke dalam file, atau mentransmisikan mereka secara langsung ("oh tidak - saya sedang crash").
Pemulihan dari situasi kesalahan seperti itu adalah reboot (jika perangkat lunak masih hidup dan menendang) atau reset perangkat keras (misalnya pengawas hw). Lebih mudah memulai dari yang pertama.
Jika masalah terkait dengan perangkat keras - maka pencatatan harus membantu Anda mengidentifikasi di mana masalah fungsi panggilan terjadi dan itu dapat memberi Anda pengetahuan dari dalam tentang apa yang tidak berfungsi dan di mana.
Juga jika kode relatif kompleks - masuk akal untuk "membagi dan menaklukkan" - artinya Anda menghapus / menonaktifkan beberapa panggilan fungsi di mana Anda menduga ada masalah - biasanya menonaktifkan setengah kode dan mengaktifkan setengah lainnya - Anda bisa mendapatkan "tidak bekerja" / "tidak berfungsi" jenis keputusan setelah itu Anda dapat fokus ke bagian lain dari kode. (Dimana masalahnya)
Jika masalah terjadi setelah beberapa waktu - maka stack overflow dapat diduga - maka lebih baik untuk memantau register titik stack - jika mereka terus tumbuh.
Dan jika Anda berhasil sepenuhnya meminimalkan kode Anda sampai "hello world" jenis aplikasi - dan itu masih gagal secara acak - maka masalah perangkat keras diharapkan - dan perlu ada "peningkatan perangkat keras" - yang berarti menciptakan cpu / ram / ... Kombinasi keras yang akan mentolerir radiasi lebih baik.
Yang paling penting mungkin adalah bagaimana Anda mendapatkan log Anda kembali jika mesin sepenuhnya berhenti / dipasang kembali / tidak bekerja - mungkin hal pertama yang harus dilakukan bootstap - adalah kembali ke rumah jika situasi bermasalah tertutup.
Jika mungkin di lingkungan Anda juga untuk mengirim sinyal dan menerima respons - Anda dapat mencoba membangun semacam lingkungan debugging jarak jauh online, tetapi kemudian Anda harus memiliki setidaknya media komunikasi yang berfungsi dan beberapa prosesor / beberapa ram dalam kondisi kerja. Dan dengan debugging jarak jauh yang saya maksud baik pendekatan jenis GDB / gdb stub atau implementasi Anda sendiri tentang apa yang Anda perlukan untuk kembali dari aplikasi Anda (mis. Unduh file log, unduh tumpukan panggilan, unduh ram, mulai ulang)
sumber
Saya benar-benar membaca banyak jawaban hebat!
Inilah 2 sen saya: buat model statistik dari memori / kelainan register, dengan menulis perangkat lunak untuk memeriksa memori atau untuk melakukan perbandingan register yang sering. Selanjutnya, buat emulator, dengan gaya mesin virtual tempat Anda dapat bereksperimen dengan masalah tersebut. Saya kira jika Anda memvariasikan ukuran persimpangan, frekuensi jam, vendor, casing, dll akan mengamati perilaku yang berbeda.
Bahkan memori PC desktop kami memiliki tingkat kegagalan tertentu, yang bagaimanapun tidak mengganggu pekerjaan sehari-hari.
sumber