您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 销售管理 > LINUX_init
1/*2*linux/init/main.c3*4*(C)1991LinusTorvalds5*/67#define__LIBRARY__//定义该变量是为了包括定义在unistd.h中的内嵌汇编代码等信息。8#includeunistd.h//*.h头文件所在的默认目录是include/,则在代码中就不用明确指明位置。//如果不是UNIX的标准头文件,则需要指明所在的目录,并用双引号括住。//标准符号常数与类型文件。定义了各种符号常数和类型,并申明了各种函数。//如果定义了__LIBRARY__,则还包括系统调用号和内嵌汇编代码_syscall0()等。9#includetime.h//时间类型头文件。其中最主要定义了tm结构和一些有关时间的函数原形。1011/*12*weneedthisinline-forkingfromkernelspacewillresult13*inNOCOPYONWRITE(!!!),untilanexecveisexecuted.This14*isnoproblem,butforthestack.Thisishandledbynotletting15*main()usethestackatallafterfork().Thus,nofunction16*calls-whichmeansinlinecodeforforktoo,asotherwisewe17*wouldusethestackuponexitfrom'fork()'.18*19*Actuallyonlypauseandforkareneededinline,sothatthere20*won'tbeanymessingwiththestackfrommain(),butwedefine21*someotherstoo.22*//**我们需要下面这些内嵌语句-从内核空间创建进程(forking)将导致没有写时复制(COPYONWRITE)!!!*直到一个执行execve调用。这对堆栈可能带来问题。处理的方法是在fork()调用之后不让main()使用*任何堆栈。因此就不能有函数调用-这意味着fork也要使用内嵌的代码,否则我们在从fork()退出*时就要使用堆栈了。*实际上只有pause和fork需要使用内嵌方式,以保证从main()中不会弄乱堆栈,但是我们同时还*定义了其它一些函数。*/23staticinline_syscall0(int,fork)//是unistd.h中的内嵌宏代码。以嵌入汇编的形式调用//Linux的系统调用中断0x80。该中断是所有系统调用的//入口。该条语句实际上是intfork()创建进程系统调用。//syscall0名称中最后的0表示无参数,1表示1个参数。24staticinline_syscall0(int,pause)//intpause()系统调用:暂停进程的执行,直到//收到一个信号。25staticinline_syscall1(int,setup,void*,BIOS)//intsetup(void*BIOS)系统调用,仅用于//linux初始化(仅在这个程序中被调用)。26staticinline_syscall0(int,sync)//intsync()系统调用:更新文件系统。2728#includelinux/tty.h//tty头文件,定义了有关tty_io,串行通信方面的参数、常数。29#includelinux/sched.h//调度程序头文件,定义了任务结构task_struct、第1个初始任务//的数据。还有一些以宏的形式定义的有关描述符参数设置和获取的//嵌入式汇编函数程序。30#includelinux/head.h//head头文件,定义了段描述符的简单结构,和几个选择符常量。31#includeasm/system.h//系统头文件。以宏的形式定义了许多有关设置或修改//描述符/中断门等的嵌入式汇编子程序。32#includeasm/io.h//io头文件。以宏的嵌入汇编程序形式定义对io端口操作的函数。3334#includestddef.h//标准定义头文件。定义了NULL,offsetof(TYPE,MEMBER)。35#includestdarg.h//标准参数头文件。以宏的形式定义变量参数列表。主要说明了-个//类型(va_list)和三个宏(va_start,va_arg和va_end),vsprintf、//vprintf、vfprintf。36#includeunistd.h37#includefcntl.h//文件控制头文件。用于文件及其描述符的操作控制常数符号的定义。38#includesys/types.h//类型头文件。定义了基本的系统数据类型。3940#includelinux/fs.h//文件系统头文件。定义文件表结构(file,buffer_head,m_inode等)。4142staticcharprintbuf[1024];//静态字符串数组。4344externintvsprintf();//送格式化输出到一字符串中(在kernel/vsprintf.c,92行)。45externvoidinit(void);//函数原形,初始化(在168行)。46externvoidblk_dev_init(void);//块设备初始化子程序(kernel/blk_drv/ll_rw_blk.c,157行)47externvoidchr_dev_init(void);//字符设备初始化(kernel/chr_drv/tty_io.c,347行)48externvoidhd_init(void);//硬盘初始化程序(kernel/blk_drv/hd.c,343行)49externvoidfloppy_init(void);//软驱初始化程序(kernel/blk_drv/floppy.c,457行)50externvoidmem_init(longstart,longend);//内存管理初始化(mm/memory.c,399行)51externlongrd_init(longmem_start,intlength);//虚拟盘初始化(kernel/blk_drv/ramdisk.c,52)52externlongkernel_mktime(structtm*tm);//建立内核时间(秒)。53externlongstartup_time;//内核启动时间(开机时间)(秒)。5455/*56*Thisissetupbythesetup-routineatboot-time57*//**以下这些数据是由setup.s程序在引导时间设置的(参见第2章2.3.1节中的表2.1)。*/58#defineEXT_MEM_K(*(unsignedshort*)0x90002)//1M以后的扩展内存大小(KB)。59#defineDRIVE_INFO(*(structdrive_info*)0x90080)//硬盘参数表基址。60#defineORIG_ROOT_DEV(*(unsignedshort*)0x901FC)//根文件系统所在设备号。6162/*63*Yeah,yeah,it'sugly,butIcannotfindhowtodothiscorrectly64*andthisseemstowork.Ianybodyhasmoreinfoonthereal-time65*clockI'dbeinterested.Mostofthiswastrialanderror,andsome66*bios-listingreading.Urghh.67*//**是啊,是啊,下面这段程序很差劲,但我不知道如何正确地实现,而且好象它还能运行。如果有*关于实时时钟更多的资料,那我很感兴趣。这些都是试探出来的,以及看了一些bios程序,呵!*/6869#defineCMOS_READ(addr)({\//这段宏读取CMOS实时时钟信息。70outb_p(0x80|addr,0x70);\//0x70是写端口号,0x80|addr是要读取的CMOS内存地址。71inb_p(0x71);\//0x71是读端口号。72})7374#defineBCD_TO_BIN(val)((val)=((val)&15)+((val)4)*10)//将BCD码转换成数字。7576staticvoidtime_init(void)//该子程序取CMOS时钟,并设置开机时间�startup_time(秒)。77{78structtmtime;7980do{81time.tm_sec=CMOS_READ(0);//参见后面CMOS内存列表。82time.tm_min=CMOS_READ(2);83time.tm_hour=CMOS_READ(4);84time.tm_mday=CMOS_READ(7);85time.tm_mon=CMOS_READ(8);86time.tm_year=CMOS_READ(9);87}while(time.tm_sec!=CMOS_READ(0));88BCD_TO_BIN(time.tm_sec);89BCD_TO_BIN(time.tm_min);90BCD_TO_BIN(time.tm_hour);91BCD_TO_BIN(time.tm_mday);92BCD_TO_BIN(time.tm_mon);93BCD_TO_BIN(time.tm_year);94time.tm_mon--;95startup_time=kernel_mktime(&time);96}9798staticlongmemory_end=0;//机器具有的内存(字节数)。99staticlongbuffer_memory_end=0;//高速缓冲区末端地址。100staticlongmain_memory_start=0;//主内存(将用于分页)开始的位置。101102structdrive_info{chardummy[32];}drive_info;//用于存放硬盘参数表信息。103104voidmain(void)/*ThisreallyISvoid,noerrorhere.*/105{/*Thestartuproutineassumes(well,...)this*//*这里确实是void,并没错。在startup程序(head.s)中就是这样假设的。//参见head.s程序第136行开始的几行代码。106/*107*Interruptsarestilldisabled.Donecessarysetups,then108*enablethem109*//**此时中断仍被禁止着,做完必要的设置后就将其开启。*///下面这段代码用于保存://根设备号�ROOT_DEV;高速缓存末端地址�buffer_memory_end;//机器内存数�memory_end;主内存开始地址�main_memory_start;110ROOT_DEV=ORIG_ROOT_DEV;111drive_info=DRIVE_INFO;112memory_end=(120)+(EXT_MEM_K10);//内存大小=1Mb字节+扩展内存(k)*1024字节。113memory_end&=0xfffff000;//忽略不到4Kb(1页)的内存数。114if(memory_end16*1024*1024)//如果内存超过16Mb,则按16Mb计。115memory_end=16*1024*1024;116if(memory_end12*1024*1024)//如果内存12Mb,则设置缓冲区末端=4Mb117buffer_memory_end=4*1024*1024;118elseif(memory_end6*1024
本文标题:LINUX_init
链接地址:https://www.777doc.com/doc-3372448 .html