--- init --- main.c --- sched_init()
| |- init() --- setup() --- int 0x80
| |- open("/dev/tty0") --- int 0x80
| |- dup(0) --- int 0x80//建立标准输出文件
| |- dup(0) --- int 0x80//标准错误文件
| |- pid=fork() --- int 0x80
| |- if(!pid) --- Yes --- close(0)
| | |- open("/etc/rc")
| | |- execve("/bin/sh")
| |- No --- 等待pid==wait(&i)//切换到进程2,并等待其退出
| |- fork() --- int 0x80
| |- close(0);close(1);close(2);
| |- open("/dev/tty0")
| |- dup(0);dup(0);
| |- execve("/bin/sh")//重启shell进程
| //由于打开的是标准输入设备,因此不会退出
| //系统进入怠速模式
|
|- kernel --- sched.c --- sched_init() --- set_system_gate(0x80,&system_call)
| |
| |- system_call.s --- system_call() --- sys_call_table(,%eax,4)
| | |- sys_execve() --- eax指向堆栈中eip指针处
| | |- do_execve()
| |
| |- exit.c --- sys_waitpid --- 找到current的子进程*p,也就是进程2
| | |- p处于僵死态,则返回(*p)->pid
| | | 否则继续运行
| | |- 设置current->state为等待状态
| | |- schedule()//切换到进程2
| | |- 检测到SIGCHLD信号量,返回第1条执行
| |- sys_exit() --- do_exit()
| |- do_exit() --- 释放shell进程所占据的内存页面
| |- 将update的父进程设置为进程1
| |- 关闭当前进程打开着的所有文件
| |- 把当前进程置为僵死状态
| |- tell_father()//通知父进程
| |- schedule()//发现进程1收到信号,切换到进程1
|
|- include --- linux --- sys_call_table[] --- sys_open()
| |- sys_dup(0)
| |- sys_fork()//复制父进程
| |- sys_waitpid()
| |- sys_close()
| |- sys_read()
| |- sys_exit()
|
|- fs --- open.c --- sys_open(pathname) --- 找到current中空闲filp[fd]
| | | |- 在file_table[64]中获取空闲项的地址f
| | | |- filp[fd]=f
| | | |- 文件引用计数加1
| | | |- open_namei(pathname,&inode)
| | | |- current->tty = MINOR(inode->i_zone[0])
| | | |- f->f_inode = inode//设置file_table[0]
| | |- sys_close() --- filp = current->filp[fd]
| | |- current->filp[fd] = NULL
| | |- filp->f_count减1
| |
| |- namei.c --- open_namei() --- dir=get_dir(pathname,&namelen,&namebase)
| | | | //获取dev目录inode,以及'tty0'的长度和首地址
| | | |- find_entry(&dir,namebase,namelen,&de)
| | | | //根据上面的信息得到目录项de
| | | |- inr=de->inode; dev=dir->i_dev
| | | |- 保存inr和dev在table_inode[32]中
| | | |- inode=iget(inr,dev)//得到tty0的i节点
| | |- get_dir() --- inode = current->root
| | |- pathname指向'd'
| | |- thisname = pathname
| | |- 获取thisname的长度namelen
| | |- pathname指向下一个目录
| | |- pathname是最后一个目录则返回inode
| | |- find_entry(&inode,thisname,namelen,&de)
| | | //根据上面的信息得到目录项de
| | |- inr=de->inode; dev=dir->i_dev
| | |- iput(inode)
| | |- inode=iget(idev,inr)
| | |- 返回3执行
| |
| |- fcntl.c --- sys_dup() --- dupfd(0,0)
| | |- dupfd() --- 在进程1的filp[20]中寻找空闲项filp[arg]
| | |- filp[arg]指向目标文件
| |
| |- exec.c --- do_execve() --- inode=namei(filename)
| | |- bh = bread(inode->i_dev,inode->i_zone[0])
| | |- ex = *((struct exec *) bh->b_data)
| | |- eip[0] = ex.a_entry//eip指向shell程序
| | //由于该线性空间对应的程序内容未加载,因此会触发 page_fault
| |
| |- read_write.c --- sys_read() --- 如果是普通文件,读取完成后返回-ERROR
|
|- mm --- page.s --- page_fault() --- do_no_page()
|- memery.c --- do_no_page() --- page = get_free_page()
| |- bread_page(page,current->executable->i_dev,nr)
| |- put_page(page)//建立页表映射关系,之后shell程序开始执行
| //中断退出后,shell程序执行
|- put_page() --- page_table = (address>>20) & 0xffc
|- page_table[(address>>12) & 0x3ff] = page | 7
--- bin --- sh --- 读取/etc/rc文件,并执行
|
|- etc --- rc --- /etc/update &//创建update程序,挂起后返回进程2
|- echo "/dev/hd1 /" > /etc/mtab --- read() --- int 0x80
|- 返回错误则执行exit() --- int 0x80
Linux-0.11内核分析04:进程2的创建及执行
猜你喜欢
转载自blog.csdn.net/egean/article/details/81000818
今日推荐
周排行