Mar 31, 2013

Lập trình syscall trên nachos

Trong file hướng dẫn của thầy không thực sự cụ thể, và như vậy rất khó cho mọi người thực hành theo, vậy mình sẽ viết lại các qui trình một chút_
Một chút tìm hiểu về quá trình thực thi 1 hàm
Qui trình thực thi các interrupt sẽ được đề cập sau
  1. Xây dựng trong kernel space
    Để xác định user đang gọi cái interrupt nào. Ta cho nó 1 định danh là 1 số nào đó. Khi kernel nhận được số đó thì hiểu là user yêu cầu chuyện gì.
    Ví dụ: Nếu user đưa vô số 11 tức là yêu cầu đọc 1 số nguyên từ console.
  2. Tạo macro:
    Để đỡ phải quên trong việc lập trình, ta sẽ define số đó thành 1 macro.
    Trong syscall.h:
    define SC_ReadInt 11
    Khai báo interface cho end-user:
    Cũng trong syscall.h, ta tạo một hàm để người dùng (end-user) giao tiếp với hệ điều hành, ở đây ta khai báo hàm ReadInt();
    int ReadInt();

    Định nghĩa hàm trong file assembler.
    Khi người dùng gửi đến 1 thông điệp, ví dụ như “đọc 1 số từ console”, đến với hệ điều hành – lúc này hiểu thông điệp là 11 chẳng hạn. Để hệ điều hành nhận được số 11 đó và truyền đến chỗ xử lý các thông điệp, ta cần pass giá trị này qua. Giống như gọi 1 hàm xxx(11) vậy. Trong nachos, công việc này tức là truyền 11 vào biến $2 được qui định trước đó và gọi system call.

    Ta mở các file sau: code/test/start.ccode/test/start.s:
    .globl ReadInt
    .ent ReadInt
    ReadInt:
        addiu $2, $0, SC_ReadInt
        syscall
        j $31
        .end ReadInt
    

    Như vậy, thông điệp “đọc 1 số từ console” đã đến tai hệ điều hành. Giờ là lúc bắt tay vào xử lý công việc đó. Và vì đây là software interrupts, hay còn gọi là 1 exceptions. Nên dĩ nhiên, ta sẽ thêm mã vào file usrprog/exceptions.cc
    ///....
    switch(which)
    {
        case SystemcallException:
            switch(type)
            {
                case SC_ReadInt:
                // Đoạn mã thực thi
                break;
                // Các xử lý khác ...
            }
            / Tăng biến pc lên 1 đơn vị
            machine->Registers[PrevPCReg] = machine->Registers[PCReg];
            machine->Registers[PCReg] = machine->Registers[NextPCReg];
            machine->Registers[NextPCReg] += 4;  
    }
    ///....
    
    
  3. Một số lớp và phương thức được thêm vào trong đồ án:
    1. SynchConsole
      Được cài đặt ở thư mục threads/ giúp truy xuất giữa console và người dùng.
      Trong file threads/system.h, phần định nghĩa macro USER_PROGRAM ta include header file của SynchConsole. Đồng thời khai báo extern cho biến gSynchConsole;
      $ifdef USER_PROGRAM
      #include "synchcons.h"
      extern SynchConsole *gSynchConsole;
      #endif
      Trong file threads/system.cc, cũng trong phần khai báo macro USER_PROGRAM ta khai báo biến gSynchConsole (chỉ khai báo, không có khóa extern).
    2. User2System và System2User

      Mã code của 2 phương thức này được trình bày ở link này: Click vào đây

      Hai hàm này sẽ trở thành phương thức public trong lớp Machine. Khai báo hàm nằm ở machine/machine.h và phần định nghĩa sẽ nằm ở machine/machine.cc hoặc có thể là trong translate.cc. Mình nghĩ là nên đặt vào trong translate.cc hơn, vì nó phần nào thể hiện bản chất: các phương thức liên quan đến vùng nhớ sẽ được đặt ở đó.
  4. Test hàm và chạy thử nghiệm
    Trong thư mục test/, ta tạo một tập tin .c để kiểm tra tính đúng đắn của exception vừa viết. Đó là gọi hàm đó theo tham số đã đề xuất.
    Cấu hình Makefile:
    Để có thể sử dụng lớp SynchConsole, ta mở file Makefile.common và thêm các thông số sau:
    • Tại THREAD_H : ‘../threads/synchcons.h’
    • Tại THREAD_C : ‘../threads/synchcons.cc’
    • Tại THREAD_O : ‘../threads/synchcons.o’
      Cấu hình file test
      Ví dụ ta muốn chạy đoạn mã test.c, qui trình biên dịch và chạy như sau:
    • Trong file test/Makefile:
      all: ... test
      Thêm vào cuối file
      test.o: test.c
          $(CC) $(CFLAGS) -c test.c
      test: test.o test.o
          $(LD) $(LDFLAGS) start.o test.o -o test.coff
          ../bin/coff2noff test.coff test
      
      

      Sau khi make xong, ta chạy lệnh ./usrprog/nachos -rs 1023 -x [Đường dẫn đến file thực thi].

Mar 2, 2013

Cấu hình giao diện cho Eclipse trên Linux

Trong Linux, giao diện của Eclipse có phần bất tiện vì khoảng trắng giữa các icon khá lớn, khiến cho không gian trở nên nhỏ đi. Điều đó gây ra sự bất tiện lớn khi làm việc


Giải pháp cho vấn đề đó như sau:
  • Trong thư mục ~/ mở file .gtkrc-2.0 và chép đoạn mã sau:
    style "gtkcompact" {
     font_name="Sans 8"
     GtkButton::default_border={0,0,0,0}
     GtkButton::default_outside_border={0,0,0,0}
     GtkButtonBox::child_min_width=0
     GtkButtonBox::child_min_heigth=0
     GtkButtonBox::child_internal_pad_x=0
     GtkButtonBox::child_internal_pad_y=0
     GtkMenu::vertical-padding=1
     GtkMenuBar::internal_padding=0
     GtkMenuItem::horizontal_padding=4
     GtkToolbar::internal-padding=0
     GtkToolbar::space-size=0
     GtkOptionMenu::indicator_size=0
     GtkOptionMenu::indicator_spacing=0
     GtkPaned::handle_size=4
     GtkRange::trough_border=0
     GtkRange::stepper_spacing=0
     GtkScale::value_spacing=0
     GtkScrolledWindow::scrollbar_spacing=0
     GtkExpander::expander_size=10
     GtkExpander::expander_spacing=0
     GtkTreeView::vertical-separator=0
     GtkTreeView::horizontal-separator=0
     GtkTreeView::expander-size=8
     GtkTreeView::fixed-height-mode=TRUE
     GtkWidget::focus_padding=0
     }
    class "GtkWidget" style "gtkcompact"
    style "gtkcompactextra" {
     xthickness=0
     ythickness=0
    }
    class "GtkButton" style "gtkcompactextra"
    class "GtkToolbar" style "gtkcompactextra"
    class "GtkPaned" style "gtkcompactextra"
    
  • Lưu file này lại và mở lại Eclipse. Lưu ý: Các chương trình khác dùng giao diện gtk cũng bị ảnh hưởng
Kết quả thu được:

Về vấn đề autocomplete không hoạt động.Giải quyết: Nhấn Alt + W + P. Chọn C/C++ - Editor - Content Assist -- Advanced và tick chọn hết. Về vấn đề tooltip bị nền màu đen hoặc khung Proposals không nhìn được: chọn giao diện hệ thống khác ( gtk theme), hoặc phải cấu hình lại giao diện đó