Chinaunix首页 | 论坛 | 博客
  • 博客访问: 121120
  • 博文数量: 31
  • 博客积分: 2010
  • 博客等级: 大尉
  • 技术积分: 361
  • 用 户 组: 普通用户
  • 注册时间: 2008-03-11 15:38
文章分类

全部博文(31)

文章存档

2008年(31)

我的朋友

分类: LINUX

2008-04-15 10:58:17

      今天用了一个小时的时间把0.11核的初始化程序main.c浏览完了,对Linux的初始化过程有了一个整体上的了解,当然main里面调用了多个初始化子程序,我都暂且没深入进去看,我打算以后看到某个专题的时候再看吧。和以前一样,老规矩,先说一下初始化程序的大概过程,在深入文件具体说一下。

      一、概述

      main.c主程序工作在任务0中, main先物理内存进行划分和分配,然后对各个设备进行初始化,最后创建进程1(init进程),并从进程1的init()运行,进程1的init()会继续进行系统的初始化并再创建一个非交互式shell进程:进程2,在进程2主要是执行rc配置文件,进程2结束后会返回到进程1中,进程1再创建一个shell登陆进程,在这里用户就可以使用Linux的shell命令环境了。

     二、main.c结构

     1)保存根设备号和划分内存:设置高速缓存末地址、物理内存大小、内存主区 开始地址。

     2)硬件初始化:陷阱门、块设备、字符设备、tty、开机时间、调度程序、硬盘等

     3)切换到用户模式,创建进程1,在进程1中从init()开始执行,而进程0处在空闲状态。

     进程1的init()中:

     4)系统调用setup:安装根文件系统设备

     5)打开设备tty0:它对应终端控制台,以读写方式打开作为输入,并再复制两个句柄作为普通输出和错误输出。

     6)创建子shell进程(进程2):创建进程2,在进程2中,关闭输入设备句柄(0),并重新将输入句柄定向到rc,使系统能加载rc文件,最后加载rc文件执行,完成配置工作。而进程1则等待进程2的结束。

     7)建立shell登陆进程:创建新进程,在新进程中,首先关闭三个句柄(0,1,2);然后创建一个会话期,接着重新打开tty0作为输入设备,复制两个句柄作为stdout和stderr;最后加载shell登陆程序。而在进程1中,等待创建进程的结束并开始新一轮的创建新进程的循环。

 

     以上就是Linux系统初始化的大体过程,在这里需要说明几个问题:

     1)系统调用改作内联函数
      程序中的三个系统调用fork()、pause()和setup()是采用的内联函数的形式而不是进行系统调用。这样做的原因是这样的,因为在创建进程1之前任务0就已经切换到用户模式下了,这个使用的栈是用户栈。进程1创建后,它用的代码和数据是核进程0共享的,也就是说进程1用的栈和进程0用的栈是一个栈,如果在进程1中发生入栈操作,根据内存管理提供的写时复制规则就会引起页面写保护异常,系统就会在物理内存中申请新的页面并将进程0栈中相应的页面复制到进程1新分配的物理页中,这样问题就来了,如果在复制之前进程0用了用户栈,那么复制时,也会把进程0栈的内容复制到进程1的栈中,这样进程1中就会有进程0的多余信息。这样不好。而内联函数就可以解决这个问题,内联函数的调用不会引起用户栈进出栈操作,即使里面的中断指令int会使用栈,但它操作的是核心态栈,核心态栈是独立的,存在于task_struct所在页面,这样就会保证在进程1执行前进程0的用户栈是空的了。

     2)会话期
     上面提到了创建会话期。下面说一下会话期。一个进程调用多个fork()创建多个子进程,这些进程会构成一个进程组,每个组内的进程除了用自己的进程号之外还有它所在组的进程组号(也就是组长的进程号),而会话期则是一个或者多个进程组的集合。用户登陆后所执行的所有程序都属于一个会话期,而登陆shell就是会话期的首进程,也就是控制终端,当他=用户退出登录的时候,系统会结束这会话期的所用进程,这也是会话期的主要用途之一。

     3)用户登录。
     上面的main.c中的init()函数中,直接创建进程运行shell登陆程序,而在实际应用中不是这样的。在实际应用中,在这个地方会执行系统初始化程序init.c,在这个程序根据rc配置信息,为每个允许登陆的终端设备创建一个子进程,并在子进程中运行getty程序,这个程序会在终端上显示登陆信息(用户名密码),用户输入用户信息后,getty被替换成login程序,login程序在验证了用户信息的正确性后,调用shell程序,进入交互式界面。

     4)CMOS信息
     内核需要直接从CMOS中读取时间、内存等信息,读取原理是这样的:系统的信息储存在CMOS的不同偏移处,系统先向CMOS的70地址端口写入偏移地址,在从71数据端口利用int读出数据。

 

阅读(794) | 评论(0) | 转发(0) |
0

上一篇:Linux的启动过程

下一篇:Linux栈的使用

给主人留下些什么吧!~~