进程2的创建与执行

来源:互联网 发布:苹果mac 笔记本电脑 编辑:程序博客网 时间:2024/04/29 19:49
    进程1第一次执行,完成设置硬盘信息、格式化虚拟盘(根设备)、加载根文件系统后会回到下面语句:
    if(!fork()) {
        init();

    }       

//===================================== 分隔符 ==========================================----init();     1.打开终端设备文件    ----open("/dev/tty0",O_RDWR,0); //创建标准输入设备,其中/dev/tty0是该文件的路径名        ----sys_open("/dev/tty0",O_RDWR,0); //通过int 0x80中断进行系统调用            ----open_namei("/dev/tty0",O_RDWR,0,&inode);////获取文件tty0的i节点,保存在inode中                ----dir_namei("/dev/tty0",&namelen,&basename); //获取枝梢i节点,namelen为tty0的长度,basename指向tty0的第一个字母't'                    ----get_dir("/dev/tty0"); //遍历整个文件路径"/dev/tty0",获取枝梢i节点(即获取dev目录文件的i节点)                        ----find_entry(&inode,thisname,namelen,&de); //根据根i节点和dev来查找dev目录项,此时thisname为dev,namelen=3                        ----iget(idev,inr); //根据dev的i节点号获取dev的i节点                ----find_entry(&dir,basename,namelen,&de); //根据dev的i节点和"tty0"来查找tty0的目录项,de指向tty0目录项            ----//检查tty0文件的i节点属性,确定它是一个字符设备文件            ----//设置file_table[0]            //至此进程1的current->filp[0]存放的file_table第一个元素地址,file_table第一个元素,又存放着inode的地址,f_count为1,完成标准输入设备/dev/tty0的创建        2.打开标准输出、标准错误输出文件                ----(void)dup(0); //复制句柄,构建标准输出设备    ----(void)dup(0); //继续复制句柄,构建标准错误输出设备        ----sys_dup(0); //dup对应的系统调用函数            ----dupfd(0,0); //执行复制句柄            //执行两次dup(0),将flip[0]中存储的tty0文件指针复制进flip[1]和filp[2],并将file_table[0]中的f_count文件引用计数自增1(两次累加后,f_count为3)    //至此,创建shell所需要的终端标准输入设备文件、标准输出设备文件和标准错误输出设备文件读已经打开        3.进程1创建进程2并切换到进程2    ----if(!pid=fork()) //进程1创建进程2(执行过程参考进程1的创建与轮转:http://blog.csdn.net/yang2011079080010/article/details/52947247),进程2创建完毕后,fork()函数返回2,不会执行if中的语句,跳到wait(&i)执行    ----wait(&i) //进程1等待子进程退出,最终会切换到进程2执行        ----sys_waitpid(pid_t pid,unsigned long * stat_addr, int options); //先遍历所有进程,找出进程1的子进程,即进程2,再对进程2进行分析,确定进程2并不准备退出,于是设置flag标志为1,该标志将导致进程切换        ----schedule(); //在调用schedule()函数之前,先将进程1设为可中断状态,然后调用schedule()切换到进程2取执行    ----close(0); //切换到进程2执行(进程1的创建与轮转:http://blog.csdn.net/yang2011079080010/article/details/52947247),确定if(!(pid=fork())这条语句为真后,调用close(0)函数来关闭标准输入输出设备文件,并用rc文件代替        ----sys_close(0); //sys_close(0)是close(0)的系统调用,close(0)就是要将filp[20]第一项清空(就是关闭标准输入设备文件tty0),并递减file_table[64]中f_count的引用计数    ----open("/etc/rc",O_EDONLY,0); //rc文件代替tty0设备文件    ----execve("/bin/sh",argv_rc,envp_rc); //加载shell程序        ----sys_execve(); //execve()的系统调用            ----do_execve() //do_execve是加载shell程序的主体函数,其路径:fs/exec.c,执行过程参考http://blog.csdn.net/jltxgcy/article/details/43560229                ....        4.执行shell程序    do_execve()函数执行完后,sys_execve便会中断返回,去执行shell程序。由于在do_execve中清空了页目录表和对应页表,所以会产生一个"页异常"中断,此中断会进一步调用"缺页中断"处理程序来分配该页面,并加载一页shell程序    //代码路径:mm/page.s    ---- _page_fault: //页异常处理函数入口       ----do_no_page(); //调用"缺页中断"处理程序来分配该页面,并加载一页shell程序           ----get_free_page(); //为shell程序申请一页新的内存           ----nr[i] = bmap(current->executable,block); //得到执行的代码所在的块号           ----bread_page(page,current->executable->i_dev,nr); //读取4个逻辑块(1页)的shell程序内容进内存页面           ----put_page(page,address); //物理地址映射到线性地址,建立页目录表--->页表--->页表--->页面的三级映射管理关系        5.切换到shell进程执行,创建update进程(进程3)    sheel程序开始执行后,要读取标准输入设备文件上的信息,即task_struct中filp[20]第一项对应的文件信息。参考前面分析知道,此时filp[20]中第一项对应文件是rc而非tty0,因此shell先读取rc    ----read(); //shell程序调用read()读取rc文件上的内容        ----sys_read();read()函数的系统调用            ----file_read(inode,file,buf,count); //rc是普通文件,读取结束后,返回值是-ERROR,会导致shell进程退出,退出将执行exit()                ---- /etc/update & ... //创建一个新进程update,并加载update程序,update进程完成:将缓存区中的数据同步到外设,由于数据交换速度远低于数据处理速度,数据不是直接写到外设,而是先写入缓存区再同步到外设,                                       //因此每隔一段时间,update就会被唤醒,然后完成一次数据同步,没有同步任务时,update进程会被休眠                .....                                           ---- echo "/dev/hd1">/etc/mtab  //将"/dev/hd1"这一字符串写入虚拟盘中/etc/mtab中    ----exit();        ----sys_exit();            ----do_exit(); //为shell退出做善后工作:释放shell进程代码段和数据段所占用的内存页面、将update进程的父进程设置为进程1、解除shell进程与其他进程、文件、终端等的关系、将当前进程(进程2)设置为僵死状态                           //给进程1发信息,通知它shell进程即将退出、进程切换                ----free_page_tables(); //释放shell进程代码段和数据段所占用的内存页面                ----tell_father(current->father); //给进程1发信息,通知它shell进程即将退出                ----schedule();  //进程切换    ----sys_waitpid(); //进程1是执行sys_waitpid()函数时调用schedule()函数切换到进程2的,所以shell进程退出时执行schedule,会最终回到sys_waitpid(),继续shell进程退出的善后工作    //sys_waitpid()执行完后最终会回到init(),因创建完进程2后,pid=2,而sys_wait返回值也是2,即wait()返回值为2,while循环条件为假,跳出while循环。        6.重建shell    进程1回到init()继续执行,准备重建shell    ----init(); //回到init()中,准备重建shell        ----pid=fork(); //进程1创建进程4,即重建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)); //加载shell进程        .... ----sys_read(); //shell读取的tty0文件为字符设备文件         ----rw_char(); //进入shell进程,shell进程将被设置为可中断等待状态,这样所有的进程全部都处于可中断等待状态,再次切换到进程0取执行,系统实现怠速      ----while(1)        if(pid == wait(&i)) //进程1等待子进程退出        break;                                                       

        

0 0
原创粉丝点击