IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 《操作系统真象还原》第十五章 ---- 实现系统交互 操作系统最终章 三十五天的不易与坚持终完结撒花(中) -> 正文阅读

[系统运维]《操作系统真象还原》第十五章 ---- 实现系统交互 操作系统最终章 三十五天的不易与坚持终完结撒花(中)


相关查阅博客链接


linux ls -l 详解
嵌入式—C语言—全局变量和extern的用法


本书中错误勘误


这两节中 PANICASSERT在书中全部小写
应该改过来 全部改成大写即可

在编写pad_print函数中 switch中间 刚哥加了个小补丁
补丁下面没有加break 需要加上哈

这个是超级错误 终极错误 我们最后的buildin_cmd文件要用shell.c的全局变量final_path 如果我们用extern来引用全局变量 这里注意 千万不能在声明全局变量的时候 直接初始化 我们尽量在函数里面memset就行了 这里如果我们在外面文件要用 那么就不能直接初始化 注意 注意!
就是那个语句

char final_path[MAX_PATH_LEN] = {0}
后面的初始化一定不要! 这里的话我把链接贴过来 这里说了千万不可 不然的话全局变量改变不了
嵌入式—C语言—全局变量和extern的用法

还有我发现需要memset我们的全局变量argv[MAX_ARG_NR] 因为我发现我不重置的话 命令输入输的多了 就自动停止了 直到我memset了 才解决了问题 不清楚为什么会这个样子


部分缩写熟知


/r 回车
/b 倒格
prompt 立刻 迅速的


实现shell(仅完成了输出+快捷键+解析字符)


哈哈 刚刚在书上面刚刚看到一个比较有意思的东西
shell.c里面 输出提示符 刚哥把提示符的字符串写的是
[rabbit@localhost /]$
不知道认真看过这本书每一个字的hxd们 知道这个是什么 哈哈
rabbit是刚哥的亲爱的老婆 王小兔的英文 哈哈
尽管说IT人 大部分都是追求技术的极客们 哈哈 性格直 心思少
但是还是能看出刚哥的生活和态度还是很让人喜悦的 哈哈

看到还是让人忍俊不禁啊 哈哈 那人家写rabbit
我作为博客博主 还是写个Love6吧 有始有终 毕竟最后一章了 毕竟这个操作系统是自己一个字一个字打出来的 留下自己的痕迹 那就定下来是
[Love 6@localhost /]$吧 哈哈


编写完的shell.c(仅完成了输出+快捷键+解析字符)


#include "shell.h"
#include "global.h"
#include "stdint.h"
#include "string.h"
#include "syscall.h"
#include "stdio.h"
#include "../fs/file.h"
#include "../kernel/debug.h"

#define cmd_len    128 //最大支持128个字符
#define MAX_ARG_NR 16  //命令名外支持15个参数

char cmd_line[cmd_len] = {0};
char cwd_cache[64] = {0}; //目录的缓存 执行cd则移动到其他目录去
char* argv[MAX_ARG_NR];   //参数

//固定输出提示副
void print_prompt(void)
{
    printf("[Love 6@localhost %s]$ ",cwd_cache);
}

//最多读入count字节到buf
void readline(char* buf,int32_t count)
{
    ASSERT(buf != NULL && count > 0);
    char* pos = buf;
    //默认没有到回车就不停止 、一个一个字节读
    while(read(stdin_no,pos,1) != -1 && (pos - buf) < count)
    {
        switch(*pos)
        {
            //清屏
            case 'l'-'a':
                *pos = 0;
                clear();
                print_prompt();
                printf("%s",buf);  //把刚刚键入的字符打印出开
                break;
            
            //清除输入
            case 'u'-'a':
                while(buf != pos)
                {
                    putchar('\b');
                    *(pos--) = 0;
                }
                break;
                
            //和下面的回车一起
            case '\n':
            case '\r':
                *pos = 0;
                putchar('\n');
                return;
            
            case '\b':
                if(buf[0] != '\b') //阻止删除不是本次输出的信息
                {
                    --pos;
                    putchar('\b');
                }
                break;
            
            default:
                putchar(*pos);
                ++pos;
        }
    }
    printf("readline: cant fine entry_key in the cmd_line,max num of char is 128\n");
}

//解析键入的字符 token为分割符号
int32_t cmd_parse(char* cmd_str,char** argv,char token)
{
    ASSERT(cmd_str != NULL);
    int32_t arg_idx = 0;
    
    //初始化指针数组
    while(arg_idx < MAX_ARG_NR)
    {
        argv[arg_idx] = NULL;
        arg_idx++;
    }
    char* next = cmd_str;
    int32_t argc = 0;
    while(*next)
    {
        while(*next == token)	++next;
        if(*next == 0)	break;	//如果最后一个参数后面是空格 则之后就是结束符号了
        argv[argc] = next;     //无论怎么样 到这里都是有字符的地方 且argc表示目前存在第几个参数字符串
        
        while(*next && *next != token)  //要不结束了为0 或者到了分割符号
            ++next;
            
        if(*next)
            *(next++) = 0; //到最后就是设置字符串的末尾0 分割符号位置刚好处理为0 这样字符串有结束末尾了
                        //最后一个参数后面自然有'\0'
        if(argc > MAX_ARG_NR)
            return -1;
        
        ++argc;        
    }
    return argc;        //多少个参数
}

void my_shell(void)
{
    cwd_cache[0] = '/';
    int argc = -1;
    while(1)
    {
        print_prompt();
        memset(cmd_line,0,cmd_len);
        readline(cmd_line,cmd_len);
        if(cmd_line[0] == 0)
            continue;
            
        argc = -1;  
        argc = cmd_parse(cmd_line,argv,' ');
        if(argc == -1)
        {
            printf("num of arguments exceed %d\n",MAX_ARG_NR);
            continue;
        }
        
        int32_t arg_idx = 0;
        while(arg_idx < argc)
        {
            printf("%s ",argv[arg_idx]);
            arg_idx++;
        }
        printf("\n");
    }
    PANIC("my_shell: should not be here");
}

编写完的shell.h(仅完成了输出+快捷键+解析字符)


#ifndef __SHELL_SHELL_H
#define __SHELL_SHELL_H

#include "stdint.h"

void print_prompt(void);
void readline(char* buf,int32_t count);
void my_shell(void);
int32_t cmd_parse(char* cmd_str,char** argv,char token);

#endif

稍加修改的keyboard.c(intr_keyboard_handler)


void intr_keyboard_handler(void)
{
    bool ctrl_down_last = ctrl_status;
    bool shift_down_last = shift_status;
    bool caps_lock_last = caps_lock_status;
    
    bool break_code;
    uint16_t scancode = inb(KBD_BUF_PORT);
    
    if(scancode == 0xe0)	//多字节处理
    {
    	ext_scancode = true;
    	return;
    }
    
    break_code = ((scancode & 0x0080) != 0); //断码 = 通码 + 0x80 通码最小比0x80小 则只有断码才可以有
    
    if(break_code)
    {
    	uint16_t make_code = (scancode &= 0xff7f); //多字节不处理
    	if(make_code == ctrl_l_make || make_code == ctrl_r_make) ctrl_status = false;
    	else if(make_code == shift_l_make || make_code == shift_r_make) shift_status = false;
    	else if(make_code == alt_l_make || make_code == alt_r_make) alt_status = false;
    	return;
    }
    else if((scancode > 0x00 && scancode < 0x3b) || (scancode == alt_r_make) || (scancode == ctrl_r_make))
    {
    	bool shift = false; //先默认设置成false
    	if((scancode < 0x0e) || (scancode == 0x29) || (scancode == 0x1a) || \
    	(scancode == 0x1b) || (scancode == 0x2b) || (scancode == 0x27) || \
    	(scancode == 0x28) || (scancode == 0x33) || (scancode == 0x34) || \
    	(scancode == 0x35))
    	{
    	    if(shift_down_last)	shift = true;
    	}
    	else
    	{
    	    if(shift_down_last && caps_lock_last)	shift = false; //效果确实是这样子的 我试了一下
    	    else if(shift_down_last || caps_lock_last) shift = true; //其中任意一个都是大写的作用
    	    else shift = false;
    	}
    	
    	uint8_t index = (scancode & 0x00ff);
        char cur_char = keymap[index][shift];
        
        if((ctrl_down_last && cur_char == 'l') || (ctrl_down_last && cur_char == 'u'))
            cur_char -= 'a';
        
        if(cur_char)
        {
        	if(!ioq_full(&ioqueue))
        		ioq_putchar(&ioqueue,cur_char);
        	//put_char(cur_char);
	    	return;
	}
    
	if(scancode == ctrl_l_make || scancode == ctrl_r_make)    	
	    ctrl_status = true;
	else if(scancode == shift_l_make || scancode == shift_r_make)
            shift_status = true;
	else if(scancode == alt_l_make || scancode == alt_r_make)
	    alt_status = true;
	else if(scancode == caps_lock_make)
	    caps_lock_status = !caps_lock_status;
	else put_str("unknown key\n");
    }
    
    return;
}

修改完的main.c


#include "print.h"
#include "init.h"
#include "debug.h"
#include "string.h"
#include "memory.h"
#include "../thread/thread.h"
#include "interrupt.h"
#include "../device/console.h"
#include "../device/ioqueue.h"
#include "../device/keyboard.h"
#include "../userprog/process.h"
#include "../lib/user/syscall.h"
#include "../userprog/syscall-init.h"
#include "../lib/stdio.h"
#include "../lib/kernel/stdio-kernel.h"
#include "../fs/fs.h"
#include "../fs/file.h"
#include "../shell/shell.h"

int main(void) 
{
    put_str("I am kernel\n");
    init_all();
    intr_enable();
    cls_screen();
    console_put_str("[Love 6@localhost /]$ ");
   
    while(1);
    return 0;
}

void init(void)
{
    uint32_t ret_pid = fork();
    if(ret_pid)
        while(1);
    else
        my_shell();
    PANIC("init: should not be here");
}

修改完的MakeFile


BUILD_DIR = ./build
ENTRY_POINT = 0xc0001500
AS = nasm
CC = gcc
LD = ld
LIB = -I lib/ -I lib/kernel/ -I lib/user/ -I kernel/ -I device/ 
ASFLAGS = -f elf
CFLAGS = -Wall -m32 -fno-stack-protector $(LIB) -c -fno-builtin -W -Wstrict-prototypes -Wmissing-prototypes
LDFLAGS =  -m elf_i386 -Ttext $(ENTRY_POINT) -e main -Map $(BUILD_DIR)/kernel.map
OBJS = $(BUILD_DIR)/main.o $(BUILD_DIR)/init.o $(BUILD_DIR)/interrupt.o \
      $(BUILD_DIR)/timer.o $(BUILD_DIR)/kernel.o $(BUILD_DIR)/print.o $(BUILD_DIR)/switch.o \
      $(BUILD_DIR)/debug.o $(BUILD_DIR)/string.o $(BUILD_DIR)/memory.o \
      $(BUILD_DIR)/bitmap.o $(BUILD_DIR)/thread.o $(BUILD_DIR)/list.o \
      $(BUILD_DIR)/sync.o $(BUILD_DIR)/console.o $(BUILD_DIR)/keyboard.o \
      $(BUILD_DIR)/ioqueue.o $(BUILD_DIR)/tss.o $(BUILD_DIR)/process.o \
      $(BUILD_DIR)/syscall-init.o $(BUILD_DIR)/syscall.o $(BUILD_DIR)/stdio.o \
      $(BUILD_DIR)/stdio-kernel.o $(BUILD_DIR)/ide.o $(BUILD_DIR)/fs.o $(BUILD_DIR)/inode.o \
      $(BUILD_DIR)/file.o $(BUILD_DIR)/dir.o $(BUILD_DIR)/fork.o $(BUILD_DIR)/shell.o
      
##############     c代码编译     ###############
$(BUILD_DIR)/main.o: kernel/main.c lib/kernel/print.h \
        lib/stdint.h kernel/init.h lib/string.h kernel/memory.h \
        thread/thread.h kernel/interrupt.h device/console.h \
        device/keyboard.h device/ioqueue.h userprog/process.h \
        lib/user/syscall.h userprog/syscall-init.h lib/stdio.h \
        lib/kernel/stdio-kernel.h fs/file.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/init.o: kernel/init.c kernel/init.h lib/kernel/print.h \
        lib/stdint.h kernel/interrupt.h device/timer.h kernel/memory.h \
        thread/thread.h device/console.h device/keyboard.h userprog/tss.h \
        userprog/syscall-init.h device/ide.h fs/fs.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/interrupt.o: kernel/interrupt.c kernel/interrupt.h \
        lib/stdint.h kernel/global.h lib/kernel/io.h lib/kernel/print.h \
        kernel/kernel.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/timer.o: device/timer.c device/timer.h lib/kernel/io.h lib/kernel/print.h \
        kernel/interrupt.h thread/thread.h kernel/debug.h kernel/global.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/debug.o: kernel/debug.c kernel/debug.h \
        lib/kernel/print.h lib/stdint.h kernel/interrupt.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/string.o: lib/string.c lib/string.h \
	kernel/debug.h kernel/global.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/memory.o: kernel/memory.c kernel/memory.h \
	lib/stdint.h lib/kernel/bitmap.h kernel/debug.h lib/string.h kernel/global.h \
	thread/sync.h thread/thread.h lib/kernel/list.h kernel/interrupt.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/bitmap.o: lib/kernel/bitmap.c lib/kernel/bitmap.h kernel/global.h \
	lib/string.h kernel/interrupt.h lib/kernel/print.h kernel/debug.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/thread.o: thread/thread.c thread/thread.h \
	lib/stdint.h lib/string.h kernel/global.h kernel/memory.h \
	kernel/debug.h kernel/interrupt.h lib/kernel/print.h \
	userprog/process.h thread/sync.h lib/user/syscall.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/list.o: lib/kernel/list.c lib/kernel/list.h \
	kernel/interrupt.h lib/stdint.h kernel/debug.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/sync.o: thread/sync.c thread/sync.h \
	lib/stdint.h thread/thread.h kernel/debug.h kernel/interrupt.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/console.o: device/console.c device/console.h \
	lib/kernel/print.h thread/sync.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/keyboard.o: device/keyboard.c device/keyboard.h \
	lib/kernel/print.h lib/kernel/io.h kernel/interrupt.h \
	kernel/global.h lib/stdint.h device/ioqueue.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/ioqueue.o: device/ioqueue.c device/ioqueue.h \
	kernel/interrupt.h kernel/global.h kernel/debug.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/tss.o: userprog/tss.c userprog/tss.h \
	kernel/global.h thread/thread.h lib/kernel/print.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/process.o: userprog/process.c userprog/process.h \
	lib/string.h kernel/global.h kernel/memory.h lib/kernel/print.h \
	thread/thread.h kernel/interrupt.h kernel/debug.h device/console.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/syscall-init.o: userprog/syscall-init.c userprog/syscall-init.h \
	lib/user/syscall.h lib/stdint.h lib/kernel/print.h kernel/interrupt.h thread/thread.h \
	kernel/memory.h fs/file.h userprog/fork.h lib/kernel/stdio-kernel.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/syscall.o: lib/user/syscall.c lib/user/syscall.h fs/file.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/stdio.o: lib/stdio.c lib/stdio.h lib/stdint.h lib/string.h lib/user/syscall.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/stdio-kernel.o: lib/kernel/stdio-kernel.c lib/kernel/stdio-kernel.h \
	lib/stdio.h device/console.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/ide.o: device/ide.c device/ide.h lib/stdint.h kernel/debug.h \
	lib/kernel/stdio-kernel.h lib/stdio.h kernel/global.h thread/sync.h \
	lib/kernel/io.h device/timer.h kernel/interrupt.h lib/kernel/list.h fs/fs.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/fs.o: fs/fs.c fs/fs.h lib/stdint.h kernel/global.h device/ide.h fs/inode.h fs/dir.h \
	fs/super_block.h lib/kernel/stdio-kernel.h lib/string.h kernel/debug.h lib/kernel/list.h \
	fs/file.h thread/thread.h device/ioqueue.h device/keyboard.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/inode.o: fs/inode.c fs/inode.h device/ide.h kernel/debug.h thread/thread.h \
	kernel/memory.h lib/string.h lib/kernel/list.h kernel/interrupt.h lib/kernel/bitmap.h \
	fs/file.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/file.o: fs/file.c fs/file.h lib/kernel/stdio-kernel.h thread/thread.h device/ide.h \
	fs/file.h kernel/global.h kernel/interrupt.h device/console.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/dir.o: fs/dir.c fs/dir.h device/ide.h fs/fs.h fs/inode.h kernel/memory.h lib/string.h lib/stdint.h \
	lib/kernel/stdio-kernel.h kernel/debug.h fs/file.h kernel/memory.h lib/string.h kernel/debug.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/fork.o: userprog/fork.c userprog/fork.h kernel/global.h lib/stdint.h lib/string.h \
	kernel/memory.h kernel/interrupt.h thread/sync.h thread/thread.h  kernel/debug.h userprog/process.h \
	lib/kernel/stdio-kernel.h fs/file.h lib/kernel/list.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/shell.o: shell/shell.c shell/shell.h kernel/global.h lib/stdint.h lib/string.h \
	lib/user/syscall.h lib/stdio.h fs/file.h kernel/debug.h
	$(CC) $(CFLAGS) $< -o $@

##############    汇编代码编译    ###############
$(BUILD_DIR)/kernel.o: kernel/kernel.S
	$(AS) $(ASFLAGS) $< -o $@

$(BUILD_DIR)/print.o: lib/kernel/print.S
	$(AS) $(ASFLAGS) $< -o $@

$(BUILD_DIR)/switch.o: thread/switch.S
	$(AS) $(ASFLAGS) $< -o $@

##############    链接所有目标文件    #############
$(BUILD_DIR)/kernel.bin: $(OBJS)
	$(LD) $(LDFLAGS) $^ -o $@

.PHONY : mk_dir hd clean all

mk_dir:
	if [ ! -d $(BUILD_DIR) ]; then mkdir $(BUILD_DIR); fi

hd:
	dd if=$(BUILD_DIR)/kernel.bin \
           of=/home/cooiboi/bochs/hd60M.img \
           bs=512 count=200 seek=9 conv=notrunc

clean:
	cd $(BUILD_DIR) && rm -f  ./*

build: $(BUILD_DIR)/kernel.bin

all: mk_dir build hd

make all 验证成果(仅完成了输出+快捷键+解析字符)


这里写了输出 快捷键 和解析字符
当然快捷键不好展示 就不展示了 就展示一下输出和 解析字符的效果

当然后面shell还要做改进 这是初代版本 我还是想一点点把迭代的代码发出来吧 不直接发最终代码 那各位看官看下面的效果
第一幅图忘直接加回车了 效果还是有的 为了好看就贴的下面的效果 哈哈
在这里插入图片描述


这里就是有间隔符 解析字符的效果了 还是可以看得出来 应该是成功了 那我们继续往下走
在这里插入图片描述


实现shell(添加了系统调用 + 实现了内建函数)


啊 这部分确实内容超级超级多 而且调试起来也是相当的不容易
而且最后的调试部分是依托着我们上一章节的文件系统的创建
这里我们这一章所编写的所有的函数不出错的话 仍然要保持不出错只能依托着原来上一章节函数全部都实现正确了

真的 每次做到这种 内容需要原来的内容作为基础我的脊背都会发冷 哈哈 开玩笑的 但是做到像这种原来的函数本来调试起来就相当不容易这一章编写的函数与原来需要叠用的 如果出错了 那是真的超级难找到错误

但是总而言之 现在各位看官看到这行文字的时候 程序此时肯定是我调试过几个小时 挑错挑了几个小时的完整实现的代码了 哈哈

如果大家的代码其中有问题的话 这一章的代码我还是很放心的让大家自己对比找一下错 那话不多说 内容还有很多没写 那下面走着


添加系统调用(syscall.c)


这部分超级超级多 方便大家还是直接给代码吧

#include "syscall.h"

#define _syscall0(NUMBER) ({ \
    int retval;		\
    asm volatile ("int $0x80" : "=a"(retval) : "a"(NUMBER) : "memory"); retval; \
    })

#define _syscall1(NUMBER, ARG1) ({ \
    int retval;		\
    asm volatile ("int $0x80" : "=a"(retval) : "a"(NUMBER) , "b"(ARG1) : "memory"); retval; \
    })
    
#define _syscall2(NUMBER, ARG1, ARG2) ({ \
    int retval;		\
    asm volatile ("int $0x80" : "=a"(retval) : "a"(NUMBER) , "b"(ARG1) , "c"(ARG2): "memory"); retval; \
    })

#define _syscall3(NUMBER, ARG1, ARG2, ARG3) ({ \
    int retval;		\
    asm volatile ("int $0x80" : "=a"(retval) : "a"(NUMBER) , "b"(ARG1) , "c"(ARG2), "d"(ARG3): "memory"); retval; \
    })

uint32_t getpid(void)
{
    return _syscall0(SYS_GETPID);
}

uint32_t write(int fd,const void* buf,int count)
{
    return _syscall3(SYS_WRITE,fd,buf,count);
}

void* malloc(uint32_t size)
{
    return _syscall1(SYS_MALLOC,size);
}

void free(void* ptr)
{
    return _syscall1(SYS_FREE,ptr);
}

int32_t fork(void)
{
    return _syscall0(SYS_FORK);
}

int32_t read(int32_t fd,void* buf,uint32_t count)
{
    return _syscall3(SYS_READ,fd,buf,count);
}

void putchar(const char chr)
{
    return _syscall1(SYS_PUTCHAR,chr);
}

void clear(void)
{
    return _syscall0(SYS_CLEAR);
}

char* getcwd(char* buf,uint32_t size)
{
    return (char*)_syscall2(SYS_GETCWD,buf,size);
}

int32_t open(char* pathname,uint8_t flag)
{
    return _syscall2(SYS_OPEN,pathname,flag);
}

int32_t close(int32_t fd)
{
    return _syscall1(SYS_CLOSE,fd);
}

int32_t lseek(int32_t fd,int32_t offset,uint8_t whence)
{
    return _syscall3(SYS_LSEEK,fd,offset,whence);
}

int32_t unlink(const char* pathname)
{
    return _syscall1(SYS_UNLINK,pathname);
}

int32_t mkdir(const char* pathname)
{
    return _syscall1(SYS_MKDIR,pathname);
}

struct dir* opendir(const char* name)
{
    return (struct dir*)_syscall1(SYS_OPENDIR,name);
}

int32_t closedir(struct dir* dir)
{
    return _syscall1(SYS_CLOSEDIR,dir);
}

int32_t rmdir(const char* pathname)
{
    return _syscall1(SYS_RMDIR,pathname);
}

struct dir_entry* readdir(struct dir* dir)
{
    return (struct dir_entry*)_syscall1(SYS_READDIR,dir);
}

void rewinddir(struct dir* dir)
{
    _syscall1(SYS_REWINDDIR,dir);
}

int32_t stat(const char* path,struct stat* buf)
{
    return _syscall2(SYS_STAT,path,buf);
}

int32_t chdir(const char* path)
{
    return _syscall1(SYS_CHDIR,path);
}

void ps(void)
{
    return _syscall0(SYS_PS);
}

添加系统调用(syscall.h)


#ifndef __LIB_USER_SCSCALL_H
#define __LIB_USER_SCSCALL_H
#include "stdint.h"
#include "../fs/file.h"

enum SYSCALL_NR
{
    SYS_GETPID,
    SYS_WRITE,
    SYS_MALLOC,
    SYS_FREE,
    SYS_FORK,
    SYS_READ,
    SYS_PUTCHAR,
    SYS_CLEAR,
    SYS_GETCWD,
    SYS_OPEN,
    SYS_CLOSE,
    SYS_LSEEK,
    SYS_UNLINK,
    SYS_MKDIR,
    SYS_OPENDIR,
    SYS_CLOSEDIR,
    SYS_CHDIR,
    SYS_RMDIR,
    SYS_READDIR,
    SYS_REWINDDIR,
    SYS_STAT,
    SYS_PS
};

uint32_t getpid(void);
uint32_t write(int fd,const void* buf,int count);
void* malloc(uint32_t size);
void free(void* ptr);
int32_t fork(void);
int32_t read(int32_t fd,void* buf,uint32_t count);
void putchar(const char chr);
void clear(void);
char* getcwd(char* buf,uint32_t size);
int32_t open(char* pathname,uint8_t flag);
int32_t close(int32_t fd);
int32_t lseek(int32_t fd,int32_t offset,uint8_t whence);
int32_t unlink(const char* pathname);
int32_t mkdir(const char* pathname);
struct dir* opendir(const char* name);
int32_t closedir(struct dir* dir);
int32_t rmdir(const char* pathname);
struct dir_entry* readdir(struct dir* dir);
void rewinddir(struct dir* dir);
int32_t stat(const char* path,struct stat* buf);
int32_t chdir(const char* path);
void ps(void);

#endif

编写完的syscall-init.c

#include "syscall-init.h"
#include "../lib/user/syscall.h"
#include "stdint.h"
#include "print.h"
#include "interrupt.h"
#include "memory.h"
#include "../thread/thread.h"
#include "../fs/file.h"
#include "fork.h"
#include "../lib/kernel/stdio-kernel.h"

#define syscall_nr 32
typedef void* syscall;
syscall syscall_table[syscall_nr];

uint32_t sys_getpid(void)
{
    return running_thread()->pid;
}

void syscall_init(void)
{
    put_str("syscall_init start\n");
    syscall_table[SYS_GETPID]    = sys_getpid;
    syscall_table[SYS_WRITE]     = sys_write;
    syscall_table[SYS_MALLOC]    = sys_malloc;
    syscall_table[SYS_FREE]      = sys_free;
    syscall_table[SYS_FORK]      = sys_fork;
    syscall_table[SYS_READ]      = sys_read;
    syscall_table[SYS_PUTCHAR]   = sys_putchar;
    syscall_table[SYS_CLEAR]     = cls_screen;
    syscall_table[SYS_GETCWD]    = sys_getcwd;
    syscall_table[SYS_OPEN]      = sys_open;
    syscall_table[SYS_CLOSE]     = sys_close;
    syscall_table[SYS_LSEEK]     = sys_lseek;
    syscall_table[SYS_UNLINK]    = sys_unlink;
    syscall_table[SYS_MKDIR]     = sys_mkdir;
    syscall_table[SYS_OPENDIR]   = sys_opendir;
    syscall_table[SYS_CLOSEDIR]  = sys_closedir;
    syscall_table[SYS_CHDIR]     = sys_chdir;
    syscall_table[SYS_RMDIR]     = sys_rmdir;
    syscall_table[SYS_READDIR]   = sys_readdir;
    syscall_table[SYS_REWINDDIR] = sys_rewinddir;
    syscall_table[SYS_STAT]      = sys_stat;
    syscall_table[SYS_PS]        = sys_ps;
    put_str("syscall_init done\n");
}

编写完的thread.c


我还是觉得 先把三个函数给出来吧 当然只给局部的代码有些细节就给不出来 当然这是最后一章了 就原谅原谅我吧 后面会专门写博客 把所有的代码都贴出来

void pad_print(char* buf,int32_t buf_len,void* ptr,char format)
{
    memset(buf,0,buf_len);
    uint8_t out_pad_0idx = 0;
    switch(format)
    {
        case 's':
            out_pad_0idx = sprintf(buf,"%s",ptr);
            break;
        case 'd':
            out_pad_0idx = sprintf(buf,"%d",*((int16_t*)ptr));
            break;
        case 'x':
            out_pad_0idx = sprintf(buf,"%x",*((uint32_t*)ptr));   
    }
    while(out_pad_0idx < buf_len)
    {
        buf[out_pad_0idx] = ' ';
        out_pad_0idx++;
    }
    sys_write(stdout_no,buf,buf_len-1);
}

bool elem2thread_info(struct list_elem* pelem,int arg)
{
    struct task_struct* pthread = elem2entry(struct task_struct,all_list_tag,pelem);
    char out_pad[16] = {0};
    pad_print(out_pad,16,&pthread->pid,'d');
    
    if(pthread->parent_pid == -1)
    	pad_print(out_pad,16,"NULL",'s');
    else
        pad_print(out_pad,16,&pthread->parent_pid,'d');
        
    switch(pthread->status)
    {
        case 0:
            pad_print(out_pad,16,"RUNNING",'s');
            break;
        case 1:
            pad_print(out_pad,16,"READY",'s');
            break;
        case 2:
            pad_print(out_pad,16,"BLOCKED",'s');
            break;
        case 3:
            pad_print(out_pad,16,"WAITING",'s');
            break;
        case 4:
            pad_print(out_pad,16,"HANGING",'s');
            break;
        case 5:
            pad_print(out_pad,16,"DIED",'s');
            break;
    }
    pad_print(out_pad,16,&pthread->elapsed_ticks,'x');
    
    memset(out_pad,0,16);
    ASSERT(strlen(pthread->name) < 17);
    memcpy(out_pad,pthread->name,strlen(pthread->name));
    strcat(out_pad,"\n");
    sys_write(stdout_no,out_pad,strlen(out_pad));
    return false;
}
//打印任务列表
void sys_ps(void)
{
    char* ps_title = "PID             PPID            STAT             TICKS            COMMAND\n";
    sys_write(stdout_no,ps_title,strlen(ps_title));
    list_traversal(&thread_all_list,elem2thread_info,0);
}


编写完的buildin_cmd.c


#include "buildin_cmd.h"
#include "../fs/file.h"
#include "../fs/fs.h"
#include "debug.h"
#include "string.h"
#include "syscall.h"
#include "stdio-kernel.h"
#include "../fs/dir.h"
#include "../fs/fs.h"
#include "stdio.h"
#include "shell.h"

extern char final_path[160];

//在用户态就把路径给解析出来
void wash_path(char* old_abs_path,char* new_abs_path)
{
    ASSERT(old_abs_path[0] == '/');
    char name[MAX_FILE_NAME_LEN] = {0};
    char* sub_path = old_abs_path;
    sub_path = path_parse(sub_path,name);
    
    //如果直接就是根目录 直接返回即可
    if(name[0] == 0)
    {
        new_abs_path[0] = '/';
        new_abs_path[1] = 0;
        return;
    }
    new_abs_path[0] = 0; 
    strcat(new_abs_path,"/");
    while(name[0])
    {
        if(!strcmp("..",name))   //返回上级
        {
            char* slash_ptr = strrchr(new_abs_path,'/'); //等于移动到最偏右的/位置去
            if(slash_ptr != new_abs_path)   //如果为 /aaa 那么移动之后就到/的位置了 如果是/aaa/bbb 那么就会回到/aaa/
                *slash_ptr = 0; // 把/变成0
            else
	        *(slash_ptr+1) = 0; // 如果是 / 或者 /aaa 那么都回到/ 则把最右边+1置零位即可
        }
        else if(strcmp(".",name))  //如果不是到. 增加到后米纳即可 .等于没有作用 继续遍历即可
        {
            if(strcmp(new_abs_path,"/"))  //不是 / 防止出现// 的情况
                strcat(new_abs_path,"/");
            strcat(new_abs_path,name);
        }
        
        memset(name,0,MAX_FILE_NAME_LEN);
        if(sub_path)
            sub_path = path_parse(sub_path,name);
    }
}

//把path处理 . ..去掉 储存在final_path getcwd得到当前工作目录 + 相对路径 即绝对路径
void make_clear_abs_path(char* path,char* final_path)
{
    char abs_path[MAX_PATH_LEN] = {0};
    if(path[0] != '/')  //如果不是绝对路径就弄成绝对路径
    {
        memset(abs_path,0,MAX_PATH_LEN);
        if(getcwd(abs_path,MAX_PATH_LEN) != NULL)
        {
            if(!((abs_path[0] == '/') && abs_path[1] == 0))
                strcat(abs_path,"/");
        }
    }
    //把path 加到工作目录的头上
    strcat(abs_path,path);
    wash_path(abs_path,final_path);
}

// pwd命令中的内建函数 得到当前工作目录
void buildin_pwd(uint32_t argc,char** argv)
{
    //没有参数才可以
    if(argc != 1)
        printf("pwd: no argument support!\n");
    else
    {
        if(getcwd(final_path,MAX_PATH_LEN) != NULL)
            printf("%s\n",final_path);
        else
            printf("pwd: get current work directory failed\n");
    }   
}

// 支持一个参数 改变当前工作目录
char* buildin_cd(uint32_t argc,char** argv)
{
    if(argc > 2)
    {
        printf("cd: only support 1 argument!\n");
        return NULL;
    }
    if(argc == 1)
    {
        final_path[0] = '/';
        final_path[1] = 0;
    }
    else    make_clear_abs_path(argv[1],final_path);
    
    if(chdir(final_path) == -1)
    {
        printf("cd: no such directory %s\n",final_path);
        return NULL;
    }
    return final_path;   
}

// ls内建函数 仅支持-l -h -h等于不支持 哈哈
void buildin_ls(uint32_t argc,char** argv)
{
    char* pathname = NULL;
    struct stat file_stat;
    memset(&file_stat,0,sizeof(struct stat));
    bool long_info = false;
    uint32_t arg_path_nr = 0;  
    uint32_t arg_idx = 1;    //第一个字符串是 ls 跳过
    while(arg_idx < argc)    //仅仅支持 ls 或者 ls -l 或者 ls -l path的形式
    {
        if(argv[arg_idx][0] == '-')
        {
            if(!strcmp("-l",argv[arg_idx]))
                long_info = true;
            else if(!strcmp("-h",argv[arg_idx]))
            {
                printf("usage: -l list all all information about the file.\nnot support -h now sry - -\n");
                return;
            }
            else
            {
                printf("ls: invaild option %s\nTry 'ls -l' u can get what u want\n",argv[arg_idx]);
                return; 
            }
        }
        else
        {
            if(arg_path_nr == 0)
            {
                pathname = argv[arg_idx];
                arg_path_nr = 1;
            }
            else
            {
                printf("ls: only support one path\n");
                return;
            }
        }
        ++arg_idx;
    }
    
    if(pathname == NULL) //ls 或者 ls -l
    {
        //得到工作目录
        if(getcwd(final_path,MAX_PATH_LEN) != NULL)
	    pathname = final_path;
	else
	{
	    printf("ls: getcwd for default path failed\n");
	    return;
	}
    }
    else
    {
        make_clear_abs_path(pathname,final_path);
        pathname = final_path;
    }
    
    //目录下的文件
    if(stat(pathname,&file_stat) == -1)
    {
        printf("ls: cannot access %s: No such file or directory\n",pathname);
        return;
    }
    
    if(file_stat.st_filetype == FT_DIRECTORY)  //得到目录文件才继续
    {
        struct dir* dir = opendir(pathname); //得到目录指针
        struct dir_entry* dir_e = NULL;
        char sub_pathname[MAX_PATH_LEN] = {0};
        uint32_t pathname_len   = strlen(pathname);
        uint32_t last_char_idx  = pathname_len - 1;
        memcpy(sub_pathname,pathname,pathname_len);
        
        //方便后面得到当前目录下的文件stat信息 
        //加个/ 之后每个文件加文件名stat即可
        if(sub_pathname[last_char_idx] != '/') 
        {
            sub_pathname[pathname_len] = '/'; 
            ++pathname_len;
        }
        
        rewinddir(dir);  //目录指针指向0  方便readdir遍历目录项
        if(long_info)    // ls -l 这里是目录的ls
        {
            char ftype;
            printf("total: %d\n",file_stat.st_size);
            while((dir_e = readdir(dir)))    //通过readdir来遍历目录项 我还专门回去看了看这个函数
            {
                ftype = 'd';
                if(dir_e->f_type == FT_REGULAR)
                    ftype = '-';
                sub_pathname[pathname_len] = 0; //把字符串末尾设0 方便strcat函数
                strcat(sub_pathname,dir_e->filename);
                memset(&file_stat,0,sizeof(struct stat));
                if(stat(sub_pathname,&file_stat) == -1)
                {
                    printf("ls: cannot access %s:No such file or directory\n",dir_e->filename);
                    return;
                }
                printf("%c    %d    %d    %s\n",ftype,dir_e->i_no,file_stat.st_size,dir_e->filename);
            }
        }
        else  //仅仅是ls 把文件名写出来即可
        {
            while((dir_e = readdir(dir)))
                printf("%s  ",dir_e->filename);
            printf("\n");
        }
        closedir(dir);
    }
    else
    {
        if(long_info)
             printf("-    %d    %d    %s\n",file_stat.st_ino,file_stat.st_size,pathname);
	else
	    printf("%s\n",pathname);
    }
}

void buildin_ps(uint32_t argc,char** argv)
{
     //不应该有参数
    if(argc != 1)
    {
        printf("ps: no argument support!\n");
        return;
    }
    ps();
}

void buildin_clear(uint32_t argc,char** argv)
{
    if(argc != 1)
    {
        printf("clear: no argument support!\n");
        return;
    }
    clear();
}

int32_t buildin_mkdir(uint32_t argc,char** argv)
{
    //必须要有一个 安装路径参数
    int32_t ret = -1;
    if(argc != 2)
        printf("mkdir: only support 1 argument!\n");
    else
    {
        make_clear_abs_path(argv[1],final_path);
        if(strcmp("/",final_path))  //不是根目录 根目录一直都在
        {
            if(mkdir(final_path) == 0)
                ret = 0;
            else
                printf("mkdir: create directory %s failed.\n",argv[1]);
        }
    }
    return ret;
}

int32_t buildin_rmdir(uint32_t argc,char** argv)
{
    int32_t ret = -1;
    if(argc != 2)
        printf("rmdir: only support 1 argument!\n");
    else
    {
        make_clear_abs_path(argv[1],final_path);
        if(strcmp("/",final_path)) // 不能删除根目录
        {
            if(rmdir(final_path) == 0)
                ret = 0;
            else    printf("rmdir: remove %s failed\n");
        }
    }
    return ret;
}

int32_t buildin_rm(uint32_t argc,char** argv)
{
    int32_t ret = -1;
    if(argc != 2)
        printf("rm: only support 1 argument!\n");
    else
    {
        make_clear_abs_path(argv[1],final_path);
        if(strcmp("/",final_path))
        {
            if(unlink(final_path) == 0)
                ret = 0;
            else    printf("rm: delete %s failed\n",argv[1]); 
        }
    }
    return ret;
}

编写完的buildin_cmd.h


#ifndef __SHELL_BUILDIN_CMD_H
#define __SHELL_BUILDIN_CMD_H
#include "stdint.h"

void wash_path(char* old_abs_path,char* new_abs_path);
void make_clear_abs_path(char* path,char* final_path);
void buildin_pwd(uint32_t argc,char** argv);
char* buildin_cd(uint32_t argc,char** argv);
void buildin_ls(uint32_t argc,char** argv);
void buildin_ps(uint32_t argc,char** argv);
void buildin_clear(uint32_t argc,char** argv);
int32_t buildin_mkdir(uint32_t argc,char** argv);
int32_t buildin_rmdir(uint32_t argc,char** argv);
int32_t buildin_rm(uint32_t argc,char** argv);

#endif

编写完的shell.c


#include "shell.h"
#include "global.h"
#include "stdint.h"
#include "string.h"
#include "syscall.h"
#include "stdio.h"
#include "../fs/file.h"
#include "../kernel/debug.h"
#include "buildin_cmd.h"
#include "../fs/fs.h"

#define cmd_len    128 //最大支持128个字符
#define MAX_ARG_NR 16  //命令名外支持15个参数

char cmd_line[cmd_len] = {0};
char cwd_cache[64] = {0}; //目录的缓存 执行cd则移动到其他目录去
char final_path[MAX_PATH_LEN];
char* argv[MAX_ARG_NR];   //参数

//固定输出提示副
void print_prompt(void)
{
    printf("[Love 6@localhost %s]$ ",cwd_cache);
}

//最多读入count字节到buf
void readline(char* buf,int32_t count)
{
    ASSERT(buf != NULL && count > 0);
    char* pos = buf;
    //默认没有到回车就不停止 、一个一个字节读
    while(read(stdin_no,pos,1) != -1 && (pos - buf) < count)
    {
        switch(*pos)
        {
            //清屏
            case 'l'-'a':
                *pos = 0;
                clear();
                print_prompt();
                printf("%s",buf);  //把刚刚键入的字符打印出开
                break;
            
            //清除输入
            case 'u'-'a':
                while(buf != pos)
                {
                    putchar('\b');
                    *(pos--) = 0;
                }
                break;
                
            //和下面的回车一起
            case '\n':
            case '\r':
                *pos = 0;
                putchar('\n');
                return;
            
            case '\b':
                if(buf[0] != '\b') //阻止删除不是本次输出的信息
                {
                    --pos;
                    putchar('\b');
                }
                break;
            
            default:
                putchar(*pos);
                ++pos;
        }
    }
    printf("readline: cant fine entry_key in the cmd_line,max num of char is 128\n");
}

//解析键入的字符 token为分割符号
int32_t cmd_parse(char* cmd_str,char** argv,char token)
{
    ASSERT(cmd_str != NULL);
    int32_t arg_idx = 0;
    
    //初始化指针数组
    while(arg_idx < MAX_ARG_NR)
    {
        argv[arg_idx] = NULL;
        arg_idx++;
    }
    char* next = cmd_str;
    int32_t argc = 0;
    while(*next)
    {
        while(*next == token)	++next;
        if(*next == 0)	break;	//如果最后一个参数后面是空格 则之后就是结束符号了
        argv[argc] = next;     //无论怎么样 到这里都是有字符的地方 且argc表示目前存在第几个参数字符串
        
        while(*next && *next != token)  //要不结束了为0 或者到了分割符号
            ++next;
            
        if(*next)
            *(next++) = 0; //到最后就是设置字符串的末尾0 分割符号位置刚好处理为0 这样字符串有结束末尾了
                        //最后一个参数后面自然有'\0'
        if(argc > MAX_ARG_NR)
            return -1;
        
        ++argc;        
    }
    return argc;        //多少个参数
}

void my_shell(void)
{
    cwd_cache[0] = '/';
    cwd_cache[1] = 0;
    int argc = -1;
    while(1)
    {
        print_prompt();
        memset(cmd_line,0,cmd_len);
        memset(final_path,0,MAX_PATH_LEN);
        memset(argv,0,sizeof(char*) * MAX_ARG_NR);
        readline(cmd_line,cmd_len);
        if(cmd_line[0] == 0)
            continue;
            
        argc = -1;  
        argc = cmd_parse(cmd_line,argv,' ');
        if(argc == -1)
        {
            printf("num of arguments exceed %d\n",MAX_ARG_NR);
            continue;
        }
        if(!strcmp("ls",argv[0]))
            buildin_ls(argc,argv);
        else if(!strcmp("pwd",argv[0]))
            buildin_pwd(argc,argv);
        else if(!strcmp("ps",argv[0]))
            buildin_ps(argc,argv);
        else if(!strcmp("cd",argv[0]))
        {
            if(buildin_cd(argc,argv) != NULL)
            {
                memset(cwd_cache,0,MAX_PATH_LEN);
                strcpy(cwd_cache,final_path);
            }
        }
        else if(!strcmp("clear",argv[0]))
            buildin_clear(argc,argv);
        else if(!strcmp("mkdir",argv[0]))
            buildin_mkdir(argc,argv);
        else if(!strcmp("rmdir",argv[0]))
            buildin_rmdir(argc,argv);   
        else if(!strcmp("rm",argv[0]))
            buildin_rm(argc,argv); 
        else
            printf("external command\n");
    }
    PANIC("my_shell: should not be here");
}

编写完的shell.h


#ifndef __SHELL_SHELL_H
#define __SHELL_SHELL_H

#include "stdint.h"
#include "../fs/fs.h"

void print_prompt(void);
void readline(char* buf,int32_t count);
void my_shell(void);
int32_t cmd_parse(char* cmd_str,char** argv,char token);

#endif

修改完的MakeFile


BUILD_DIR = ./build
ENTRY_POINT = 0xc0001500
AS = nasm
CC = gcc
LD = ld
LIB = -I lib/ -I lib/kernel/ -I lib/user/ -I kernel/ -I device/ 
ASFLAGS = -f elf
CFLAGS = -Wall -m32 -fno-stack-protector $(LIB) -c -fno-builtin -W -Wstrict-prototypes -Wmissing-prototypes
LDFLAGS =  -m elf_i386 -Ttext $(ENTRY_POINT) -e main -Map $(BUILD_DIR)/kernel.map
OBJS = $(BUILD_DIR)/main.o $(BUILD_DIR)/init.o $(BUILD_DIR)/interrupt.o \
      $(BUILD_DIR)/timer.o $(BUILD_DIR)/kernel.o $(BUILD_DIR)/print.o $(BUILD_DIR)/switch.o \
      $(BUILD_DIR)/debug.o $(BUILD_DIR)/string.o $(BUILD_DIR)/memory.o \
      $(BUILD_DIR)/bitmap.o $(BUILD_DIR)/thread.o $(BUILD_DIR)/list.o \
      $(BUILD_DIR)/sync.o $(BUILD_DIR)/console.o $(BUILD_DIR)/keyboard.o \
      $(BUILD_DIR)/ioqueue.o $(BUILD_DIR)/tss.o $(BUILD_DIR)/process.o \
      $(BUILD_DIR)/syscall-init.o $(BUILD_DIR)/syscall.o $(BUILD_DIR)/stdio.o \
      $(BUILD_DIR)/stdio-kernel.o $(BUILD_DIR)/ide.o $(BUILD_DIR)/fs.o $(BUILD_DIR)/inode.o \
      $(BUILD_DIR)/file.o $(BUILD_DIR)/dir.o $(BUILD_DIR)/fork.o $(BUILD_DIR)/shell.o \
      $(BUILD_DIR)/buildin_cmd.o
      
##############     c代码编译     ###############
$(BUILD_DIR)/main.o: kernel/main.c lib/kernel/print.h \
        lib/stdint.h kernel/init.h lib/string.h kernel/memory.h \
        thread/thread.h kernel/interrupt.h device/console.h \
        device/keyboard.h device/ioqueue.h userprog/process.h \
        lib/user/syscall.h userprog/syscall-init.h lib/stdio.h \
        lib/kernel/stdio-kernel.h fs/file.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/init.o: kernel/init.c kernel/init.h lib/kernel/print.h \
        lib/stdint.h kernel/interrupt.h device/timer.h kernel/memory.h \
        thread/thread.h device/console.h device/keyboard.h userprog/tss.h \
        userprog/syscall-init.h device/ide.h fs/fs.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/interrupt.o: kernel/interrupt.c kernel/interrupt.h \
        lib/stdint.h kernel/global.h lib/kernel/io.h lib/kernel/print.h \
        kernel/kernel.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/timer.o: device/timer.c device/timer.h lib/kernel/io.h lib/kernel/print.h \
        kernel/interrupt.h thread/thread.h kernel/debug.h kernel/global.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/debug.o: kernel/debug.c kernel/debug.h \
        lib/kernel/print.h lib/stdint.h kernel/interrupt.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/string.o: lib/string.c lib/string.h \
	kernel/debug.h kernel/global.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/memory.o: kernel/memory.c kernel/memory.h \
	lib/stdint.h lib/kernel/bitmap.h kernel/debug.h lib/string.h kernel/global.h \
	thread/sync.h thread/thread.h lib/kernel/list.h kernel/interrupt.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/bitmap.o: lib/kernel/bitmap.c lib/kernel/bitmap.h kernel/global.h \
	lib/string.h kernel/interrupt.h lib/kernel/print.h kernel/debug.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/thread.o: thread/thread.c thread/thread.h \
	lib/stdint.h lib/string.h kernel/global.h kernel/memory.h \
	kernel/debug.h kernel/interrupt.h lib/kernel/print.h \
	userprog/process.h thread/sync.h lib/user/syscall.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/list.o: lib/kernel/list.c lib/kernel/list.h \
	kernel/interrupt.h lib/stdint.h kernel/debug.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/sync.o: thread/sync.c thread/sync.h \
	lib/stdint.h thread/thread.h kernel/debug.h kernel/interrupt.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/console.o: device/console.c device/console.h \
	lib/kernel/print.h thread/sync.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/keyboard.o: device/keyboard.c device/keyboard.h \
	lib/kernel/print.h lib/kernel/io.h kernel/interrupt.h \
	kernel/global.h lib/stdint.h device/ioqueue.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/ioqueue.o: device/ioqueue.c device/ioqueue.h \
	kernel/interrupt.h kernel/global.h kernel/debug.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/tss.o: userprog/tss.c userprog/tss.h \
	kernel/global.h thread/thread.h lib/kernel/print.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/process.o: userprog/process.c userprog/process.h \
	lib/string.h kernel/global.h kernel/memory.h lib/kernel/print.h \
	thread/thread.h kernel/interrupt.h kernel/debug.h device/console.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/syscall-init.o: userprog/syscall-init.c userprog/syscall-init.h \
	lib/user/syscall.h lib/stdint.h lib/kernel/print.h kernel/interrupt.h thread/thread.h \
	kernel/memory.h fs/file.h userprog/fork.h lib/kernel/stdio-kernel.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/syscall.o: lib/user/syscall.c lib/user/syscall.h fs/file.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/stdio.o: lib/stdio.c lib/stdio.h lib/stdint.h lib/string.h lib/user/syscall.h
	$(CC) $(CFLAGS) $< -o $@

$(BUILD_DIR)/stdio-kernel.o: lib/kernel/stdio-kernel.c lib/kernel/stdio-kernel.h \
	lib/stdio.h device/console.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/ide.o: device/ide.c device/ide.h lib/stdint.h kernel/debug.h \
	lib/kernel/stdio-kernel.h lib/stdio.h kernel/global.h thread/sync.h \
	lib/kernel/io.h device/timer.h kernel/interrupt.h lib/kernel/list.h fs/fs.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/fs.o: fs/fs.c fs/fs.h lib/stdint.h kernel/global.h device/ide.h fs/inode.h fs/dir.h \
	fs/super_block.h lib/kernel/stdio-kernel.h lib/string.h kernel/debug.h lib/kernel/list.h \
	fs/file.h thread/thread.h device/ioqueue.h device/keyboard.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/inode.o: fs/inode.c fs/inode.h device/ide.h kernel/debug.h thread/thread.h \
	kernel/memory.h lib/string.h lib/kernel/list.h kernel/interrupt.h lib/kernel/bitmap.h \
	fs/file.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/file.o: fs/file.c fs/file.h lib/kernel/stdio-kernel.h thread/thread.h device/ide.h \
	fs/file.h kernel/global.h kernel/interrupt.h device/console.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/dir.o: fs/dir.c fs/dir.h device/ide.h fs/fs.h fs/inode.h kernel/memory.h lib/string.h lib/stdint.h \
	lib/kernel/stdio-kernel.h kernel/debug.h fs/file.h kernel/memory.h lib/string.h kernel/debug.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/fork.o: userprog/fork.c userprog/fork.h kernel/global.h lib/stdint.h lib/string.h \
	kernel/memory.h kernel/interrupt.h thread/sync.h thread/thread.h  kernel/debug.h userprog/process.h \
	lib/kernel/stdio-kernel.h fs/file.h lib/kernel/list.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/shell.o: shell/shell.c shell/shell.h kernel/global.h lib/stdint.h lib/string.h \
	lib/user/syscall.h lib/stdio.h fs/file.h kernel/debug.h shell/buildin_cmd.h fs/fs.h
	$(CC) $(CFLAGS) $< -o $@
	
$(BUILD_DIR)/buildin_cmd.o: shell/buildin_cmd.c shell/buildin_cmd.h fs/file.h fs/fs.h kernel/debug.h \
	lib/string.h lib/user/syscall.h fs/dir.h fs/fs.h lib/stdio.h shell/shell.h
	$(CC) $(CFLAGS) $< -o $@

##############    汇编代码编译    ###############
$(BUILD_DIR)/kernel.o: kernel/kernel.S
	$(AS) $(ASFLAGS) $< -o $@

$(BUILD_DIR)/print.o: lib/kernel/print.S
	$(AS) $(ASFLAGS) $< -o $@

$(BUILD_DIR)/switch.o: thread/switch.S
	$(AS) $(ASFLAGS) $< -o $@

##############    链接所有目标文件    #############
$(BUILD_DIR)/kernel.bin: $(OBJS)
	$(LD) $(LDFLAGS) $^ -o $@

.PHONY : mk_dir hd clean all

mk_dir:
	if [ ! -d $(BUILD_DIR) ]; then mkdir $(BUILD_DIR); fi

hd:
	dd if=$(BUILD_DIR)/kernel.bin \
           of=/home/cooiboi/bochs/hd60M.img \
           bs=512 count=200 seek=9 conv=notrunc

clean:
	cd $(BUILD_DIR) && rm -f  ./*

build: $(BUILD_DIR)/kernel.bin

all: mk_dir build hd

make all 验证成果


由于这一篇的博客 内容挺多的了多到我编辑这篇博客就开始卡了 所以我们的用户进程和后面的两个只能一起放到最后的博客来写了 估计那篇博客的内容超级多 那我们就上图了

第一个是解析路径 第二个是最后的命令解析 看效果应该是没有问题的 那就下一篇 可能是最后一篇见啦!

在这里插入图片描述


在这里插入图片描述

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2021-08-14 14:33:10  更:2021-08-14 14:34:28 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/20 18:31:09-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码