• 【HIT-OSLAB-2-系统调用的实现】


    lab2-system call

    实验目的

    • 建立对系统调用接口的深入认识
    • 掌握系统调用的基本过程
    • 能完成系统调用的全面控制
    • 为后续实验做准备

    实验内容

    指导书给的内容

    iam()

    第一个系统调用是iam(),其原型为:

    int iam(const char * name);
    
    • 1

    完成的功能是将字符串参数name的内容拷贝到内核中保存下来。要求name的长度不能超过23个字符。返回值是拷贝的字符数。如果name的字符个数超过了23,则返回“-1”,并置errno为EINVAL。

    在kernal/who.c中实现此系统调用。

    whoami()

    第二个系统调用是whoami(),其原型为:

    int whoami(char* name, unsigned int size);
    
    • 1

    它将内核中由iam()保存的名字拷贝到name指向的用户地址空间中,同时确保不会对name越界访存(name的大小由size说明)。返回值是拷贝的字符数。如果size小于需要的空间,则返回“-1”,并置errno为EINVAL。

    也是在kernal/who.c中实现。

    简单点

    两个函数

    在kernel/who.c中一块实现。

    iam存储一个字符串

    whoami将这个字符串复制到给定的字符指针所指向的区域。

    如果长度不够,就返回-1,置errno为EINVAL。

    实验中的记录

    /lib/_who.c
    #define __LIBRARY__
    #include 
    _syscall1(int, iam, const char*, name);
    _syscall2(int, whoami, char*, name, unsigned int, size);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    /include/unistd.h
    
    #define __NR_whoami 72
    #define __NR_iam 73
    
    • 1
    • 2
    • 3
    • 4
    /include/linux/sys.h
    extern int sys_whoami();
    extern int sys_iam();
    
    fn_ptr sys_call_table [] = {
        ...
        sys_whoami, sys_iam
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    /kernel/system_call.s
    nr_system_calls = 74
    
    • 1
    • 2
    /kernel/who.c
        #include 
    int sys_iam(const char* name) {
        return -1;
    }
    
    int sys_whoami(char *name, unsigned int size) {
        return -1;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    /kernel/Makefile
    OBJS = sched.o system_call.o traps.o asm.o fork.o \
        panic.o printk.o vsprintf.o sys.o exit.o \
        signal.o mktime.o who.o
        
    ### Dependencies:
    who.s who.o: who.c ../include/linux/kernel.h ../include/unistd.h \
        ../include/errno.h
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    gcc -o iam iam.c -Wall
    ./iam
    sync //写入磁盘
    
    • 1
    • 2
    • 3

    第一次报错信息

    iam.c
        
    #include 
    #define __LIBRARY__
    #include 
        
    _syscall1(int, iam, const char*, name);
    _syscall2(int, whoami, char*, name, unsigned int, size);
    
    int main () {
        printf("%d\n", iam("rebel over waist"));
        printf("%d\n", whoami("who are you", 0));
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    __NR_whoami undeclared
    __NR_iam undeclared
    
    在unistd.h中存在函数调用
    in function iam:
    __NR_iam undeclared
    
    in function whoami:
    __NR_whoami undeclared
    
    原因
    在写好的库中
    
    嗯
    也就是在编译完运行之后的系统库中
    确实不存在这两个号
    我记得之前提到过
    
    在0.11环境下编译C程序,包含的头文件都在/usr/include目录下。该目录下的unistd.h是标准头文件(它和0.11源码树中的unistd.h并不是同一个文件,虽然内容可能相同),没有__NR_whoami和__NR_iam两个宏,需要手工加上它们,也可以直接从修改过的0.11源码树中拷贝新的unistd.h过来。
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    怎么传值

    又遇到了一个问题
    就是参数并没有传进去
    刚刚查看了汇编的源代码
    确实是传了的
    但是不知道为什么是那样

    我觉得是因为指针传递的问题

    也就是内核的数据和用户的数据其实并不是共享的

    你所传递的字符串是用户区域的字符串的首地址

    .globl _iam
    _iam:
    	pushl %ebp
    	
    	movl %esp, %ebp ; esp -> ebp
    	subl $4, %esp ;alloc 4 bytes
    	pushl %ebx ; push ebx 
    	
    	movl $73, %eax
    	movl 8(%ebp), %ebx; get address of string
    	int 0x80
    	
    	movl %eax, -4(%ebp)
    	cmpl $0, -4(%ebp)
    	jl L2
    	movl -4(%ebp), %eax
    	jmp L1
    	.align 2
    L2:
    	movl -4(%ebp), %eax
    	negl %eax
    	movl %eax, _errno
    	movl $-1, %eax
    	jmp L1
    	.align 2
    L1:
    	leal -8(%ebp), %esp
    	popl %ebx
    	leave
    	ret
    	.align 2
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    system_call:
    	cmpl $nr_system_calls-1,%eax    # 调用号如果超出范围的话就在eax中置-1并退出
    	ja bad_sys_call
    	push %ds                        # 保存原段寄存器值
    	push %es
    	push %fs
    # 一个系统调用最多可带有3个参数,也可以不带参数。下面入栈的ebx、ecx和edx中放着系统
    # 调用相应C语言函数的调用函数。这几个寄存器入栈的顺序是由GNU GCC规定的,
    # ebx 中可存放第1个参数,ecx中存放第2个参数,edx中存放第3个参数。
    # 系统调用语句可参见头文件include/unistd.h中的系统调用宏。
    	pushl %edx
    	pushl %ecx		# push %ebx,%ecx,%edx as parameters
    	pushl %ebx		# to the system call
    	movl $0x10,%edx		# set up ds,es to kernel space
    	mov %dx,%ds
    	mov %dx,%es
    # fs指向局部数据段(局部描述符表中数据段描述符),即指向执行本次系统调用的用户程序的数据段。
    # 注意,在Linux 0.11 中内核给任务分配的代码和数据内存段是重叠的,他们的段基址和段限长相同。
    	movl $0x17,%edx		# fs points to local data space
    	mov %dx,%fs
    # 下面这句操作数的含义是:调用地址=[_sys_call_table + %eax * 4]
    # sys_call_table[]是一个指针数组,定义在include/linux/sys.h中,该指针数组中设置了所有72
    # 个系统调用C处理函数地址。
    	call sys_call_table(,%eax,4)        # 间接调用指定功能C函数
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    所以fs是关键

    include/asm/segment.h
    static inline unsigned char get_fs_byte(const char * addr)
    {
    	unsigned register char _v;
    
    	__asm__ ("movb %%fs:%1,%0":"=r" (_v):"m" (*addr));
    	return _v;
    }
    
    static inline void put_fs_byte(char val,char *addr)
    {
    __asm__ ("movb %0,%%fs:%1"::"r" (val),"m" (*addr));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    第二次错误 segment fault

    length: 16
    general protection: 0000
    fs: 0010
    base: 1000 0000
    limit: 0400 0000
    Segmentation fault
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    之前的代码使用的是指针版本

    现在的代码使用的是数组版本

    可能是因为char * p = const char* s

    不被允许,p被修改了0?

    第三个错误

    代码自己测完全没问题

    但是给测试程序,怎么也跑不对。

    请添加图片描述

    请添加图片描述

    请添加图片描述

    而且很奇怪,内核函数的错误输出在前面,但是测试样例在后面。

    我还以为是我看错了,又特地加上了字符串长度,结果还是这样的。

    但是我看了看程序的源码,都是正常的啊。

    很正常的顺序执行,不就是调用了一下函数,和应该有的结果做了一下比较。

    而且这个报错还真的就是返回值为-1的时候才有的报错。

    晕了。

    到网上找到了一份说是全通过的代码,但是看了一眼它的具体实现,我的天,sys_iam, sys_whoami连errno都不带,返回值不是-1,返回的是-EINVAL, 但是测试程序和我的一样,这是咋全对的?

    又看了他的iam.c 和whoami.c,额,直接根据返回值给errno赋值。啧啧啧。

    不想管了。

    第四个问题

    我在linux0.11是root用户

    但是怎么也修改不了iam.c这种文件的删除,重命名权限。

    总是说不是文件所有者

    但是我用ls -al看了一下,所有者都是root啊

    搞不懂

    实验原理

    系统调用的实现首先得理解下面这些步骤

    应用程序调用库函数(API);
    API将系统调用号存入EAX,然后通过中断调用使系统进入内核态;
    内核中的中断处理函数根据系统调用号,调用对应的内核函数(系统调用);
    系统调用完成相应功能,将返回值存入EAX,返回到中断处理函数;
    中断处理函数返回到API中;
    API将EAX返回给应用程序。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    调用API

    为了方便去做系统调用和接口,linux采取了统一的系统调用接口,这些调用区分是参数个数和调用号。

    参数最多3个。放到ebx ecx edx中。

    调用号放到eax中。

    调用号在unistd.h中。(注意,这里(include/unistd.h)的unistd.h和你跑的linux0.11中的unistd.h不是一个,也就是说你就算在include/unistd.h中修改了,在linux0.11中的那个也还是原来的样子。而你的应用程序,实际上include的是系统中的。所以你得找到这个库文件,然后给它加上几个系统调用号。这样才能在代码中调用成功。

    系统调用总数在system_call.s中,由于你要新加系统调用,就得改一下总数。

    system_call.s中的代码其实不需要修改,这是一个统一的接口,用来进行进程切换等等操作。

    最后会根据include/linux/sys.h中的函数表找到对应功能的函数。

    所以你这个时候得在这个表sys_call_table的指定位置,也就是你的系统调用号对应的位置,填上你要执行的函数。

    这个函数并不在这头文件中实现。

    所以你得在前面说明这是一个外部函数,然后找到去进行具体的实现。

    实现就蛮简单了。完成指定的功能即可。

    注意,包括一些用到的头文件。

    比如printk,errno,EINVAL,get_fs_byte.

    附记

    如果你在实验过程中感到很苦恼,不知道什么该写什么,那就去看看linux中哪些系统调用是如何实现的?

    在此举出几个有帮助的。

    open, 和文件相关,涉及到了get_fs_byte

    close 简单 明确 知道怎么写入口

    syst.c 头文件该包含哪些

    以及一些起到辅助作用的代码,用了老久时间琢磨,找了一堆方法,最后搞定的。

    (整体项目扔github上了,但是老是登不上,麻烦)

    将测试脚本 挂载到linux0.11中(在files文件夹中)

    #########################################################################
    # File Name:    syscall.sh
    # Author:       rebelOverWaist
    #########################################################################
    #!/bin/bash
    make clean && make all
    cd ..
    sudo ./mount-hdc
    cd linux-0.11
    cp iam.c whoami.c ../hdc/usr/root
    cp testlab2.c testlab2.sh ../hdc/usr/root
    cd ..
    sudo umount hdc
    ./run
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    测试程序(防止没有files)

    /*
     * Compile: "gcc testlab2.c"
     * Run: "./a.out"
     */
    
    #include 
    #include 
    #include 
    #include 
    #include 
    #define __LIBRARY__
    #include 
    
    _syscall2(int, whoami,char*,name,unsigned int,size);
    _syscall1(int, iam, const char*, name);
    
    #define MAX_NAME_LEN        23
    #define NAMEBUF_SIZE        (MAX_NAME_LEN + 1)
    /* truncate a long name to SHORT_NAME_LEN for display */
    #define SHORT_NAME_LEN      (MAX_NAME_LEN + 2)
    
    /*           name               score */
    #define TEST_CASE { \
        {"x",                           10,  1, NAMEBUF_SIZE,  1},\
        {"sunner",                      10,  6, NAMEBUF_SIZE,  6},\
        {"Twenty-three characters",      5, 23, NAMEBUF_SIZE, 23},\
        {"123456789009876543211234",     5, -1, 0,            -1},\
        {"abcdefghijklmnopqrstuvwxyz",   5, -1, 0,            -1},\
        {"Linus Torvalds",               5, 14, NAMEBUF_SIZE, 14},\
        {"",                             5,  0, NAMEBUF_SIZE,  0},\
        {"whoami(0xbalabala, 10)",       5, 22,           10, -1},\
        {NULL, 0, 0, 0, 0}  /* End of cases */ \
    }
    /*改动一:增加size,和rval2*/
    
    int test(const char* name, int max_score, int expected_rval1, int size, int expected_rval2);
    void print_message(const char* msgfmt, const char* name);
    
    struct test_case 
    {
        char *name;
        int score;
        int rval1;  /* return value of iam() */
         /*改动2:增加size,和rval2定义*/
        int size;   /*Patch for whoami,2009.11.2*/
        int rval2;  /* return value of whoami() */
    };
    
    int main(void)
    {
        struct test_case cases[] = TEST_CASE;
    
        int total_score=0, i=0;
    
        while (cases[i].score != 0)
        {
            int score;
    
            printf("Test case %d:", i+1);
    
             /*改动3:增加size,和rval2的参数阿*/
            score = test( cases[i].name, 
                          cases[i].score, 
                          cases[i].rval1,
                          cases[i].size,
                          cases[i].rval2 );
    
            total_score += score;
            i++;
        }
    
        printf("Final result: %d%%\n", total_score);
        return 0;
    
    }
     /*改动4:增加size,和rval2的声明*/
    int test(const char* name, int max_score, int expected_rval1, int size, int expected_rval2)
    {
        int rval;
        int len;
        char * gotname;
        int score=-1;
    
        assert(name != NULL);
    
        print_message("name = \"%s\", length = %d...", name);
    
        /*Test iam()*/
        len = strlen(name);
        rval = iam(name);
        /* printf("Return value = %d\n", rval);*/
     
    /*改动5:增加的expected_rval1*/
        if (rval == expected_rval1)
        {
            if (rval == -1 && errno == EINVAL) /*The system call can detect bad name*/
            {
                /* print_message("Long name, %s(%d), detected.\n", name);*/
                printf("PASS\n");
                score = max_score;
            }
            else if (rval == -1 && errno != EINVAL)
            {
                printf("\nERROR iam(): Bad errno %d. It should be %d(EINVAL).\n", errno, EINVAL);
                score = 0;
            }
            /* iam() is good. Test whoami() next. */
        }
        else
        {
            printf("\nERROR iam(): Return value is %d. It should be %d.\n", rval, expected_rval1);
            score = 0;
        }
    
        if (score != -1) 
            return score;
    
        /*Test whoami()*/
        gotname = (char*)malloc(len+1);
        if (gotname == NULL)
            exit(-1);
    
        memset(gotname, 0, len+1);
    
        /* printf("Get: buffer length = %d.\n", len+1); */
    
        rval = whoami(gotname, size);
        /* printf("Return value = %d\n", rval); */
    
    /*改动6:增加的expected_rval2*/
    /*改动++:比较多 ,但还是顺序的改改*/
    
        if(rval == expected_rval2)
        {   
            if(rval == -1)
            {
                printf("PASS\n");
                score = max_score;
            }       
            else 
            {
                if (strcmp(gotname, name) == 0)
                {
                    /* print_message("Great! We got %s(%d) finally!\n", gotname); */
                    printf("PASS\n");
                    score = max_score;
                }
                else
                {
                    print_message("\nERROR whoami(): we got %s(%d). ", gotname);
                    print_message("It should be %s(%d).\n", name);
                    score = 0;
                }
            }
        }
        else if (rval == -1)
        {
            printf("\nERROR whoami(): Return value is -1 and errno is %d. Why?\n", errno);
            score = 0;
        }
        else 
        {
            printf("\nERROR whoami(): Return value should be %d, not %d.\n", expected_rval2, rval);
            score = 0;
        }
    
        free(gotname);
        assert(score != -1);
    
        return score;
    }
    
    void print_message(const char* msgfmt, const char* name)
    {
        char short_name[SHORT_NAME_LEN + 4] = {0};
        int len;
        
        len = strlen(name);
    
        if (len == 0)
        {
            strcpy(short_name, "NULL");
        }
        else if (len <= SHORT_NAME_LEN)
        {
            strcpy(short_name, name);
        }
        else
        {
            memset(short_name, '.', SHORT_NAME_LEN+3);
            memcpy(short_name, name, SHORT_NAME_LEN);
        }
        
        printf(msgfmt, short_name, len);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    #/bin/sh
    
    string1="Sunner"
    string2="Richard Stallman"
    string3="This is a very very long string!"
    
    score1=10
    score2=10
    score3=10
    
    expected1="Sunner"
    expected2="Richard Stallman"
    expected3="Richard Stallman"
    
    echo Testing string:$string1
    ./iam "$string1"
    result=`./whoami`
    if [ "$result" = "$expected1" ]; then
    	echo PASS.
    else
    	score1=0
    	echo FAILED.
    fi
    score=$score1
    
    echo Testing string:$string2
    ./iam "$string2"
    result=`./whoami`
    if [ "$result" = "$expected2" ]; then
    	echo PASS.
    else
    	score2=0
    	echo FAILED.
    fi
    score=$score+$score2
    
    echo Testing string:$string3
    ./iam "$string3"
    result=`./whoami`
    echo "$result"
    if [ "$result" = "$expected3" ]; then
    	echo PASS.
    else
    	score3=0
    	echo FAILED.
    fi
    score=$score+$score3
    
    let "totalscore=$score"
    echo Score: $score = $totalscore%
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    /* ************************************************************************
    > File Name:     whoami.c
    > Author:        rebelOverWaist
    > Created Time:  2022年11月05日 星期六 18时30分35秒
    > Description:  
     ************************************************************************/
    #define __LIBRARY__
    #include 
    #include 
    #include 
    
    _syscall2(int, whoami, char*, name, unsigned int, size)
    #define SIZE 23
    int main (void) {
        char name[SIZE + 1];
        int res;
        res = whoami(name, SIZE+1);
        if(res == -1) {
            errno = EINVAL;
         } else {
            printf("%s\n", name);
         }
        return res;
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    /* ************************************************************************
    > File Name:     iam.c
    > Author:        rebelOverWaist
    > Description:   
     ************************************************************************/
    #define __LIBRARY__
    #include 
    #include 
    
    _syscall1(int, iam, const char*, name)
    
    #define NAMELEN 100
    
    char name[NAMELEN];
    
    int main (int argc, char *argv[]) {
        int res;
        int namelen = 0;
        if(2 <= argc) {
            while((name[namelen] = argv[1][namelen]) != '\0')
                namelen++;
            printf("iam.c: %s, %d\n", name, namelen);
            res = iam(name);
            if(res == -1) 
                errno = EINVAL;
            return res;
          }
         return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    kernel中的makefile代码

    #
    # Makefile for the FREAX-kernel.
    #
    # Note! Dependencies are done automagically by 'make dep', which also
    # removes any old dependencies. DON'T put your own dependencies here
    # unless it's something special (ie not a .c file).
    #
    
    AR	=ar
    AS	=as --32
    LD	=ld
    LDFLAGS	=-m elf_i386 -x
    CC	=gcc-3.4 -march=i386
    CFLAGS	=-m32 -g -Wall -O -fstrength-reduce -fomit-frame-pointer \
    	-finline-functions -nostdinc -I../include
    CPP	=gcc-3.4 -E -nostdinc -I../include
    
    .c.s:
    	$(CC) $(CFLAGS) \
    	-S -o $*.s $<
    .s.o:
    	$(AS) -o $*.o $<
    .c.o:
    	$(CC) $(CFLAGS) \
    	-c -o $*.o $<
    
    OBJS  = sched.o system_call.o traps.o asm.o fork.o \
    	panic.o printk.o vsprintf.o sys.o exit.o \
    	signal.o mktime.o who.o
    
    kernel.o: $(OBJS)
    	$(LD) -m elf_i386 -r -o kernel.o $(OBJS)
    	sync
    
    clean:
    	rm -f core *.o *.a tmp_make keyboard.s
    	for i in *.c;do rm -f `basename $$i .c`.s;done
    	(cd chr_drv; make clean)
    	(cd blk_drv; make clean)
    	(cd math; make clean)
    
    dep:
    	sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
    	(for i in *.c;do echo -n `echo $$i | sed 's,\.c,\.s,'`" "; \
    		$(CPP) -M $$i;done) >> tmp_make
    	cp tmp_make Makefile
    	(cd chr_drv; make dep)
    	(cd blk_drv; make dep)
    
    ### Dependencies:
    who.s who.o: who.c ../include/linux/kernel.h ../include/unistd.h \
    	../include/errno.h
    exit.s exit.o: exit.c ../include/errno.h ../include/signal.h \
      ../include/sys/types.h ../include/sys/wait.h ../include/linux/sched.h \
      ../include/linux/head.h ../include/linux/fs.h ../include/linux/mm.h \
      ../include/linux/kernel.h ../include/linux/tty.h ../include/termios.h \
      ../include/asm/segment.h
    fork.s fork.o: fork.c ../include/errno.h ../include/linux/sched.h \
      ../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
      ../include/linux/mm.h ../include/signal.h ../include/linux/kernel.h \
      ../include/asm/segment.h ../include/asm/system.h
    mktime.s mktime.o: mktime.c ../include/time.h
    panic.s panic.o: panic.c ../include/linux/kernel.h ../include/linux/sched.h \
      ../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
      ../include/linux/mm.h ../include/signal.h
    printk.s printk.o: printk.c ../include/stdarg.h ../include/stddef.h \
      ../include/linux/kernel.h
    sched.s sched.o: sched.c ../include/linux/sched.h ../include/linux/head.h \
      ../include/linux/fs.h ../include/sys/types.h ../include/linux/mm.h \
      ../include/signal.h ../include/linux/kernel.h ../include/linux/sys.h \
      ../include/linux/fdreg.h ../include/asm/system.h ../include/asm/io.h \
      ../include/asm/segment.h
    signal.s signal.o: signal.c ../include/linux/sched.h ../include/linux/head.h \
      ../include/linux/fs.h ../include/sys/types.h ../include/linux/mm.h \
      ../include/signal.h ../include/linux/kernel.h ../include/asm/segment.h
    sys.s sys.o: sys.c ../include/errno.h ../include/linux/sched.h \
      ../include/linux/head.h ../include/linux/fs.h ../include/sys/types.h \
      ../include/linux/mm.h ../include/signal.h ../include/linux/tty.h \
      ../include/termios.h ../include/linux/kernel.h ../include/asm/segment.h \
      ../include/sys/times.h ../include/sys/utsname.h
    traps.s traps.o: traps.c ../include/string.h ../include/linux/head.h \
      ../include/linux/sched.h ../include/linux/fs.h ../include/sys/types.h \
      ../include/linux/mm.h ../include/signal.h ../include/linux/kernel.h \
      ../include/asm/system.h ../include/asm/segment.h ../include/asm/io.h
    vsprintf.s vsprintf.o: vsprintf.c ../include/stdarg.h ../include/string.h
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86

    仓库地址
    跟实验一的代码放一块了

  • 相关阅读:
    appium---如何判断原生页面和H5页面
    计算之魂(吴军)1.3笔记,Datawhale组队学习Task02
    第三章:存储系统
    学习日记(单元测试、反射、注解、动态代理)
    8-12外部排序
    第六章 Java newCachedThreadPool 示例
    SQL中WITH RECURSIVE的用法
    非人脸场景AE模块调试方法及其合理性分析
    【C语言】青蛙跳台阶 —— 详解
    有此秘籍,TIF图片转Excel表格不再难
  • 原文地址:https://blog.csdn.net/SDDHDY/article/details/127711483