linux内核原代码init/main的注释

/ns/wz/sys/data/20020809010801.htm

linux内核原代码init/main的注释


本文出自:http://os.silversand.net
  #define __LIBRARY__
  #include
  #include
  /*
  * we need this inline - forking from kernel space will result
  * in NO COPY ON WRITE (!!!), until an execve is executed. This
  * is no problem, but for the stack. This is handled by not letting
  * main() use the stack at all after fork(). Thus, no function
  * calls - which means inline code for fork too, as otherwise we
  * would use the stack upon exit from 'fork()'.
  *
  * Actually only pause and fork are needed inline, so that there
  * won't be any messing with the stack from main(), but we define
  * some others too.
  */
  static inline _syscall0(int,fork) @@定义fork
  --sys_fork在unistd.h中定义syscall0
  static inline _syscall0(int,pause)
  static inline _syscall0(int,setup)
  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 hd_init(void);
  extern long kernel_mktime(struct tm * tm);
  extern long startup_time;

/*
  * Yeah, yeah, it's ugly, but I cannot find how to do this correctly
  * and this seems to work. I anybody has more info on the real-time
  * clock I'd be interested. Most of this was trial and error, and some
  * bios-listing reading. Urghh.
  */

#define CMOS_READ(addr) ({ \
  outb_p(0x80|addr,0x70); \
  inb_p(0x71); \
  })

#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)

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)-1;
   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);
  startup_time = kernel_mktime(&time);
  }

void main(void) /* This really IS void, no error here. */
  { /* The startup routine assumes (well, ...) this */
  /*
  * Interrupts are still disabled. Do necessary setups, then
  * enable them
  */
  time_init();
  tty_init();
  trap_init();
  sched_init();
  buffer_init();
  hd_init();
  sti();
  move_to_user_mode(); @@切至用户模式???到哪去了,回来了!!!
  if (!fork()) { /* we count on this going ok */
   init(); @@fork在unistd.h有其宏扩展int 0x80 
   如何返回两次?应该说子进程如何激活?
  }
  /*
  * NOTE!! For any other task 'pause()' would mean we have to get a
  * signal to awaken, but task0 is the sole exception (see 'schedule()')
  * as task 0 gets activated at every idle moment (when no other tasks
  * can run). For task0 'pause()' just means we go check if some other
  * task can run, and if not we return here.
  */
  for(;;) pause();
   @@pause 同fork在unistd.h有其宏扩展int 0x80 然后调schedule()
  }

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[] = { "-",NULL };
  static char * envp[] = { "HOME=/usr/root", NULL };

void init(void)
  {
  int i,j;

setup(); @@系统0号调用
  if (!fork())
   _exit(execve("/bin/update",NULL,NULL));
  (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(" Ok.\n\r");
  if ((i=fork())<0)
   printf("Fork failed in init\r\n");
  else if (!i) { @@启动一root shell进程?
   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));
  }
  j=wait(&i);
  printf("child %d died with code %04x\n",j,i);
  sync();
  _exit(0); /* NOTE! _exit, not exit() */
  }