《从0开始写一个微内核操作系统》1-构建GN-base

GN-base

https://github.com/jingjin666/GN-base.git

BUILD.gn

BUILD.gn是GN构建的核心配置文件,GN-base中只用到了一些基本语法,其他高级语法可参考goolge官方文档https://gn.googlesource.com/gn/进行扩展

GN最小系统

  • .gn
  • BUILD.gn
  • build/config/BUILDCONFIG.gn
  • build/toolchain/BUILD.gn

.gn

buildconfig = "//build/config/BUILDCONFIG.gn"

BUILD.gn

executable

executable为最后输出的可执行文件,依赖于os_modules,一个系统中可以根据需要生成多个可执行文件
os_config为生成可执行文件的配置文件,也就是ldflags

gcc下的ldflags参考https://sourceware.org/binutils/docs-2.38/ld/Options.html#Options

os_modules模块依赖于os下的BUILD.gn

import("//build/config/compiler.gni")

group("os_modules") {
    deps = [ 
        "//os",
    ]
}

config("os_config") {
    defines = []
    ld_script = rebase_path("//os/linker.lds")
    ldflags = [
        "-g",
        "-T",
        "$ld_script"
    ]
}

executable("os") {
    configs = []
    configs += [ ":os_config" ]

    sources = []

    deps = [
        ":os_modules",
    ]
}

target = "$root_out_dir/os.elf"
target_elf = "$root_out_dir/image/os.elf"
target_bin = "$root_out_dir/image/os.bin"
target_hex = "$root_out_dir/image/os.hex"
target_dump = "$root_out_dir/image/os.dump"

copy("copy_os") {
    deps = [ ":os" ]
    sources = [ "$target" ]
    outputs = [ "$target_elf" ]
}

action("build_image") {
    deps = [
        ":copy_os",
    ]

    script = "//build/py_script/elf_format.py"
    sources = [
        "$target_elf",
    ]
    
    outputs = [
        "$target_bin",
        "$target_hex",
        "$target_dump",
    ]

    args = [
        "--format_tool",
        "$crossdev",
        "--elf",
        rebase_path("$target_elf"),
        "--bin",
        rebase_path("$target_bin"),
        "--hex",
        rebase_path("$target_hex"),
        "--dump",
        rebase_path("$target_dump"),
        "--dir",
        rebase_path("$root_out_dir/image"),
        "--flag",
        "bd",
    ]
}

copy

copy为拷贝动作,定义在build/toolchain/BUILD.gn中

action

当生成可执行文件后,你还需要一些后续操作,这个时候你可以定义action,actoin实际上是通过python脚本来实现自定义操作

build/config/BUILDCONFIG.gn

配置GN使用的编译器,配置toolchain变量来配置使用gcc或者clang等编译器

toolchain = "gcc"
#toolchain = "clang"

target_toolchain = "//build/toolchain:${toolchain}"

set_default_toolchain(target_toolchain)

build/toolchain/BUILD.gn

配置gcc或者clang等其他编译的具体编译选项

gcc

gcc变量定义在build/config/compiler.gni头文件中

import("//build/config/compiler.gni")
toolchain("gcc") {
    tool("asm") {
        depfile = "{{output}}.d"
        command = "${crossdev}gcc -MMD -MF $depfile {{defines}} {{include_dirs}} {{asmflags}} -c {{source}} -o {{output}}"
        depsformat = "gcc"
        description = "ASM {{output}}"
        outputs =
            [ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o" ]
    }

    tool("cc") {
        depfile = "{{output}}.d"
        command = "${crossdev}gcc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} -c {{source}} -o {{output}}"
        depsformat = "gcc"
        description = "CC {{output}}"
        outputs =
            [ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o" ]
    }

    tool("cxx") {
        depfile = "{{output}}.d"
        command = "${crossdev}g++ -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} -c {{source}} -o {{output}}"
        depsformat = "gcc"
        description = "CXX {{output}}"
        outputs =
            [ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o" ]
    }

    tool("link") {
        outfile = "{{target_output_name}}{{output_extension}}"
        rspfile = "$outfile.rsp"
        command = "${crossdev}ld {{ldflags}} -o $outfile --start-group @$rspfile {{solibs}} --end-group {{libs}}"
        description = "LINK $outfile"
        default_output_dir = "{{root_out_dir}}"
        rspfile_content = "{{inputs}}"
        outputs = [ outfile ]
        default_output_extension = ".elf"
    }

    tool("alink") {
        outfile = "{{target_output_name}}{{output_extension}}"
        rspfile = "$outfile.rsp"
        command = "${crossdev}ar cr $outfile @$rspfile"
        description = "AR $outfile"
        default_output_dir = "{{root_out_dir}}"
        rspfile_content = "{{inputs}}"
        outputs = [ outfile ]
        default_output_extension = ".a"
        output_prefix = "lib"
    }

    tool("solink") {
        outfile = "{{target_output_name}}{{output_extension}}"
        rspfile = "$outfile.rsp"
        command = "${crossdev}gcc --shared -fPIC -o $outfile @$rspfile"
        description = "SOLINK $outfile"
        default_output_dir = "{{root_out_dir}}"
        rspfile_content = "{{inputs}}"
        outputs = [ outfile ]
        default_output_extension = ".so"
        output_prefix = "lib"
    }

    tool("stamp") {
        command = "touch {{output}}"
        description = "STAMP {{output}}"
    }

    tool("copy") {
        command = "cp -af {{source}} {{output}}"
        description = "COPY  {{source}} {{output}}"
    }
}

toolchain("clang") {

}

clang

build/config/compiler.gni

gcc

gcc下通用的变量包括:

  • crossdev:是否需要交叉编译
  • defines:宏定义
  • include_dirs:头文件目录
  • asmflags:汇编编译选项
  • cflags:目标编译选项
  • cflags_c:C标准的编译选项
  • cflags_cc:C++标准编译选项

arch_flags定义了所选编译器针对目标硬件的编译选项,包括不限于:

  • arch_cpu
  • arch_c
  • debug
  • cpu
  • optimaztion

不同编译器对应不同cpu架构所支持的arch_flags是不一样的,这里的arch_flags只是gcc对应cpu的flags

gcc支持的flags参考https://gcc.gnu.org/onlinedocs/gcc/Option-Summary.html

arch_cpuflags =  []
arch_cpuflags =  [ "-mcpu=cortex-a53" ]

arch_cflags = []
arch_cflags = [ "-nostdlib",
                "-nostdinc",
                "-fno-builtin",
                "-fno-common",
                "-fno-stack-protector",
                "-fno-strict-overflow",
                "-fno-strict-aliasing" ]

debug_build_flags =  []
debug_build_flags =  [ "-g" ]
debug_build_flags += [ "-Wall",
                       "-Wstrict-prototypes",
                       "-Wshadow",
                       "-Wundef" ]

arch_optimaztion_flags = []

arch_flags  = arch_cpuflags + arch_cflags + debug_build_flags + arch_optimaztion_flags

crossdev = "aarch64-none-elf-"

cflags_c = [ "-std=gnu99" ]
cflags_cc = [ "-std=gnu++17" ]
cflags = arch_flags
asmflags = cflags
asmflags += [ "-D__ASSEMBLY__" ]
defines = [ "GIT_VERSION=" ]

添加新代码到GN-base中

1、新增文件夹os/test

2、修改os/BUILD.gn

添加deps和configs

group("os") {
    deps = []
    deps += [
        "arch",
        "test",
    ]
}

config("kernel") {
    configs = []
    configs += [
        "arch:kernel",
        "test:kernel",
    ]
}

3、新增源文件和头文件os/test/test.c,os/test/include/test.h

4、新增os/test/BUILD.gn

如果需要把当前头文件目录导出到系统头文件目录,需要在config-kernel中加入include_dirs
如果当前源文件需要导入kernel系统头文件目录,需要在configs中加入//build/config:kernel

module_name = get_path_info(rebase_path("."), "name")
source_set(module_name) {
    sources = [
        "test.c",
    ]

  	# 导入的配置目录
    configs = [
        "//build/config:kernel",
    ]
}

# 导出的头文件
config("kernel") {
    include_dirs =  [ "./include" ]
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 用Linux内核作为操作系统的基础,可以实现一个新的操作系统。在这个过程中,需要深入了解Linux内核的各个方面,包括内存管理、进程管理、文件系统、设备驱动程序等。 需要使用C语言编内核代码,并且需要了解一些汇编语言来实现一些底层的功能。同时,还需要了解操作系统的整体架构和设计原则,以确保操作系统的可靠性、安全性和效率。 这是一个非常复杂的任务,需要经验丰富的程序员和计算机科学家的共同努力才能实现。即使使用了Linux内核,也需要进行大量的开发和测试工作,才能构建一个完整、稳定、可靠的操作系统。 ### 回答2: 要用 Linux 内核一个操作系统,首先需要了解操作系统的基本概念和功能,并熟悉 Linux 内核的架构和编程接口。接下来,可以按照以下步骤进行: 1. 确定操作系统的需求和目标:思考要开发的操作系统的用途、目标用户群体和基本功能等方面的需求。 2. 下载和安装适当的开发工具:根据所选操作系统开发的需求,从 Linux 官方网站或其他可靠资源下载合适版本的 Linux 内核,并安装在开发机上。 3. 初步配置和编译内核:根据实际需求,进行初步的内核配置,确定需要的功能模块。然后,使用内核配置工具进行配置保存,接着开始编译内核源码。 4. 针对具体应用进行内核定制:根据所需操作系统的功能需求,可以对内核进行二次开发和定制,添加或删除相应模块,扩充或精简某些功能。 5. 编系统级驱动程序和服务:根据需求,编特定的设备驱动和系统服务程序。可以利用 Linux 内核提供的接口函数,编驱动程序,控制硬件设备的操作。 6. 进行内核的构建和连接:按照所做的修改和定制,重新编译内核源码,生成适合的内核映像文件。 7. 进行系统的测试和调试:将生成的内核映像文件烧录到目标设备上,进行系统的验证和测试。调试是一个不可或缺的环节,可以通过调试工具和日志信息定位和修复问题。 8. 配置和优化操作系统:根据实际需求,对操作系统进行细致的配置和优化,保证系统的性能和稳定性。 9. 发布和更新操作系统:在进行充分测试和验证之后,将操作系统发布到用户,并及时修复和升级系统中的漏洞和问题。 总之,使用 Linux 内核一个操作系统是一项复杂的任务,需要掌握操作系统和编程技术的知识,并进行详细的计划和设计。同时,要耐心和细心进行开发、测试和调试工作,确保最终的操作系统具备所需的功能和稳定性。 ### 回答3: 使用Linux内核编一个操作系统一个庞大的工程,需要深入了解Linux内核的结构和原理,以及操作系统的设计和实现。 首先,我们需要从Linux内核的源代码开始,这可以从Linux官方网站或其他途径获取。然后,我们需要对内核进行分析和理解,包括内核的启动过程、内核空间和用户空间的切换、设备驱动、进程管理等。 接下来,我们可以根据需求对内核进行定制,可以添加或删除某些功能,设计和实现自己的系统调用,以及其他相关的内核模块。这需要深入了解Linux内核的API和接口,如系统调用接口、文件系统接口等。 然后,我们需要编启动引导程序,将我们的操作系统加载到内存中并启动。 在编操作系统的过程中,需要注意保护内核的安全性和稳定性,处理各种异常和中断,管理和调度进程,实现进程间通信和同步,支持多线程和多CPU,设计并实现内存管理、文件系统、网络协议栈等核心功能。 此外,对于更高级的功能,如图形界面、设备驱动程序、网络系统等,我们需要进一步的学习和研究。 总之,使用Linux内核编一个操作系统一个充满挑战的任务,需要对底层的硬件、操作系统原理和编程技术有深入的了解。通过不断的学习和实践,我们可以逐步掌握这个技能,创建出符合我们需求的定制化操作系统

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值