一个内核的helloworld

动手编写一个可以用GRUB来引导的简单x86内核,该内核会在屏幕上打印一条信息后挂起
X86机器是怎样启动的?

在我们思考怎样写一个内核之前,让我们先看一下x86机器从启动到把控制权交给内核的过程是怎样的:

x86 CPU在机器启动之后就会从地址 [0xFFFFFFF0]处开始执行,这个地址就是在32位寻址空间中的最后16个字节处,这里存放了一条跳转指令,会跳转到内存中BIOS代码起始处。

接着,cpu就开始开始执行BIOS代码块了,BIOS首先会在我们配置好的启动设备序列中,通过检查一个特定的魔数,找到第一个可以引导的设备。

一旦BIOS找到一个可以引导的设备后,它就会把该设备第一个扇区的代码复制到物理内存的[0x7c00]的位置,然后跳转到这个地址开始执行这一段代码,我们习惯把这一段代码叫作bootloader。

Bootloader会将内核代码加载到物理内存[0x100000]的位置,[0x100000]这个地址是所有x86机器宏内核代码的起始地址

项目代码 https://github.com/killinux/mkernel

下载qemu,模拟器http://qemu.weilnetz.de/w32/qemu-20130616-w32.exe
安装后使用
E:\Program Files (x86)\qemu>qemu-system-i386.exe
代码如下
kernel.asm

view plaincopy to clipboardprint?
    
bits 32
section .text
;multiboot spec
align 4
dd 0x1BADB002 ;magic
dd 0x00 ;flags
dd - (0x1BADB002 + 0x00) ;checksum. m+f+c should be zero

global start
extern kmain ;this is defined in the c file

start:
cli ;block interrupts
call kmain
hlt ;halt the CPU
cli是关中断,防止有些硬件中断对程序的干扰
sti是开中断,允许硬件中断

kernel.c

view plaincopy to clipboardprint?
void kmain(void)
{
char *str = "my first kernel";
//video memory begins at address 0xb8000
char *vidptr = (char*)0xb8000;
unsigned int i = 0;
unsigned int j = 0;

//this loops clears the screen
//there are 25 lines each of 80 columns; each element takes 2 bytes
while(j < 80 * 25 * 2) {
//blank character
vidptr[j] = ' ';
//attribute-byte
vidptr[j+1] = 0x07;
j = j + 2;
}

j = 0;

//this loop write the string to video memory
while(str[j] != '\0') {
//the character's ascii
vidptr[i] = str[j];
//attribute-byte: give character black bg and-light grey fg
vidptr[i+1] = 0x07;
++j;
i = i + 2;
}
return;
}

link.ld
OUTPUT_FORMAT(elf32-i386)  
ENTRY(start)
SECTIONS
{
. = 0x100000;
.text : { *(.text) }
.data : { *(.data) }
.bss : { *(.bss) }
}

nasm -f elf32 kernel.asm -o kasm.o
gcc -m32 -c kernel.c -o kc.o
ld -m elf_i386 -T link.ld -o kernel kasm.o kc.o
sz kernel

E:\Program Files (x86)\qemu>qemu-system-i386.exe -kernel kernel

参考

http://www.geekfan.net/8663/
Linux内核学习 篇-00:构建学习环境并运行一个HelloWorld模块 Linux内核学习”系列博文致力为每一位有兴趣学习Linux内核的同志排除学习道路上的障碍,给大家提供最好的帮助,补足市面上各种材料书籍解释不周、报错多等问题。本系列博文使用的系统版本和编译器版本等均在《Linux内核学习 篇-00》中有详细介绍。 阅读详情

相关推荐

Linux内核开发(一)-----动手实现第一个helloworld程序

首先需要配有gcc的Linux环境,可以执行make对LinuxC代码进行编译。 1. 首先创建 /tmp目录,用来保存源代码C文件。 2.创建hello.c #ifndef __KERNEL__ #define __KERNEL__ #endif #ifndef MODULE #define MODULE #endif #incl

小宇宙的专栏 2510

编写最简单的内核:HelloWorld

内核是操作系统最核心的内容,主要提供硬件抽象层、磁盘及文件系统控制、多任务等功能,由于其涉及非常广泛的计算机知识,很少被人们所熟悉,因而披上了一层神秘的面纱。 本文将从零开始实现一个最简单的内核,其可以通过x86系统的GRUB引导启动,并向屏幕输出“Hello World!“字符串。该内核代码非常简短,并且在本人的Debian 7系统中可以正常运行。 x86机器启动过程 在具体实

萌萌的It人 www.itmmd.com 1702

Ubuntu下内核编程之第一个模块helloworld(附源码)

图文并茂的描述了Ubuntu下内核编程之第一个模块helloworld的编写全过程,另附有代码。

Linux内核编程入门实例--Hello world

Linux 内核模块编程 Linux 内核模块编程是一个很重要的知识点。尤其是编写底层驱动程序时,一定会涉及到它。内核模块编程也是 Tiger 哥学习 Linux 时第一节课所接触的知识。由此可以看出它的 important, 也可以看出其实它很 easy 。 一前言: 1. 什么是内核模块 1> 内核模块是具有独立功能的程序。它可以被单独编译,但是不能单独运行,它的运...

Kunaly 1969

基于ADS的低噪声放大电路设计

1. 低噪声放大器设计理论基础 1.1 低噪声放大器在通信系统中的作用 低噪声放大器的主要作用是放大天线从空中接收到的微弱信号,减小噪声干扰,以供系统解调出所需的信息数据。当今,人们对于各种无线通信工具的要求越来越高,如功率辐射要小、作用距离要远、覆盖范围要广等,这就对系统的接收灵敏度提出了更高的要求,系统接收灵敏度的计算公式为: Smin⁡=−144(dBmHz)+NF+10lg⁡BW(MHz)+SN(dB) {S_{\min }} = - 144\left( {\frac{{{\rm{dBm}}}}{

ASH_GUARDIAN的博客 4万+

Ubuntu20.04安装Eigen3.3.7、模板类Sophus和Ceres

Sophus的使用必须依赖3.3以上的Eigen版本。如果版本太低,Sophus库将无法安装使用。

qq_62964142的博客 3422

Linux内核模块编程入门——Hello World

在学习C/C++语言,入门的程序都是输出hello world,那么学习内核模块编程,也从输出Hello World开始。 首先,从最简单模块开始。 1)编写程序hello-1.c #include #include int init_module(void) { printk(KERN_INFO "Hello World 1.\n"); return 0; } void

Second的专栏 2963

WebVTT中的文本轨道(Text Tracks,TT)到底是什么鬼?

WebVTT,全称是The Web Video Text Tracks Format,意思是网络视频文本轨道格式。那么到底什么是文本轨道(Text Tracks)呢?这篇文章希望一探究竟。

码农1479的博客 1985

内核编程五:从hello world开始

这是一个简单的 Linux 内核模块(LKM)示例,模块加载时打印 “Hello, world”,卸载时打印 “Goodbye curl world”。通过 module_init 和 module_exit 宏,分别指定了模块加载和卸载时的函数。

zyqash的博客 1251

Intel Realsense windows安装与入门

realsense400系列介绍: https://www.intelrealsense.com/stereo-depth/?utm_source=intelcom_website&utm_medium=button&utm_campaign=day-to-day&utm_content=D400_learn-more_button realsense 435i介绍: ...

hanshuning的专栏 1万+

【AUTOSAR-E2E】-2.1-配置E2E:基于E2EPW配置一个RX接收的Signal Group(使用E2E Profile 2)

《共13页精讲》:此法也适用于E2E Profile 4/5/6/7/11/22 目录 1 检查CAN Matrix Arxml/DBC是否满足E2E需求 2 在DaVinci Developer中为Port添加E2E保护 3 在DaVinci Configurator settings设置 4 如何使用应用层的E2E保护 5 结尾 <--返回「Autosar_BSW高阶配置」总目录--> <--返回「Autosar_BSW高阶配置」专栏主页--> <--

「汽车电子助手」的博客 4417

Linux内核编程Hello World

_init和__initdata告诉内核这些函数和数据只在初始化期间使用,一旦初始化完成,它们就不再需要,从而可以释放掉它们占用的内存,从而提高系统的性能和效率。将函数helloworld_init注册为当前内核模块的初始化函数,当这个内核模块被加载到系统中时,内核会自动调用这个函数来完成其初始化工作。__exit告诉内核这些函数只在模块卸载时使用,一旦模块被卸载,它们就不再需要,从而可以释放掉它们占用的内存,从而提高系统的性能和效率。是一个 Linux 内核模块中的宏,用于声明模块的许可证信息。

qq_53928256的博客 1318

IEC 61400-1:2019 附录 C 湍流模型全面解读

IEC 61400-1:2019 附录 C 全面解读

weixin_46713695的博客 471

一个内核模块的helloworld

helloworld.c [code="java"] #include #include static int __init helloworld_init(void) { printk("""helloworld!\n"); return 0; } static void __exit helloworld_exit(void) { printk...

走在左边 202

保姆级教程:ABAP 通过 HTTP POST 调用 OData 服务创建业务数据的具体例子

笔者之前的文章发布之后,有朋友在评论区留言,询问 ABAP 除了 Web Service 之外,是否也支持 HTTP 呢?ABAP 这么强大的语言,支持 HTTP 当然不在话下。网上有很多在 ABAP 系统基于 CL_HTTP_CLIENT 工具类,通过 HTTP 协议和第三方系统交互的代码例子。本文介绍笔者项目中一个实际例子,实现的是在 ABAP 系统 A 通过 HTTP 调用 OData 服务,在 ABAP 系统 B 创建业务数据的需求。下面我们按照这个套路来一步步实现。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 697

lammps教程:聚合物压缩,避免“bond atoms missing”

如果使用ms建模,聚合物的链会伸出到盒子外面,在导出data文件后,盒子外面的原子被周期性算法折叠进盒子对面,这就造成了边界附近的bond原子可能被分布到了盒子的两侧。并且,这个data文件不能使用npt系综进行压缩,npt系综必须使用周期性边界,在压缩时,bond原子同样会移动到对面的边界。所以,最好的解决办法是使用一个反射墙墙进行压缩,设置一个反射墙墙既可以实现压缩效果,也可以组织原子跨越box边界移动到对面。解决这个问题的原则只有一个:导出data时确保所有的bond原子没有跨越边界。

lammps_jiayou的博客 3819

Ubuntu下内核编程之第一个模块helloworld

模块是驱动开发的必经之路,这也是我们在前边要构建内核源码树的目的所在。因为模块属于kernel编程了,和用户空间的c语言变成不同。他要依附于内核源码树的存在而存在,下面就开始我们的第一个模块的编写吧。       Ubuntu下内核编程之第一个模块——我的叫jun_module。随你怎么起名。以下是建立的全过程:       1、首先肯定是编写模块的源代码,和Makefile。我们建立一个专用

dreambegin 的 优快云 4101

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

一个HelloWorld的简单内核模块例子

注:编译驱动的条件:1、交叉工具链2、内核源码包(驱动的版本和内核源码的版本一致)3、源码包需要配置编译过 注:如需要帮助,可以参考内核源码中modules.txt文件(内核源码树/Documentation/kbuild/modules.txt) 编写模块的注意事项: 1.模块运行需要初始化及退出。 module_init(test_init); module_exit(test_...

weixin_30347009的博客 125

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

第一个helloworld内核模块

第一个helloworld内核模块 1 源码: first_mod.c /* first_mod.c My first kernel module. */#include <linux/module.h> /* Needed by all modules */ #include <linux/kernel.h> /* Needed for KERN_INFO*/ MODULE_LICENSE("D

混沌的博客 616

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

【转载】Ubuntu下内核编程之第一个模块helloworld

【转载】Ubuntu下内核编程之第一个模块helloworld

GengLUT 1450

只有一个内核跑linux,第一步,用qemu启动linux内核,从跑个Helloworld开始

老生长谈的内容了,就是自己编译内核,然后制作initramfs,在用qemu跑起来。不过在这之前先跑个helloworld玩玩。顺便我在学校写博客的笔记本系统是ubuntu16.04,在实习单位玩的时候用的系统是centos7,两个不同的地方我会尽量说明,当然有些地方我自己也不是很清楚就是了。编译内核#  建一个目录$  mkdir build# 首先當然是去下一個linux內核,地址, ...

weixin_36166752的博客 687

编译第一个内核模块helloworld

【4】开始make # make 输出类似以下消息: make -C /lib/modules/2.6.28-11-generic/build M=/home/wk/hello modules make[1]: 正在进入目录 `/usr/src/linux-headers-2.6.28-11-generic' Building modules, stage 2. MODPOST 1 m

Miles的专栏 743

MyOS(一):用Java做一个最小的helloworld操作系统内核

将这段Java代码运行一下会生成一个system.img文件,接着利用virtualbox创建一个虚拟机,设置它为磁盘启动,并在配置中,将代码生成的system.img当做虚拟磁盘插入虚拟机 import java.io.DataOutputStream; import java.io.FileOutputStream; import java.util.ArrayLis...

hxxjxw的博客 695
上一篇: qemu的简单使用
下一篇: 关于wordpress的安装
linux内核控
博客等级 码龄19年 41粉丝 638原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值