做家教有什么网站论坛搭建教程
2026/5/21 17:16:19 网站建设 项目流程
做家教有什么网站,论坛搭建教程,wap建站,wordpress 4.8正式版Linux内核设计与实现读书笔记—#xff08;三#xff09;进程管理 #xff08;1#xff09;进程 ①啥是进程 进程是处于执行期的程序。不仅是代码。 进程不仅仅包含可执行的代码#xff08;Unix称其为代码段 text section#xff09;#xff0c;它还是所有相关资源的集合…Linux内核设计与实现读书笔记—三进程管理1进程①啥是进程进程是处于执行期的程序。不仅是代码。 进程不仅仅包含可执行的代码Unix称其为代码段 text section它还是所有相关资源的集合。这包括打开的文件挂起的信号内核内部数据处理器状态内存地址空间包含内存映射一个或多个执行线程数据段存放全局变量程序本身不是进程程序是静态的目标码。进程是程序执行时的实时结果。完全可能有两个不同的进程在执行同一个程序它们并存且可以共享资源如打开的文件、地址空间。②啥是线程基本概念 线程是进程中活动的对象。每个线程拥有独立的程序计数器、进程栈和一组进程寄存器。调度单位 内核调度的对象实际上是线程而不是进程。Linux 的特殊性重点Linux 内核不区分线程和进程。在 Linux 内核眼中线程只不过是一种特殊的进程通常被称为轻量级进程它们与其他进程共享某些资源如地址空间。这与其他操作系统专门设计线程机制有很大不同。③进程的虚拟机制虚拟处理器让进程觉得自己在独享 CPU实际上是多进程共享由调度器管理。虚拟内存 让进程在分配和管理内存时觉得拥有整个系统的所有内存资源。同一进程内的线程之间共享虚拟内存但每个线程拥有各自的虚拟处理器。④进程的生命周期Linux 进程的生命周期主要由几个核心系统调用控制创建 (Creation) - fork():Linux 通过复制一个现有进程父进程来创建一个全新的进程子进程。fork() 从内核返回两次一次回到父进程一次回到新产生的子进程。在现代 Linux 内核中fork()实际上是由 clone()系统调用实现的。加载 (Loading) - exec():创建进程后通常接着调用 exec()这组函数。它会创建新的地址空间并将新的程序载入其中执行。终结 (Termination) - exit():程序通过 exit()系统调用退出执行终结进程并释放占用的资源。清理与等待 - wait4():父进程通过 wait4()查询子进程是否终结。这使得父进程可以等待特定子进程执行完毕。僵死状态 (Zombie)进程退出执行后直到它的父进程调用 wait()为止它会被设置为僵死状态。⑤Linux内核通常把进程也叫做任务2进程描述符及任务结构①进程描述符内核把进程的列表存放在叫做任务队列的双向循环链表中。链表中的每一项都是类型为task_struct,称为进程描述符的结构进程描述符包含一个具体进程的所有信息打开的文件进程的地址空间挂起的信号进程的状态还有其他更多的信息。②分配进程描述符Linux 通过 slab 分配器动态生成 task_struct以实现对象复用和缓存着色。③进程描述符的存放内核通过唯一的进程标识符PID来标识每一个进程这个PID也在进程各自的进程描述符中。访问任务需要获取指向task_struct的指针但不同的硬件结构实现方式不同有些硬件结构体系专门拿出一个专门的寄存器来存放当前进程的task_struct的指针用于加快访问速度。像x86这种寄存器不富裕的体系结构只能在内核栈的尾端创建thread_info结构同步内部各个计算偏移间接地查找task_struct结构。对于ARM架构优先采用寄存器存储 task_struct 指针。④进程状态进程描述符中的 state域描述了进程的当前状态进程必处于以下五种状态之一TASK_RUNNING (运行)进程是可执行的正在执行或在运行队列中等待。TASK_INTERRUPTIBLE (可中断)进程正在睡眠被阻塞等待条件达成。可以被信号唤醒。TASK_UNINTERRUPTIBLE (不可中断)进程正在睡眠但不响应信号。通常用于关键的 I/O 操作防止数据破坏。__TASK_TRACED被其他进程跟踪如 ptrace 调试。__TASK_STOPPED (停止)停止执行通常由 SIGSTOP 等信号触发。操作状态使用 set_task_state(task, state) 函数来调整状态它包含内存屏障以保证 SMP 下的安全性。⑤进程上下文当一个程序调执行了系统调用或者触发了某个异常它就陷入了内核空间。此时我们称内核“代表进程执行”并处于进程上下文中。在此下文中current指向该进程的 task_struct宏是有效的。⑥进程家族树Linux系统中所有的进程都是PID为1的init进程的后代。内核在系统启动的最后阶段启动init进程。该进程读取系统的初始化脚本并执行其他的相关程序最终完成系统启动的整个过程。系统中的每个进程必有一个父进程相应的每个进程也可以拥有零个或多个子进程。拥有同一个父进程的所有进程被称为兄弟。进程间的关系存放在进程描述符中。每个task_struct都包含一个指向其父进程tast_struct、叫做 parent 的指针还包含一个称为children的子进程链表。3进程创建①写时拷贝传统的fork()系统调用直接把所有的资源复制给新创建的进程。这种实现过于简单并且效率低下因为它拷贝的数据也许并不共享更糟的情况是如果新进程打算立即执行一个新的映像那么所有的拷贝都将前功尽弃。Linux的fork()使用写时拷贝copy-on-write页实现。写时拷贝是一种可以推迟甚至免除拷贝数据的技术。内核此时并不复制整个进程地址空间而是让父进程和子进程共享同一个拷贝。只有在需要写入的时候数据才会被复制从而使各个进程拥有各自的拷贝。也就是说资源的复制只有在需要写人的时候才进行在此之前只是以只读方式共享。这种技术使地址空间上的页的拷贝被推迟到实际发生写入的时候才进行。在页根本不会被写入的情况下举例来说fork()后立即调用exec()它们就无须复制了。②fork()Linux 里的 fork()其实是通过 clone() 系统调用来实现的。这后面有一系列复杂的调用链fork()- clone() - do_fork()- copy_process()。真正干活的是 copy_process() 生孩子的具体步骤都在这儿复制身份证给孩子发一个新的 task_struct进程描述符但里面的信息先抄爸爸的。检查户口看看你这个用户是不是生的孩子太多了有没有超标。划清界限把孩子身上的一些统计信息清零不能继承爸爸的“工龄”和“计时”。先别动把孩子的状态设为 TASK_UNINTERRUPTIBLE不可中断保证它还没生好前别乱跑。分配 PID给孩子发一个独一无二的身份证号PID。处理资源根据参数决定是复制文件、信号等资源还是和爸爸共享。扫尾返回指向孩子的指针。内核通常会让孩子子进程先运行。因为孩子大概率会马上调用 exec()变身去干别的事这样就避免了写时拷贝的发生如果爸爸先跑爸爸可能会改数据一改就会触发拷贝浪费时间。③vfork()vfork() 是个老东西。除了不拷贝父进程的页表项外,vfork()系统调用和fork()的功能相同。以前是因为 fork()太慢才用它现在 fork() 有了写时拷贝已经很快了所以 vfork基本上没什么用了除非你要极致的性能优化或者在那特定场景下。4线程在Linux中的实现Linux实现线程的机制非常独特。从内核的角度来说,它并没有线程这个概念。Linux把所有的线程都当做进程来实现。内核并没有准备特别的调度算法或是定义特别的数据结构来表征线 程。相反,线程仅仅被视为一个与其他进程共享某些资源的进程。每个线程都拥有唯一隶属于自 己的task_struct,所以在内核中,它看起来就像是一个普通的进程(只是线程和其他一些进程共 享某些资源,如地址空间)。①创造线程线程的创建和普通进程的创建类似,只不过在调用clone()的时候需要传递一些参数标志来指明需要共享的资源:②内核线程上面说的普通线程用户能看见的Linux 还有一种特殊的内核线程Kernel Thread内核线程和普通的进程间的区别在于内核线程没有独立的地址空间。它们只在内核空间运行,从来不切换到用户空间去。内核进程和普通进程一样,可以被调度,也可以被枪占。5进程终结**①进程终结 **进程终结的主要入口是 do_exit() (定义于 kernel/exit.c)无论是主动调用 exit()还是因异常/信号被动终止最终都会执行此函数。核心逻辑 (do_exit 的工作)标记状态将 task_struct 中的 flags设置为 PF_EXITING。资源解绑删除内核定时器 (del_timer_sync)。释放内存描述符 mm_struct若未被共享。退出 IPC 队列 (sem__exit)。递减文件描述符及文件系统引用计数。保存现场将退出代码 (exit code) 写入 task_struct供父进程检索。通知机制调用 exit_notify()向父进程发送信号并为自己的子进程寻找新父进程。进入僵死态将状态设置为 EXIT_ZOMBIE。调度切换调用 schedule()切换到新进程。注意 do_exit()永不返回。此时进程不可运行大部分资源已释放但内核栈、thread_info 和 task_struct 依然保留。这是为了向父进程提供信息。**②删除进程描述符 **僵死进程 (Zombie) 必须等待父进程回收才能彻底释放剩余的内核数据结构。回收触发父进程调用 wait() 族函数。清理函数release_task()。清理步骤脱离组织调用 __exit_signal() - unhash_process()从 PID 哈希表 (pidhash) 和任务列表 (task list) 中删除该进程。资源彻底释放释放目前的僵死进程所使用的剩余资源。释放内存页释放内核栈和 thread_info结构所占的页。释放缓存释放 task_struct所占的 slab 高速缓存。**③ 孤儿进程处理 **若父进程在子进程结束前退出子进程成为“孤儿进程”。必须为孤儿进程找到新的父进程否则它们将永久处于僵死状态 (Memory Leak)。寻父机制在 do_exit()中调用 exit_notify()- forget_original_parent()- find_new_reaper()。寻父优先级线程组内其他线程若当前线程组有其他存活线程则过继给它们。init 进程若无其他线程最终过继给 PID 为 1 的 init 进程。init 的职责init进程会例行调用 wait()来检查并清理其名下的僵死子进程确保系统资源被回收。Ptrace 特殊处理被调试ptrace的进程若父进程退出会先在 ptrace 子进程链表中搜索兄弟进程最后同样由 init兜底。程**若无其他线程最终过继给 PID 为 1 的 init 进程。init 的职责init进程会例行调用 wait()来检查并清理其名下的僵死子进程确保系统资源被回收。Ptrace 特殊处理被调试ptrace的进程若父进程退出会先在 ptrace 子进程链表中搜索兄弟进程最后同样由 init兜底。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询