void init(void)
169 {
170 int pid,i;
171
172 setup((void *) &drive_info); // 读取硬盘参数包括分区表信息并建立虚拟盘和
// 安装根文件系统设备。(kernel/blk_drv/hd.c,71)
173 (void) open("/dev/tty0",O_RDWR,0); // 用读写访问方式打开设备“/dev/tty0”,
// 这里对应终端控制台。
// 返回的句柄号0 -- stdin 标准输入设备。
174 (void) dup(0); // 复制句柄,产生句柄1 号 -- stdout 标准输出设备。
175 (void) dup(0); // 复制句柄,产生句柄2 号 -- stderr 标准出错输出设备。
176 printf("%d buffers = %d bytes buffer space\n\r",NR_BUFFERS,
177 NR_BUFFERS*BLOCK_SIZE); // 打印缓冲区块数和总字节数,每块1024 字节。
178 printf("Free mem: %d bytes\n\r",memory_end-main_memory_start); //空闲内存字节数。
// 下面fork()用于创建一个子进程(子任务)。对于被创建的子进程,fork()将返回0 值,
// 对于原(父进程)将返回子进程的进程号。所以180-184 句是子进程执行的内容。该子进程
// 关闭了句柄0(stdin),以只读方式打开/etc/rc 文件,并执行/bin/sh 程序,所带参数和
// 环境变量分别由argv_rc 和envp_rc 数组给出。参见后面的描述。
179 if (!(pid=fork())) {
180 close(0);
181 if (open("/etc/rc",O_RDONLY,0))
182 _exit(1); // 如果打开文件失败,则退出(/lib/_exit.c,10)。
183 execve("/bin/sh",argv_rc,envp_rc); // 装入/bin/sh 程序并执行。
184 _exit(2);
185 }
// 下面是父进程执行的语句。wait()是等待子进程停止或终止,其返回值应是子进程的进程号(pid)。
// 这三句的作用是父进程等待子进程的结束。&i 是存放返回状态信息的位置。如果wait()返回值不
// 等于子进程号,则继续等待。
186 if (pid>0)
187 while (pid != wait(&i))
188 /* nothing */;
// 如果执行到这里,说明刚创建的子进程的执行已停止或终止了。下面循环中首先再创建一个子进程,
// 如果出错,则显示“初始化程序创建子进程失败”的信息并继续执行。对于所创建的子进程关闭所
有
// 以前还遗留的句柄(stdin, stdout, stderr),新创建一个会话并设置进程组号,然后重新打开
// /dev/tty0 作为stdin,并复制成stdout 和stderr。再次执行系统解释程序/bin/sh。但这次执行所
// 选用的参数和环境数组另选了一套(见上面165-167 行)。然后父进程再次运行wait()等待。如果
// 子进程又停止了执行,则在标准输出上显示出错信息“子进程pid 停止了运行,返回码是i”,然后
// 继续重试下去…,形成“大”死循环。
189 while (1) {
190 if ((pid=fork())<0) {
191 printf("Fork failed in init\r\n");
更多电子书教程下载请登陆http://down.zzbaike.com/ebook
本站提供的电子书教程均为网上搜集,如果该教程涉及或侵害到您的版权请联系我们。
第4 章 初始化程序 linux/init/
67
192 continue;
193 }
194 if (!pid) {
195 close(0);close(1);close(2);
196 setsid();
197 (void) open("/dev/tty0",O_RDWR,0);
198 (void) dup(0);
199 (void) dup(0);
200 _exit(execve("/bin/sh",argv,envp));
201 }
202 while (1)
203 if (pid == wait(&i))
204 break;
205 printf("\n\rchild %d died with code %04x\n\r",pid,i);
206 sync();
207 }
208 _exit(0);
}