Pada artikel
sebelumnya , yang kedua berturut-turut, kami mengembangkan fungsi yang diperlukan untuk bekerja dengan string dari pustaka C. Dalam pelajaran ini, kami menerapkan output debugging penuh ke layar - log sistem kernel.
Daftar isi
- Membangun sistem (make, gcc, gas). Boot awal (multiboot). Luncurkan (qemu). Pustaka C (strcpy, memcpy, strext).
- Pustaka C (sprintf, strcpy, strcmp, strtok, va_list ...). Membangun perpustakaan dalam mode kernel dan mode aplikasi pengguna.
- Log sistem kernel. Memori video Output ke terminal (kprintf, kpanic, kassert).
- Memori dinamis, tumpukan (kmalloc, kfree).
- Organisasi memori dan penanganan interupsi (GDT, IDT, PIC, syscall). Pengecualian
- Memori virtual (direktori halaman dan tabel halaman).
- Proses Perencana Multitasking. Panggilan sistem (bunuh, keluar, ps).
- Sistem file kernel (initrd), elf, dan internalnya. Panggilan sistem (exec).
- Driver perangkat karakter. Panggilan sistem (ioctl, fopen, fread, fwrite). Pustaka C (fopen, fclose, fprintf, fscanf).
- Shell sebagai program lengkap untuk kernel.
- Mode perlindungan pengguna (ring3). Segmen Status Tugas (tss).
Log sistem kernel
Sebelum kita mulai, kita perlu memperkenalkan beberapa fungsi yang berguna untuk bekerja dengan port I / O. Port I / O untuk seorang programmer tidak berbeda dari sel-sel biasa dalam memori, kecuali bahwa ada perintah terpisah untuk mengoperasikannya. Perangkat yang beroperasi pada port-port ini terhubung ke bus memori. Ada juga ruang alamat khusus untuk mereka. Kita akan membutuhkan dua fungsi assembler untuk bekerja dengan port input / output, karena seperti yang sudah Anda ingat, saya tidak mentolerir insert assembler.
extern u_char asm_read_port(u_char port); extern void asm_write_port(u_int port, u_char data);
Demikian pula, dua perintah untuk mengendalikan prosesor yang disela mengganggu.
extern void asm_lock(); extern void asm_unlock();
Nah, untuk menghemat energi setelah kesalahan fatal, Anda memerlukan perintah berhenti prosesor.
extern void asm_hlt();
Seperti yang Anda ingat, memori video dimulai pada 0xB8000, tetapi saya sarankan menulis pesan terlebih dahulu ke buffer dalam format teks biasa. Dan kemudian salin saja buffer ini ke dalam memori video, dengan mempertimbangkan atribut warna. Untuk melakukan ini, saya mengimplementasikan beberapa utilitas untuk bekerja dengan buffer ini. Satu buffer akan untuk syslog kernel, dan sisanya untuk terminal virtual. Menggulir layar juga akan dilakukan pada buffer. Dan hanya fungsi video_flush akan menyalin buffer ke memori video, memperluasnya dengan atribut.
extern void video_init(); extern void video_disable_cursor(); extern void* video_scroll(char const* video_buff, char* pos); extern char* video_clear(char const* video_buff); extern void video_flush(char const* video_buff);
Sekarang saatnya memperkenalkan fitur yang paling umum digunakan. Dua yang terakhir akan digunakan untuk men-debug kernel ketika kemalasan didebug oleh debugger. Percayalah, saya tidak pernah menggunakan debugger ketika saya menulis kernel ini.
extern void kpanic(char* message, ...); extern void kassert(const char* file, u_int line, bool expr); extern void kunreachable(const char* file, u_int line);
Sebenarnya, fungsi untuk bekerja dengan log sistem kernel. Untuk mengontrol apa yang ditampilkan di layar, saya memasukkan fungsi kmode di log sistem atau konsol pengguna. Dan untuk membaca log sistem ke buffer, fungsi klog akan diperlukan, karena proses pengguna tidak akan memiliki akses ke kernel kecuali melalui panggilan sistem.
extern void kclear(); extern void kprintf(const char* format, ...); extern void kvprintf(const char* format, va_list list); extern void kmode(bool is_early); extern void klog(char* buf, u_int n);
Saya memberikan fungsi yang paling menarik di sini:
extern void* video_scroll(char const* video_buff, char* pos) { char* ptr = (void*)video_buff; for (int i = 1; i < VIDEO_SCREEN_HEIGHT; ++i) { for (int j = 0; j < VIDEO_SCREEN_WIDTH; ++j) { ptr[(i - 1) * VIDEO_SCREEN_WIDTH + j] = ptr[i * VIDEO_SCREEN_WIDTH + j]; } } for (int j = 0; j < VIDEO_SCREEN_WIDTH; ++j) { ptr[(VIDEO_SCREEN_HEIGHT - 1) * VIDEO_SCREEN_WIDTH + j] = ' '; } pos -= VIDEO_SCREEN_WIDTH; return pos; }
extern void kvprintf(const char* format, va_list list) { char buff[VIDEO_SCREEN_WIDTH]; int len = vsprintf(buff, format, list); for (int i = 0; i < len; ++i) { if (buff[i] != '\n') { kputc(buff[i]); } else { int line_pos = (syslog_pos - syslog) % VIDEO_SCREEN_WIDTH; for (int j = 0; j < VIDEO_SCREEN_WIDTH - line_pos; ++j) { kputc(' '); } } } kflush(); }
static void kputc(char ch) { if ((size_t)syslog_pos - (size_t)syslog + 1 < VIDEO_SCREEN_SIZE) { *syslog_pos++ = ch; } else { syslog_pos = video_scroll(syslog, syslog_pos); kputc(ch); } }
Lihat tutorial rinci dalam tutorial video.
Referensi
โ
Video tutorial untuk artikel iniโ
Kode sumber (Anda membutuhkan cabang lesson3)
Referensi
- James Molloy. Gulung mainan Anda sendiri UNIX-clone OS.
- Zubkov. Assembler untuk DOS, Windows, Unix
- Kalashnikov. Assembler mudah!
- Tanenbaum. Sistem operasi. Implementasi dan pengembangan.
- Robert Love. Kernel Linux Deskripsi proses pengembangan.