Coder Social home page Coder Social logo

oslab's People

Contributors

githubhahaha avatar

Watchers

James Cloos avatar

oslab's Issues

Lab1

bootsect.s

linux 0.11的bootsect.s首先由BIOS读到内存的0x7c00处,bootsect模块开始执行后,会将自己移动到0x90000处。之后bootsect模块会将setup模块读入内存0x90200处,system模块则被读入到0x10000处。

执行权交由setup模块之后,bootsect就失去作用了,setup模块将system模块移动到内存的开始处,即0x00处。

关于上述加电启动的描述,图示非常清晰

关于为什么代码要移来移去,这里面有很多历史遗留问题。

1981年8月,IBM公司最早的个人电脑IBM PC 5150上市,就用了8088这个芯片。
当时,搭配的操作系统是86-DOS。这个操作系统需要的内存最少是32KB。我们知道,内存地址从0x0000开始编号,32KB的内存就是0x0000~0x7FFF。
8088芯片本身需要占用0x0000~0x03FF,用来保存各种中断处理程序的储存位置。(主引导记录本身就是中断信号INT 19h的处理程序。)所以,内存只剩下0x0400~0x7FFF可以使用。
为了把尽量多的连续内存留给操作系统,主引导记录就被放到了内存地址的尾部。由于一个扇区是512字节,主引导记录本身也会产生数据,需要另外留出512字节保存。所以,它的预留位置就变成了:
0x7FFF – 512 – 512 = 0x7C00
0x7C00就是这样来的。
计算机启动后,32KB内存的使用情况如下。
+——————— 0x0
| Interrupts vectors
+——————— 0x400
| BIOS data area
+——————— 0x5??
| OS load area
+——————— 0x7C00
| Boot sector
+——————— 0x7E00
| Boot data/stack
+——————— 0x7FFF
| (not used)
+——————— (…)

在此之后,这个传统可能沿袭了下来,所以1991年的时候,bootsect还是要首先被读到0x7c00处。

而关于为什么system模块不从0开始的问题,是由于在setup模块在获取硬件信息时,需要用到BIOS的中断来获取硬件参数。当BIOS初始化时会在物理内存的开始出放置一个大小为1KB大小的中断向量表。因此在使用完此中断向量表之前,system模块只能先找个地方暂时存一下。

Lab2

系统调用

系统调用过程:

  • 把系统调用的编号存入eax寄存器
  • 把函数参数存入其它通用寄存器
  • 触发0x80号中断(int 0x80)

include/unistd.h中定义了系统调用的宏,如

#define __NR_close    6

可以在unistd.h中添加新的系统调用的宏,并且指定编号。

kernel/system_call.s中,定义了系统调用的总数nr_system_calls,需要修改。其中的 _system_call函数中有一句call sys_call_table(,%eax,4),根据汇编寻址方法实际应为
call sys_call_table + 4 * %eax # 其中eax中放的是系统调用号,即__NR_xxxxxx
即从sys_call_table中找出相应的系统调用。

sys_call_table定义在include/linux/sys.h中,它包含函数定义和函数数组。

makefile文件的用法需要学习。

定义好的系统调用需要自己实现,这里的who.ckernel中实现。系统调用时,内核态在获取用户态数据时需要使用get_fs_byte(),发送数据时使用put_fs_byte()

在应用程序中要有

#define __LIBRARY__               /* 有它,_syscall1等才有效。详见unistd.h */
#include <unistd.h>                /* 有它,编译器才能获知自定义的系统调用的编号 */
/* iam()在用户空间的接口函数 */
_syscall1(int, iam, const char*, name);        
 /* whoami()在用户空间的接口函数 */
_syscall2(int, whoami,char*,name,unsigned int,size);   

这样应用程序的main函数才能调用系统调用,如下:

_syscall1(int,iam,const char*,name)
 
int main(int argc,char* argv[])
{
    int n;
    n=iam(argv[1]);
    return n;
}

C语言中,main函数的参数argc表示传递给main函数的命令行参数的个数,argv数组存放了传递的参数,其中0号元素存放的是程序的路径名,如:

~/Documents$ ./a.out 123
参数个数2
0号参数为./a.out
1号参数为123

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.