Linux 内核--任务0的调度切换


本文分析基于Linux 0.11内核,main.c中在move_to_user_mode()之后,切换到用户模式下运行,task0然后执行fork()创建进程task1来执行init()函数。init()函数如下:

  1. void init (void)   
  2. {   
  3.   int pid, i;   
  4.   // 读取硬盘参数包括分区表信息并建立虚拟盘和安装根文件系统设备。   
  5.   // 该函数是在25 行上的宏定义的,对应函数是sys_setup(),在kernel/blk_drv/hd.c,71 行。   
  6.     setup ((void *) &drive_info);   
  7.     (void) open ("/dev/tty0", O_RDWR, 0);   // 用读写访问方式打开设备“/dev/tty0”,   
  8.   // 这里对应终端控制台。   
  9.   // 返回的句柄号0 -- stdin 标准输入设备。   
  10.     (void) dup (0);     // 复制句柄,产生句柄1 号 -- stdout 标准输出设备。   
  11.     (void) dup (0);     // 复制句柄,产生句柄2 号 -- stderr 标准出错输出设备。   
  12.     printf ("%d buffers = %d bytes buffer space\n\r", NR_BUFFERS, NR_BUFFERS * BLOCK_SIZE); // 打印缓冲区块数和总字节数,每块1024 字节。   
  13.     printf ("Free mem: %d bytes\n\r", memory_end - main_memory_start);  //空闲内存字节数。   
  14.   // 下面fork()用于创建一个子进程(子任务)。对于被创建的子进程,fork()将返回0 值,   
  15.   // 对于原(父进程)将返回子进程的进程号。所以180-184 句是子进程执行的内容。该子进程   
  16.   // 关闭了句柄0(stdin),以只读方式打开/etc/rc 文件,并执行/bin/sh 程序,所带参数和   
  17.   // 环境变量分别由argv_rc 和envp_rc 数组给出。参见后面的描述。   
  18.   if (!(pid = fork ()))   
  19.     {   
  20.       close (0);   
  21.       if (open ("/etc/rc", O_RDONLY, 0))   
  22.     _exit (1);      // 如果打开文件失败,则退出(/lib/_exit.c,10)。   
  23.       execve ("/bin/sh", argv_rc, envp_rc); // 装入/bin/sh 程序并执行。   
  24.       _exit (2);        // 若execve()执行失败则退出(出错码2,“文件或目录不存在”)。   
  25.     }   
  26.   // 下面是父进程执行的语句。wait()是等待子进程停止或终止,其返回值应是子进程的进程号(pid)。   
  27.   // 这三句的作用是父进程等待子进程的结束。&i 是存放返回状态信息的位置。如果wait()返回值不   
  28.   // 等于子进程号,则继续等待。   
  29.   if (pid > 0)   
  30.     while (pid != wait (&i))   
  31.       /* nothing */ ;   
  32.   // 如果执行到这里,说明刚创建的子进程的执行已停止或终止了。下面循环中首先再创建一个子进程,   
  33.   // 如果出错,则显示“初始化程序创建子进程失败”的信息并继续执行。对于所创建的子进程关闭所有   
  34.   // 以前还遗留的句柄(stdin, stdout, stderr),新创建一个会话并设置进程组号,然后重新打开   
  35.   // /dev/tty0 作为stdin,并复制成stdout 和stderr。再次执行系统解释程序/bin/sh。但这次执行所   
  36.   // 选用的参数和环境数组另选了一套(见上面165-167 行)。然后父进程再次运行wait()等待。如果   
  37.   // 子进程又停止了执行,则在标准输出上显示出错信息“子进程pid 停止了运行,返回码是i”,然后   
  38.   // 继续重试下去…,形成“大”死循环。   
  39.   while (1)   
  40.     {   
  41.       if ((pid = fork ()) < 0)   
  42.     {   
  43.       printf ("Fork failed in init\r\n");   
  44.       continue;   
  45.     }   
  46.       if (!pid)   
  47.     {   
  48.       close (0);   
  49.       close (1);   
  50.       close (2);   
  51.       setsid ();   
  52.       (void) open ("/dev/tty0", O_RDWR, 0);   
  53.       (void) dup (0);   
  54.       (void) dup (0);   
  55.       _exit (execve ("/bin/sh", argv, envp));   
  56.     }   
  57.       while (1)   
  58.     if (pid == wait (&i))   
  59.       break;   
  60.       printf ("\n\rchild %d died with code %04x\n\r", pid, i);   
  61.       sync ();   
  62.     }   
  63.   _exit (0);            /* NOTE! _exit, not exit() */  
  64. }  
  • 1
  • 2
  • 下一页

相关内容