基于Linux源码分析.doc_第1页
基于Linux源码分析.doc_第2页
基于Linux源码分析.doc_第3页
基于Linux源码分析.doc_第4页
全文预览已结束

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Linux 源码分析1. Linux进程概述进程简单的说就是一个程序一次执行的过程,它是一个动态的概念。按照教科书上的定义,进程是程序执行的实例,是linux的基本调度单位。对于程序员来说,最重要的就是要区分进程和程序的区别,程序是指一段完成功能的代码,或者说是一个工具,它是一个静态的概念,而进程,它是动态的,比如,linux的vi编辑器,它就是一段在linux下用于文本编辑的工具,那么它是一个程序,而我们在linux终端中,可以分别开启两个vi编辑器的进程。一旦提到进程,我们的脑子里就应该产生程序从代码的第一句动态的执行到最后一句这样的一个思路。一个进程由如下元素组成:1. 进程的当前上下文,即进程的当前执行状态;2. 进程的当前执行目录3. 进程访问的文件和目录4. 进程的访问权限,比如它的文件模式和所有权5. 内存和其他分配给进程的系统资源在linux系统中,内核使用进程来控制对CPU和其他系统资源的访问,并且使用进程来决定在CPU上运行哪个程序,运行多久以及采用什么特性运行它。内核的调度器负责在所有的进程间分配CPU执行时间,称为时间片(time slice),它轮流在每个进程分得的时间片用完后从进程那里抢回控制权。OS会为每个进程分配一个唯一的整型ID,做为进程的标识号(pid)。进程除了自身的ID外,还有父进程ID(ppid),所有进程的祖先进程是同一个进程,它叫做init进程,ID为1,init进程是内核自检后的一个启动的进程。init进程负责引导系统、启动守护(后台)进程并且运行必要的程序。2.Linux进程源码分析Linux 中有3 个系统调用fork、vfork 和clone 用来产生进程,在核心中分别对应sys_fork、sys_vfork 和sys_cloen,进一步都调用内部函数do_fork()完成,区别仅是调用do_fork()的参数不同。do_fork 参数:unsigned long clone_flags: 特征参数unsigned long stack_start: 子进程堆栈起始地址struct pt_regs* regs: 寄存器结构指针unsigned long stack_size: 堆栈容量,该参数未使用int _user * parent_tidptr:父进程tid 指针int _user * child_tidptr: 子进程tid 指针sys_fork 参数:struct pt_regs* regs调用do_fork 时格式:clone_flags = SIGCHLD:子进程结束(terminate)或停止(stop)时向父进程发送该信号stack_start = regs-rsp:共用父进程堆栈,使用COW 机制进行复制regs = regsstack_size = 0parent_tidptr = NULLchild_tidptr = NULLsys_vfork 参数:struct pt_regs* regs调用do_fork 时格式:clone_flags = CLONE_VFORK | CLONE_VM | SIGCHLD:与父进程共用一个地址空间;并且使父进程挂起进入等待状态,直至子进程释放地址空间,即结束或执行一个新程序;其他与sys_fork 相同sys_clone 参数:unsigned long clone_flagsunsigned long newspvoid _user* parent_tidvoid _user* child_tidstruct pt_regs* regs调用do_fork 时格式:stack_start = newsp ? : regs-rspstack_start = 0其它参数对应使用下面分析do_fork()过程1 pid = alloc_pidmap():分配一个空闲的pid 号2 检测current-ptrace 标记,如果需要跟踪子进程,则在clone_flags 加入CLONE_PTRACE 标记3 p = copy_process():创建进程描述字I 如果clone_flags 同时带有CLONE_NEWNS 和CLONE_FS 标记则出错。CLONE_NEWNS 表示使用新的命名空间(namespace);CLONE_FS 表示与父进程共享current-fs 结构,即fs_structII 如果clone_flags 带有CLONE_THREAD 标记但没有CLONE_SIGHAND 标记则出错。CLONE_THREAD:将子进程加入到父进程的线程组中,强制子进程共享父进程的信号描述符。CLONE_SIGHAND:共享信号标示表,包括信号句柄(handler)、阻塞和挂起的信号III 如果clone_flags 带有CLONE_SIGHAND标记但没有CLONE_VM标记则出错。CLONE_VM:父子进程共享虚地址空间IV p = dup_task_struct(orig = current):复制进程控制字task_structi prepare_to_copy(orig):直接调用函数unlazy_fpu(orig),如果当前进程正在使用浮单元(FPU),即orig-thread_info-status中有TS_USEDFPU标记,则调用函数save_init_fpu(orig),将浮点寄存器值保存到orig-thread.i387.fxsave 中,同时清除orig-thread_info-status 中的TS_USEDFPU 标记,并调用宏stts 将CR0 中的TS 标记(bit3)置1,表示即将有进程切换,若使用x87 指令或多媒体指令将产生设备不可用异常ii tsk = alloc_task_struct():从专用缓存task_struct_cachep 中分配一个进程控制结构iii ti = alloc_thread_info():调用为宏_get_free_pages(,1)分配2 个连续物理页面作为线程管理字和核心堆栈iv *ti = *orig-thread_info:复制线程控制结构v *tsk = *origf:复制进程控制结构vi tsk-thread_info = ti;ti-task = tsk:建立进程、线程控制字对应关系vii 设置tsk-usage = 2:设置控制字计数,一个用于新创建进程自身,一个用于release_task()执行者,通常为父进程V 验证新进程拥有者的进程总数是否超过限制,即p-user-processes = p-signal-rlimRLIMIT_NPROC.rlim_cur,若超过,且没有管理员权限也不是root 用户,则出错VI 增加计数:p-user-_count,p-user-processesVII get_group_info(p-group_info):增加p-group_info-usage 计数VIII copy_flags(clone_flags, p):将p-flags 中清除PF_SUPERPRIV 标记,设置PF_FORKNOEXEC标记,如果clone_flags 中没有CLONE_PTRACE 标记,则置p-ptrace = 0。PF_SUPERPRIV:超级用户标记,PF_FORKNOEXEC:fork 但不执行标记IX p-pid = pid:为子进程设置PIDX 如果clone_flags 中带有CLONE_PARENT_SETTID 标记,则将p-pid 写入用户空间变量parent_tidptr 中XI 置 p-proc_dentry=NULL,初始化链表p-children、p-sibling,初始化自旋锁p-alloc_lock,p-proc_lock,init_sigpending(&p-pending):初始化挂起信号管理结构,初始化p 其他成员XII copy_semundo(clone_flags, p):i 如果clone_flags 中没有CLONE_SYSVSEM 标记,则置p-sysvsem.undo_list = NULL后返回,否则继续执行ii get_undo_list(undo_listp = &undo_list):A 如果当前进程undo_list(current-sysvsem.undo_list)= NULL,则为其分配一个semundo_list 结构B *undo_lsitp = current-sysvsem.undo_listiii 增加undo_list 计数undo_list-refcntiv p-sysvsem.undo_list = undo_listXIII copy_files(clone_flags, p)i 如果clone_flags 中有标志CLONE_FILES,则增加引用计数current-files-count 返回ii 从专用缓存files_cachep 中分配一个files_struct 结构并初始化iii open_files = count_open_files():计算当前进程使用的最大文件描述符fdiv 复制files_struct 中的open_fds 和close_on_exec 标记,未使用的部分清0v 利用一个for 循环,复制current-files-fd.中的全部打开的文件到p-files-fd.中,若文件没有打开,则清除p-file-open_fds 中对应的位图XIV copy_fs(clone_flags, p):如果clone_flags 标记CLONE_FS 置位,则增加current-fs-count 计数后返回,否则设置p-fs = _copy_fs_struct(current-fs):从专用缓存fs_cachep 中分配一个fs_struct 结构,并设置初值等于当前进程的fs_struct 结构XV copy_sighand(clone_flags, p):复制信号处理函数i 如果带有CLONE_SIGHAND或CLONE_THREAD标记,则直接增加current-sighand-count 计数后返回ii 从专用缓存sighand_cachep 中分配一个sighand_struct 结构sig,并进行初始化iii 复制current-sighand-action 到sig-action 中iv 设置p-sighand = sig,sig-count = 1XVI copy_signal(clone_flags, p)i 如果clone_flags 中标记CLONE_THREAD 置位则增加引用计数current-signal-count和current-signal-live 后返回ii 从专用缓存signal_cachep 中分配一个signal_struct 结构sigiii p-signal = sig,执行其它基本初始化iv 复制current-signal-rlim 到sig-rlim 中XVII copy_mm(clone_flags, p):复制虚地址空间,从init_level4_pgt 中复制核心空间页表i 如果clone_flags 中标记CLONE_VM 置位则增加引用计数current-mm-mm_users,否则继续执行ii mm = allocate_mm():从专用缓存mm_cachep 中分配一个mm_struct 结构iii memcpy(mm, current-mm, sizeof(*mm):复制mm_struct 结构iv mm = mm_init(mm):分配pgd,并从init_level4_pgt 中复制核心空间页表A 对 mm 结构进行基本初始化B mm_alloc_pgd(mm):设置mm-pgd = pgd_alloc(mm):a pgd = _get_free_page():分配一个物理页面b boundary = pgd_index(_PAGE_OFFSET):计算地址_PAGE_OFFSET 在pgd 中的位置c 将 pgd 中的0boundary 项清0d 复制init_level4_pgt+boundary 到pgd+boundary,共PTRS_PER_PGD-boundary项,即复制核心空间对应pgd,设置子进程核心空间页表v init_new_context(p, mm):调用函数copy_ldt(new = &mm-context, old = ¤t-mm-context)A alloc_ldt(pc = new, mimcount = old-size, reload = 0)a 如果new-size = old-size 将直接返回,此时复制进程时直接返回b 将 mincount 向上圆整到512 字节的整数倍c 新的LDT 容量为mincount*LDT_ENTRY_SIZE,如果该值小于1 页则调用kmalloc 分配内存,否则调用

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论