Linux-0.11 入口函数main.c详解

news2025/2/25 2:01:20

Linux-0.11 入口函数main.c详解

模块简介

main.c大部分代码主要是对内核进行初始化,而main.c开始,就都是c语言编写的内核了。

函数详解

time_init

static void time_init(void)

该函数读取CMOS时钟信息作为系统的开机时间。

	struct tm time;

	do {
		time.tm_sec = CMOS_READ(0);//当前的秒数
		time.tm_min = CMOS_READ(2);//当前分钟值
		time.tm_hour = CMOS_READ(4);//当前小时数
		time.tm_mday = CMOS_READ(7);//当前的天数
		time.tm_mon = CMOS_READ(8);//当前的月份
		time.tm_year = CMOS_READ(9);//当前的年份
	} while (time.tm_sec != CMOS_READ(0));
	BCD_TO_BIN(time.tm_sec); //转换成二进制数值
	BCD_TO_BIN(time.tm_min);
	BCD_TO_BIN(time.tm_hour);
	BCD_TO_BIN(time.tm_mday);
	BCD_TO_BIN(time.tm_mon);
	BCD_TO_BIN(time.tm_year);
	time.tm_mon--;
	startup_time = kernel_mktime(&time);//调用kernel_mktime构建时间,详情参考Linux-0.11 kernel目录mktime.c详解

main

void main(void)	

在head.s中会跳转main函数中进行执行。

if (memory_end > 16*1024*1024)
    memory_end = 16*1024*1024;
if (memory_end > 12*1024*1024) 
    buffer_memory_end = 4*1024*1024;
else if (memory_end > 6*1024*1024)
    buffer_memory_end = 2*1024*1024;
else
    buffer_memory_end = 1*1024*1024;

接下来就是对各个模块进行初始化。其内容在具体的模块都有讲解,这里不再赘述。在这最后,会重新打开中断。

	mem_init(main_memory_start,memory_end);
	trap_init();
	blk_dev_init();
	chr_dev_init();
	tty_init();
	time_init();
	sched_init();
	buffer_init(buffer_memory_end);
	hd_init();
	floppy_init();
	sti();

接下来,将切换到用户态去执行进程0。

	move_to_user_mode();
	if (!fork()) {		/* we count on this going ok */
		init();
	}

在分析move_to_user_mode,我们回顾一下sched_init函数中和进程0相关的部分。

在sched_init函数中设置了进程0的ldt和tss。其中ldt部分的定义如下:

    //ldt
	{ \
        {0,0}, \
        {0x9f,0xc0fa00}, \
		{0x9f,0xc0f200}, \
	}, \

其中代码段为{0x0000009f,0x00c0fa00}, 数据段为{0x0000009f,0x00c0f200}

接下来我们依次分析。

首先是代码段,{0x0000009f,0x00c0fa00}, 翻译成二进制,注意是按照小端序列,如下所示:

63-48:00000000 11000000
47-32:11111010 00000000
31-16:00000000 00000000
15-00:00000000 10011111

按照段描述符的定义,代码段的分析结果如下
:
段基址:00000000 00000000 00000000 00000000
段限长:0x009f * 4k

接下来是数据段,{0x0000009f,0x00c0f200}, 翻译成二进制,注意是按照小端序列,如下所示:

63-48:00000000 11000000
47-32:11110010 00000000
31-16:00000000 00000000
15-00:00000000 10011111

按照段描述符的定义,数据段的分析结果如下

段基址:00000000 00000000 00000000 00000000
段限长:0x009f * 4k

由此可以看出,进程0的代码段和数据段都映射到线性地址为0处。

数据段和代码段唯一不同的是TYPE字段不同,代码段是1010,代表是代码段,其可读可执行。数据段是0010,代表数据段,且可读可写。

因此sched_init为这里切换进程0到用户态执行打下了铺垫。

下面我们就来看move_to_user_mode, 其定义如下:

#define move_to_user_mode() \
__asm__ ("movl %%esp,%%eax\n\t" \
	"pushl $0x17\n\t" \
	"pushl %%eax\n\t" \
	"pushfl\n\t" \
	"pushl $0x0f\n\t" \
	"pushl $1f\n\t" \
	"iret\n" \
	"1:\tmovl $0x17,%%eax\n\t" \
	"movw %%ax,%%ds\n\t" \
	"movw %%ax,%%es\n\t" \
	"movw %%ax,%%fs\n\t" \
	"movw %%ax,%%gs" \
	:::"ax")

看到其中使用了iret指令,因此这里其实是模拟了一个中断的压栈情况。其效果就是在iret返回时,使得ss=0x17,cs=0x0f
在这里插入图片描述

接着通过movw指令,将ds、es、fs、gs都设置为0x17。

通过这一番操作,这些寄存器中的DPL都是3了,也就是用户态了。因此,可以这样总结,move_to_user_mode实际就是将cs/ds/es/fs/gs/ss 都设置为用户态的值。

在这最后,进程0开始fork出进程1, 而自己则进入pause,因此进程0又被称为idle进程。

	if (!fork()) {		/* we count on this going ok */
		init();
	}
	for(;;) pause();

init

void init(void)

init进程是系统中真正的第一个进程。

	int pid,i;
	setup((void *) &drive_info);
	(void) open("/dev/tty0",O_RDWR,0);
	(void) dup(0);
	(void) dup(0);
	printf("%d buffers = %d bytes buffer space\n\r",NR_BUFFERS,
		NR_BUFFERS*BLOCK_SIZE);
	printf("Free mem: %d bytes\n\r",memory_end-main_memory_start);

执行shell程序,加载/etc/rc

	if (!(pid=fork())) {
		close(0);
		if (open("/etc/rc",O_RDONLY,0))
			_exit(1);
		execve("/bin/sh",argv_rc,envp_rc);
		_exit(2);
	}
	if (pid>0)
		while (pid != wait(&i))
			/* nothing */;
	while (1) {
		if ((pid=fork())<0) {
			printf("Fork failed in init\r\n");
			continue;
		}
		if (!pid) {
			close(0);close(1);close(2);
			setsid();
			(void) open("/dev/tty0",O_RDWR,0);
			(void) dup(0);
			(void) dup(0);
			_exit(execve("/bin/sh",argv,envp));
		}
		while (1)
			if (pid == wait(&i))
				break;
		printf("\n\rchild %d died with code %04x\n\r",pid,i);
		sync();
	}
	_exit(0);	/* NOTE! _exit, not exit() */

Q & A

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/582694.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

携手高通,移远通信以全栈式车载产品实力重新定义汽车

5月25日至26日&#xff0c;2023高通汽车技术与合作峰会在苏州成功举办。 移远通信作为高通重要的长期战略合作伙伴&#xff0c;受邀参加此次峰会&#xff0c;并现场展示了支持5G/4G、C-V2X、算力、UWB、Wi-Fi、高精定位等领先技术的多款车规级模组、天线等产品&#xff0c;更有…

Three.js——六、模型对象/材质

模型对象/材质 三维向量 Vector3 与模型位置 该类表示的是一个三维向量&#xff08;3D vector&#xff09;。 一个三维向量表示的是一个有顺序的、三个为一组的数字组合&#xff08;标记为 x、y 和 z&#xff09;&#xff0c; 可被用来表示很多事物&#xff0c;例如&#xff…

Flutter(七)功能型组件

1.导航返回拦截&#xff08;WillPopScope&#xff09; 需求&#xff1a;再按一次退出应用 用户在1秒内点击两次返回按钮时&#xff0c;则退出&#xff1b;如果间隔超过1秒则不退出 import package:flutter/material.dart;class WillPopScopeTestRoute extends StatefulWidget…

建筑行业数字化转型,工程管理系统已成建筑行业转型的利器

建筑工程项目管理的困境 专业工种多、工作环境复杂&#xff0c;工期长&#xff0c;且整体工业化标准化程度较低。 进度难管控、项目沟通协作不畅、项目执行过程不透明、项目成本管控难、项目盈亏情况不清、项目难共享等。 什么是工程项目管理 工程项目管理指的是对工程项目…

茶润童心 以茶明礼

中国是茶的故乡&#xff0c;也是茶文化的发源地&#xff0c;茶文化也是中国文化的一部分。5月27日下午&#xff0c;8位武汉公益小天使来到中茶恩施硒茶全国运营中心开展少儿茶艺活动。 开场的自我介绍&#xff0c;公益小天使逐个进行自我介绍&#xff0c;喊着“好名字”互相加…

软件测试的一些关键点

软件测试的一些关键点 随着互联网的快速发展&#xff0c;软件已经成为了我们生活和工作中不可或缺的一部分。在软件开发过程中&#xff0c;一项重要的工作就是软件测试。软件测试是指对软件产品或系统进行验证和验证的过程。在软件测试中&#xff0c;需要注意以下关键点。 首先…

[转]Github进行fork后如何与原仓库同步

问题场景&#xff1a; 新公司要求所有的代码提交都要先通过自己的库提交到主repo上去&#xff0c;所以先在gitlab网页上fork出一个自己的库&#xff0c;在本地修改完代码后提交到远程自己库上&#xff0c;然后在gitlab网页上发起一个merge request请求&#xff0c;然后等待主r…

面试:webpack常用loader和plugin

Webpack简介 Webpack 是一个用于现代 JavaScript 应用程序的 静态模块打包工具。当 webpack 处理应用程序时&#xff0c;它会在内部从一个或多个入口点构建一个 依赖图(dependency graph)&#xff0c;然后将你项目中所需的每一个模块组合成一个或多个 bundles&#xff0c;它们均…

如何选择专业的低代码开发平台?为企业数字化转型保驾护航

在当今快节奏的商业环境中&#xff0c;软件开发已经成为任何组织的关键方面。然而&#xff0c;由于市场上有无数的软件开发平台&#xff0c;选择合适的平台可能是一项艰巨的任务。对于任何想要创建满足其业务需求的高质量应用程序的组织来说&#xff0c;选择正确的软件开发平台…

英国卡迪夫大学学生使用ChatGPT写论文拿到一等成绩

近日&#xff0c;BBC报道了一则新闻&#xff1a; 卡迪夫大学一名学生在期末考试中使用ChatGPT撰写了一篇论文&#xff0c;并获得了一等成绩&#xff0c;要知道这是英国大学中最高等级的成绩&#xff0c;而他的另一篇论文没有使用ChatGPT&#xff0c;只获得了二等一的成绩。 此…

1.6. 数组

数组是一种数据结构&#xff0c;用于存储相同类型的多个元素。在 Java 中&#xff0c;数组是一个对象&#xff0c;它具有一定数量的连续内存空间。数组中的每个元素都有一个索引&#xff0c;用于访问和操作元素。 1.6.1. 数组的声明与初始化 在 Java 中&#xff0c;可以使用以…

Find My资讯|iOS17将重点改进钱包、Find My、SharePlay和AirPlay等功能

彭博社的马克・古尔曼&#xff08;Mark Gurman&#xff09;在最新一期 Power On 时事通讯中表示&#xff0c;苹果即将推出的 iOS 17 系统将改进 Wallet、Find My、SharePlay 和 AirPlay 等多项功能。 古尔曼在博文中还表示苹果会增强 Find My 的位置服务&#xff0c;同样也没…

前端数据可视化开发平台FlyFish数据源应用教程详解

介绍 飞鱼&#xff08;FlyFish&#xff09;是云智慧开源的一款免费的数据可视化编排平台。通过简易的方式快速创建数据模型&#xff0c;通过拖拉拽的形式&#xff0c;快速生成一套数据可视化解决方案。在飞鱼产品中可以通过直接连接 MySQL 、 Oracle 等数据库直接从数据源中获…

LiangGaRy-学习笔记-Day17

1、磁盘的介绍 自动分区、手工分区、命令工具分区 1.1、磁盘分类 根据介质来区分&#xff1a; 机械硬盘和固态硬盘 通过盘大小&#xff1a; 3.5英寸和2.5英寸 通过接口分类&#xff1a; SAS、SATA、FC scisi 根据功能&#xff1a; 桌面和企业级别 1.2、磁盘类型 HD…

关于【Stable-Diffusion WEBUI】生成全身图:插件解决面部崩坏问题

文章目录 &#xff08;零&#xff09;前言&#xff08;一&#xff09;脸难看的问题&#xff08;1.1&#xff09;面部修复&#xff08;1.2&#xff09;远景脸部问题 &#xff08;二&#xff09;面部修复插件&#xff08;Face Editor&#xff09;&#xff08;2.1&#xff09;模型…

最常见JS加密保护代码的方法

当谈到JavaScript&#xff08;简称JS&#xff09;代码的保护时&#xff0c;加密是一种常见的策略。加密可以帮助保护你的JS代码&#xff0c;防止未经授权的访问、修改和复制。在本文中&#xff0c;我将向你介绍一些常用的js加密保护方法&#xff0c;并提供一些通俗易懂的示例代…

如何有效和快速清理C盘

电脑在运行过程中会产生磁盘碎片&#xff0c;时间一长垃圾文件就会越多。而且我们平常不敢乱清理C盘中的文件&#xff0c;以免因为误删导致系统出现故障&#xff0c;所以垃圾文件才肆意占用系统盘空间。不过我们可以选择系统自带的“磁盘清理”功能“制服”它&#xff0c;给C盘…

(转载)多种群遗传算法的函数优化算法

以下内容大部分来源于《MATLAB智能算法30个案例分析》&#xff0c;仅为学习交流所用。 1 理论基础 1.1 遗传算法早熟问题 遗传算法是一种借鉴生物界自然选择和进化机制发展起来的高度并行、随机、自适应的全局优化概率搜索算法。由于优化时不依赖于梯度&#xff0c;具有很强…

商代数与积代数

商代数 设 R R R使 A < S , ∗ 1 , ∗ 2 , ⋯ , ∗ n > A \left<S, *_1, *_2,\cdots, *_n\right> A⟨S,∗1​,∗2​,⋯,∗n​⟩上的同余关系&#xff0c;则 R R R使 S S S上的等价关系&#xff0c;因此 R R R可诱导出 S S S的一个划分 S / R { [ a ] R ∣ a ∈…

【大数据处理与可视化】七、时间序列分析

【大数据处理与可视化】七、时间序列分析 实验目的实验内容实验步骤一、案例——股票收盘价分析1、读取数据&#xff0c;并转换成DataFrame对象展示2、将“交易日期”一列设置为行索引3、根据数据中“收盘价”一列的数据绘制一张折线图&#xff0c;以了解近些年来收盘价格的趋势…