为了使用unistd.h中的宏,该宏用来进行系统调用,
系统调用是通过0x80进行的,防止使用用户栈空间。
#define __LIBRARY__
#include
#include
声明系统调用,采用内联的方式。
fork系统调用
static inline _syscall0(int,fork)
pause系统调用
static inline _syscall0(int,pause)
setup系统调用
static inline _syscall1(int,setup,void *,BIOS)
sync系统调用
static inline _syscall0(int,sync)
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
static char printbuf[1024];
extern int vsprintf();
extern void init(void);
extern void blk_dev_init(void);
extern void chr_dev_init(void);
extern void hd_init(void);
extern void floppy_init(void);
extern void mem_init(long start, long end);
extern long rd_init(long mem_start, int length);
extern long kernel_mktime(struct tm * tm);
extern long startup_time;
参见setup.s中,通过BIOS中断加载的系统参数。
扩展内存大小
#define EXT_MEM_K (*(unsigned short *)0x90002)
硬盘参数表
#define DRIVE_INFO (*(struct drive_info *)0x90080)
根文件系统的设备号
#define ORIG_ROOT_DEV (*(unsigned short *)0x901FC)
读取CMOS的实时钟
#define CMOS_READ(addr) ({ /
outb_p(0x80|addr,0x70); /
inb_p(0x71); /
})
将BCD码转换成二进制码
#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
将实时钟时间转换成1970年1月1日0时开始的秒数
static void time_init(void)
{
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);
}
static long memory_end = 0;
static long buffer_memory_end = 0;
static long main_memory_start = 0;
struct drive_info { char dummy[32]; } drive_info;
main函数的返回类型是void,由head.s压入栈时决定的。
void main(void)
{
对根文件系统设备号进行付值
ROOT_DEV = ORIG_ROOT_DEV;
对硬盘参数表进行付值
drive_info = DRIVE_INFO;
计算内存结束位置,1M+扩展内存
memory_end = (1<<20) + (EXT_MEM_K<<10);
内存结束地址4k对齐
memory_end &= 0xfffff000;
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;
main_memory_start = buffer_memory_end;
如果编译内核的时候选择了虚拟盘参数,则内存的开始位置需要考虑虚拟盘所占空间
#ifdef RAMDISK
main_memory_start += rd_init(main_memory_start, RAMDISK*1024);
#endif
进行一系列的初始化操作
内存初始化
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();
move_to_user_mode();
创建子进程
if (!fork()) {
在进程1中执行init程序
init();
}
等待init进程退出
for(;;) pause();
}
定义printf函数。
static int printf(const char *fmt, ...)
{
va_list args;
int i;
va_start(args, fmt);
系统调用,写到标准输出。
write(1,printbuf,i=vsprintf(printbuf, fmt, args));
va_end(args);
return i;
}
static char * argv_rc[] = { "/bin/sh", NULL };
static char * envp_rc[] = { "HOME=/", NULL };
static char * argv[] = { "-/bin/sh",NULL };
static char * envp[] = { "HOME=/usr/root", NULL };
void init(void)
{
int pid,i;
执行setup系统调用,读取硬盘信息
setup((void *) &drive_info);
打开终端/dev/tty0,以读写方式打开
(void) open("/dev/tty0",O_RDWR,0);
复制文件描述符0到标准输出
(void) dup(0);
复制文件描述符0到标准出错
(void) dup(0);
打印高速缓存的信息,以1024字节为单位
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);
在进程1中创建子进程
if (!(pid=fork())) {
创建成功之后,在子进程中执行/etc/rc中的命令
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) {
在init进程中创建子进程
if ((pid=fork())<0) {
printf("Fork failed in init/r/n");
continue;
}
if (!pid) {
为新创建的子进程创建一个新的会话期,执行shell.
close(0);close(1);close(2);
setsid();
设置标准输入,标准输出和标准出错
(void) open("/dev/tty0",O_RDWR,0);
(void) dup(0);
(void) dup(0);
执行交互式shell。
_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);
}