第三章 进程管理
1. fork系统调用从内核返回两次: 一次返回到子进程,一次返回到父进程2. task_struct结构是用slab分配器分配的,2.6以前的是放在内核栈的栈底的;所有进程的task_struct连在一起组成了一个双向链表3. 2.6内核的内核栈底放的是thread_info结构,其中有指向task_struct的指针;4. current宏可以找到当前进程的task_struct;X86是通过先找到thread_info结构,而PPC是有专门的寄存器存当前task_struct(R2)5. 内核栈大小一般是8KB6. 进程的五种状态:TASK_RUNNING, TASK_INTERRUPTABLE, TASK_UNINTERRUPTABLE(处于改状态的进程不能被kill,因为它可能正在等待很关键的数据,或者持有了信号量等), TASK_TRACED(被其他进程跟踪状态,具体状态表现不明), TASK_STOPPED(收到SIG_STOP信号,停止进程,相当于暂停进程,但是也可以恢复)7. 运行上下文分为“进程上下文”和“中断上下文”。系统调用时内核代表进程在进程上下文中执行代码,这时current宏是有效的,指向进程的task_struct,而且系统调用时内核使用的页表是用户态进程的页表;而在中断上下文内核不代表任何进程执行代码,而是执行一个中断处理程序,不会有进程去干预这些中断上下文,所以此时不存在进程上下文。8. 系统调用在陷入内核的瞬间应该是在中断上下文的,因为是软中断,只是陷入内核后又用了进程上下文9. 在每个进程的task_struct结构中,有一个parent指针指向其父进程,有一个链表表示其所有的子进程,用这样的结构构成了整个系统进程关系树。10. 内核的双向列表专用结构struct list_head11. 进程创建分为两个步骤:fork和exec,fork用来创建进程的结构,通过写时复制,父子进程共享进程空间(页表),父进程和子进程的区别仅仅是PID,PPID,某些资源,统计量(task_struct的结构); exec读出程序代码并执行之。通过写时复制,只有在需要写入进程地址空间时,才为子进程创建自己的进程地址空间。*** fork的开销其实就是复制父进程的页表 和 为子进程分配task_struct 结构fork的过程: fork() -> clone() -> do_fork() -> copy_PRocess()copy_process()的过程:a) 为子进程分配内核栈,创建thread_info结构,创建一份与父进程相同的task_struct结构b) 更改thread_info ,task_struct结构中的部分字段,将子进程与父进程区分开来c) 将子进程的状态设置为TASK_UNINTERRUPTIBLEd) 为子进程分配一个可用的PID(alloc_pid())e) 拷贝或共享父进程打开的文件,信号处理函数,进程地址空间等f) 设置子进程状态为RUNNINGg) 返回一个指向子进程的指针一般系统会优先唤醒子进程,因为如果优先唤醒父进程,父进程就有可能会写入,这样会触发写时复制,而子进程一般会调用exec12. vforkvfork保证父进程在创建子进程后被阻塞,除非子进程执行了exec,或者子进程退出vfork在fork有写时复制功能后的好处只有一个,就是:vfork不用拷贝子进程的页表13. 线程线程在linux内核中的实现就是一个进程,只是线程会与别的线程共享进程地址空间,共享信号等等创建一个有四个线程的进程,会有四个进程被创建(四个内核栈和四个task_struct),只要指明这些task_struct中共享同一个进程地址空间即可线程的创建和进程的创建的代码上的对比:线程创建: clone(CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, 0)进程创建: clone(SIG_CHILD, 0)从线程创建的代码也可以看出:线程创建时是共享父进程的 进程地址空间(CLONE_VM), 打开的文件(CLONE_FILES),文件系统信息(CLONE_FS), 信号处理函数(CLONE_SIGHAND)14. 内核线程内核进程需要在后台执行一些操作,所以需要创建一些内核线程(kernel thread)内核线程和普通线程的主要区别是: 内核线程没有独立的地址空间(task_struct中的mm指针是NULL),共享使用内核态的页表; 内核线程只在内核运行,从来不会调度到用户态;内核线程和普通线程的相同点有: 同样有状态,被调度,也可以被抢占有哪些内核线程:flush,ksoftirqd等, 用ps -ef可以查看,其中CMD栏是[]扩起来的都是内核线程创建方法: kthread_create(); wake_up_process()用来唤醒创建的线程; kthread_run()可以创建并使之运行; kthread_stop()停止内核线程15. 孤儿进程如果父进程比子进程先执行完,父进程要在线程组中找一个新的进程作为子进程的父进程,或者找init进程作为子进程的父进程16. 进程消亡进程消亡时是通过exit()来实现的,进行exit之后内核依然会保留其task_struct结构,直到其父进程调用wait()或waitpid()回收大部分UNIX文件系统种类具有类似的通用结构,即使细节有些变化。其中心概念是超级块superblock, i节点inode, 数据块data block,目录块directory block, 。其中超级块中包含了关于该硬盘或分区上的文件系统的整体信息,如文件系统的大小(其准确信息依赖文件系统)等。 i节点包括除了名字外的一个文件的所有信息,名字与i节点数目一起存在目录中,目录条目包括文件名和文件的i节点数目。 i节点包括几个数据块的数目,用于存储文件的数据。 i节点中只有少量数据块数的空间,如果需要更多,会动态分配指向数据块的指针空间。这些动态分配的块是间接块;为了找到数据块,这名字指出它必须先找到间接块的号码。=========3. 超级块超级块记录文件系统基本信息超级块的操作主要是CRUD inode4. inodeinode存放的是文件或目录的所有信息:几个时间,引用计数,uid,gid,文件大小,权限一个inode就代表了一个文件:可以是普通文件,也可以是管道,块设备,字符设备等inode的操作:CRUD文件,修改权限,truncate,mkdir, mknod, rename等等通过inode可以寻找到dentry对象5. dentry目录项对象目录和普通文件都是一个目录项对象主要用来解析文件路径目录项结构中维护了整个文件目录树dentry的操作:判断目录对象是否有效,比较文件名,查找文件等6. 文件对象文件对象存放的是文件信息:文件路径,文件操作file_Operations, 文件offset,页高速缓存地址文件的操作: read/write/lseek/ioctl/fsync/open/close/mmap...
新闻热点
疑难解答