「30日でできる!OS自作入門」をRustで。18日目

Posted on July 13, 2019 , Tags: OS自作入門, OS, Rust

「30日でできる!OS自作入門 」のC言語の部分をできるだけRustですすめてみる。今回は18日目の内容。

ウィンドウの非アクティブ時にはカーソルの点滅を止める

現在は両方のウィンドウのカーソルが常に点滅している状態なので、ウィンドウがアクティブかどうかで制御する。

コンソールタスクの方にはfifo経由で渡すようにしている。 コンソールタスク側にも点滅制御ロジックがはいるが、同じなので省略する。

実行結果

カーソル点滅の抑止

Enterキーのハンドリング

Enterキーを入力されたときの処理を追加する。
コンソールウィンドウでのみ扱いたいため、コンソールウィンドウのタスク側にfifo経由で送る。

コンソールタスク側ではCONSOLE_ENTERをうけとったら、Y座標を一文字分変えるようにする。 ウィンドウの最後までいった場合はスクロール処理をする。

実行結果

以下の通り改行とスクロールができた。

改行とスクロール

memコマンドの実装

コンソール上でmemと入力することで、メモリの使用量を表示するようなコマンドを実装する。
実装にあたり、改行されるまでに入力された文字を格納していく配列をつくる。
尚、今後もコンソールにコマンドを追加していくようなので、console.rsという新しいファイルを作り、そちらにコンソールまわりはまとめることにした。

改行処理をまとめたnewline、コマンド実行をまとめたexec_cmdという関数を追加する。
newlineは前述の処理をまとめただけなので、記載は省く。

// console.rs
fn exec_cmd(
    cmdline: [u8; 30],
    cursor_y: isize,
    sheet_manager: &mut SheetManager,
    sheet_index: usize,
    memtotal: usize,
) -> isize {
    let sheet = sheet_manager.sheets_data[sheet_index];
    let mut cursor_y = cursor_y;
    let cmd_ind = extract_cmd_index(cmdline);
    let cmd = core::str::from_utf8(&cmdline[cmd_ind.0..cmd_ind.1]).unwrap();
    if cmd == "mem" {
        let memman = unsafe { &mut *(MEMMAN_ADDR as *mut MemMan) };

        write_with_bg!(
            sheet_manager,
            sheet_index,
            sheet.width,
            sheet.height,
            8,
            cursor_y,
            Color::White,
            Color::Black,
            30,
            "total   {}MB",
            memtotal / (1024 * 1024)
        );
        cursor_y = newline(cursor_y, sheet_manager, sheet_index);
        write_with_bg!(
            sheet_manager,
            sheet_index,
            sheet.width,
            sheet.height,
            8,
            cursor_y,
            Color::White,
            Color::Black,
            30,
            "free {}KB",
            memman.total() / 1024
        );
        cursor_y = newline(cursor_y, sheet_manager, sheet_index);
        cursor_y = newline(cursor_y, sheet_manager, sheet_index);
    } else {
        write_with_bg!(
            sheet_manager,
            sheet_index,
            sheet.width,
            sheet.height,
            8,
            cursor_y,
            Color::White,
            Color::Black,
            12,
            "Bad Command"
        );
        cursor_y = newline(cursor_y, sheet_manager, sheet_index);
        cursor_y = newline(cursor_y, sheet_manager, sheet_index);
    }
    cursor_y
}

fn extract_cmd_index(cmdline: [u8; 30]) -> (usize, usize) {
    // 空白(32)、0はとばす
    let mut start: isize = -1;
    let mut end: isize = -1;
    for i in 0..cmdline.len() {
        if start < 0 {
            if cmdline[i] != 0 && cmdline[i] != 32 {
                start = i as isize;
                end = i as isize;
            }
        } else {
            end = i as isize;
            if cmdline[i] == 0 || cmdline[i] == 32 {
                break;
            }
        }
    }
    (
        (if start < 0 { 0 } else { start }) as usize,
        (if end < 0 { 0 } else { end }) as usize,
    )
}

コマンド文字列を認識するために、空白や未入力の部分を省いた配列のインデックスを抽出するためのextract_cmd_indexという関数も追加している。(この処理は独自に追加した。)

実行結果

コンソール上にメモリ容量が表示できるようになった。

memコマンド

clear(cls) コマンドの追加

コンソールの表示をクリアするためのclearコマンドを追加する。
本中ではclsになっているが、自分はLinuxで実行しているため、せっかくなのでclearとする。

実行結果

画面がクリアできるようになったことがわかる。

clearコマンド

ls(dir)コマンドの追加

ファイル情報の表示を行うコマンドを追加する。
ここでも本はdirとなっているが、lsとして実装する。
まずはファイル情報を読み込むためのstructと定数をfile.rsに定義しておく。

これを使って、ファイル情報を読み込み、表示する。

表示確認のため、Makefileで適当なファイルをイメージに追加しておく。

実行結果

以下の通り、ファイル情報が表示された。

lsコマンド

18日目は以上となる。ここまでの内容のコードはyoshitsugu/hariboteos_in_rustのday18としてタグを打ってある。