免费服装网站模板,织梦网站如何做二级导航栏,购买网域名的网站好,外贸网站建设软件有哪些目录
进程、线程和协程的区别
线程和进程的区别
进程
线程
进程间通信方式
线程同步机制
守护进程、僵尸进程、孤儿进程
进程/线程切换过程切换的资源有哪些 进程、线程和协程的区别 进程 线程 协程 定义 资源分配和拥有的基本单位 程序执行的基本单位 用户态的轻…目录
进程、线程和协程的区别
线程和进程的区别
进程
线程
进程间通信方式
线程同步机制
守护进程、僵尸进程、孤儿进程
进程/线程切换过程切换的资源有哪些 进程、线程和协程的区别 进程 线程 协程 定义 资源分配和拥有的基本单位 程序执行的基本单位 用户态的轻量级线程线程内部调度的基本单位 切换情况 进程CPU环境(栈、寄存器、页表和文件句柄等)的保存以及新调度的进程CPU环境的设置 保存和设置程序计数器、少量寄存器和栈的内容 先将寄存器上下文和栈保存等切换回来的时候再进行恢复 切换者 操作系统 操作系统 用户 切换过程 用户态-内核态-用户态 用户态-内核态-用户态 用户态(没有陷入内核) 调用栈 内核栈 内核栈 用户栈 拥有资源 CPU资源、内存资源、文件资源和句柄等 程序计数器、寄存器、栈和状态字 拥有自己的寄存器上下文和栈 并发性 不同进程之间切换实现并发各自占有CPU实现并行 一个进程内部的多个线程并发执行 同一时间只能执行一个协程而其他协程处于休眠状态适合对任务进行分时处理 系统开销 切换虚拟地址空间切换内核栈和硬件上下文CPU高速缓存失效、页表切换开销很大 切换时只需保存和设置少量寄存器内容因此开销很小 直接操作栈则基本没有内核切换的开销可以不加锁的访问全局变量所以上下文的切换非常快 通信方面 进程间通信需要借助操作系统 线程间可以直接读写进程数据段(如全局变量)来进行通信 共享内存、消息队列 线程和进程的区别
执行单元:进程是操作系统资源分配的基本单位是一个完整的运行环境而线程则是任务调度和执行的基本单位。资源分配和管理:每个进程都有自己的独立的进程地址空间、系统资源和文件描述符表而线程共享进程的资源。但每个线程各自都有一套独立的寄存器和栈因此进程之间的切换需要一定的时间和开销而线程之间的切换则相对快速和轻量级。由于同一进程的各线程间共享内存和文件资源那么在线程之间数据传递的时候就不需要经过内核了这就使得线程之间的数据交互效率更高了通信方式:进程间通信需要特定的机制如管道、消息队列、共享内存、信号量等。同个进程下的线程之间都是共享进程的资源只要是共享变量都可以做到线程间通信比如全局变量所以对于线程间关注的不是通信方式而是关注多线程竞争共享资源的问题信号量也同样可以在线程间实现互斥与同步安全性:由于进程之间是相互隔离的因此一个进程中的代码不会对其他进程产生影响而线程之间则可能会相互干扰或者造成数据不一致等问题。一个线程的错误可能会导致整个进程崩溃。从内核的角度来说Linux把所有的线程都当做进程来实现。内核并没有准备特别的调度算法或是内存管理机制来处理线程而是和进程一样使用相同的调度算法和内存管理机制。 进程
进程是操作系统中的一个独立的执行单元它包含了程序的代码、数据以及一些运行时的状态信息。每个进程都有自己的内存空间独立于其他进程使其能够互相隔离。
进程可以通过多种方式创建包括通过shell命令启动程序、由其他进程派生fork新进程。新进程拥有自己的进程标识符PID。
操作系统对进程的管理方法是先描述再组织。创建一个进程实际上就是先将进程的代码和数据加载到内存上接着操作系统对该进程进行描述形成对应的PCBPCB是对进程控制块的统称Linux下描述进程控制块的结构体叫做task_struct。在Linux的根目录下有proc文件这个文件里面就包含大量的进程信息可以使用ps命令来查看进程信息
进程在其生命周期中可以处于不同的状态包括就绪态、运行态、等待态等。就绪态表示进程已准备好执行但尚未获得CPU时间片运行态表示进程正在执行等待态表示进程正在等待某个事件的发生。
操作系统负责调度进程以便它们可以共享CPU时间。进程调度算法决定了哪个进程获得CPU时间通常使用抢占式调度算法。
进程可以通过多种方式进行通信包括管道、套接字、消息队列、共享内存等。这些机制允许进程在不同的地址空间中传递数据和信息。
进程可以正常退出也可以被强制终止。当进程完成其工作或者遇到错误时它会释放其资源并终止。操作系统也可以通过发送信号来终止进程。
系统管理员可以使用工具来监控和管理系统中的进程例如ps、top、kill等命令。这些工具允许管理员查看进程的状态、资源使用情况以及终止不需要的进程。 线程
线程是进程内的一个独立执行单元它与同一进程中的其他线程共享相同的进程内存空间。线程包含了程序代码、数据以及一些运行时状态信息因此线程比进程更轻量级创建和切换开销较小可以更有效地利用系统资源。但它们与进程内的其他线程共享相同的资源如文件描述符和全局变量。
Linux下的线程是最小的执行单位调度的基本单位。从内核的角度来说Linux把所有的线程都当做进程来实现。内核并没有准备特别的调度算法或是内存管理机制来处理线程而是和进程一样使用相同的调度算法和内存管理机制。
线程有自己的生命周期包括创建、就绪、运行、阻塞和终止。线程可以被创建、启动、暂停、恢复和终止。
多个线程共享进程内存因此需要进行同步以避免数据竞争和冲突。常见的同步机制包括互斥锁、条件变量、信号量和读写锁等这些机制用于控制线程对共享资源的访问。线程可能引入竞争条件和死锁需要仔细设计和测试多线程应用。
操作系统负责线程的调度以确定哪个线程获得CPU时间片执行。调度算法通常以优先级、时间片轮转等方式决定线程执行的顺序。
多线程应用程序对于用户输入和外部事件的响应更快因为一个线程的阻塞不会影响其他线程的执行。
线程比进程更轻量级创建和切换开销较小可以更有效地利用系统资源。 进程间通信方式
进程间通信就是在不同进程之间传播或交换信息。进程间通信的本质就是让不同的进程看到同一份资源。
匿名管道
shell 命令中的「|」竖线就是匿名管道通信的数据是无格式的流并且大小受限通信的方式是单向的数据只能在一个方向上流动再来匿名管道是只能用于存在父子关系的进程间通信或者具有共同祖先的进程之间通信
pipe 函数用于创建匿名管道管道只能够进行单向通信因此当父进程创建完子进程后需要确认父子进程谁读谁写然后关闭相应的读写端。
命名管道
命名管道突破了匿名管道只能在亲缘关系进程间的通信限制因为使用命名管道的前提需要在文件系统创建一个类型为 p 的设备文件那么毫无关系的进程就可以通过这个设备文件进行通信。通信数据都遵循先进先出原则。
可以使用 mkfifo 创建一个命名管道。
消息队列
消息队列克服了管道通信的数据是无格式的字节流的问题消息队列实际上是保存在内核的「消息链表」。消息队列通信的速度不是最及时的毕竟每次数据的写入和读取都需要经过用户态与内核态之间的拷贝过程。消息队列提供了一种异步通信的机制所以通信速度不及时
比如A 进程要给 B 进程发送消息A 进程把数据放在对应的消息队列后就可以正常返回了B 进程需要的时候再去读取数据就可以了。同理B 进程要给 A 进程发送消息也是如此。
共享内存
共享内存可以解决消息队列通信中用户态与内核态之间数据拷贝过程带来的开销它直接分配一个共享空间每个进程都可以直接访问, 而无需数据复制和内核参与。享有最快的进程间通信方式之名。但是便捷高效的共享内存通信带来新的问题多进程竞争同个共享资源会造成数据的错乱。
创建共享内存我们需要用 shmget 函数
信号量
那么就需要信号量来保护共享资源以确保任何时刻只能有一个进程访问共享资源这种方式就是互斥访问。信号量其实是一个计数器表示的是资源个数其值可以通过两个原子操作来控制分别是 P 操作和 V 操作。
减减的操作就叫做 P 操作而计数器加加的操作就叫做 V 操作P操作就是申请信号量而V操作就是释放信号量。P等待操作用于尝试获取资源或者等待某个条件成立如果资源不可用或条件不成立则会阻塞。V发信号操作用于释放资源或者通知条件成立如果有其他进程正在等待则唤醒其中一个。
信号是异步通信机制一旦有信号发生进程有三种方式响应信号 1. 执行默认操作、2. 捕捉信号、3. 忽略信号。有两个信号是应用进程无法捕捉和忽略的即 SIGKILL 和 SIGSTOP这是为了方便我们能在任何时候结束或停止某个进程。
Socket 通信
Socket 实际上不仅用于不同的主机进程间通信还可以用于本地主机进程间通信可根据创建 Socket 的类型不同分为三种常见的通信方式一个是基于 TCP 协议的通信方式一个是基于 UDP 协议的通信方式一个是本地进程间通信方式。 线程同步机制
用于协调多个线程的执行以确保数据的正确性和一致性。
互斥锁
互斥锁是最常见的线程同步机制。它允许多个线程访问共享资源但在任何给定时刻只有一个线程可以进入临界区被保护的代码段。其他线程需要等待锁的释放才能进入临界区。
信号量
信号量是一种更通用的同步工具它可以控制同时访问共享资源的线程数量。
条件变量
条件变量用于在线程之间进行复杂的协调。它通常与互斥锁一起使用允许线程等待特定条件的发生并在条件满足时被唤醒。
读写锁
读写锁允许多个线程同时读取共享资源但只有一个线程可以写入资源。这对于读多写少的场景非常有用可以提高性能。
自旋锁
自旋锁是一种锁定机制它不会使线程休眠而是在获取锁失败时一直循环尝试直到成功。自旋锁在短期争用情况下可能效率更高但需要小心避免长时间的自旋。 守护进程、僵尸进程、孤儿进程
守护进程
是对立于控制终端并且周期性的执行某种任务的进程
指在后台运行的没有控制终端与之相连的进程。它独立于控制终端周期性地执行某种任务。Linux的大多数服务器就是用守护进程的方式实现的如web服务器进程http等
孤儿进程
如果父进程先退出子进程还没退出那么子进程的父进程将变为init进程。注任何一个进程都必须有父进程。
一个父进程退出而它的一个或多个子进程还在运行那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养并由init进程对它们完成状态收集工作。
僵尸进程
父进程不读取子进程的退出信息子进程就会变成僵尸进程进而造成资源的浪费
父进程可以使用waitpid来等待子进程的退出设置WNOHANG为非阻塞等待
如果子进程先退出父进程还没退出那么子进程必须等到父进程捕获到了子进程的退出状态才真正结束否则这个时候子进程就成为僵尸进程。
设置僵尸进程的目的是维护子进程的信息以便父进程在以后某个时候获取。这些信息至少包括进程ID进程的终止状态以及该进程使用的CPU时间所以当终止子进程的父进程调用wait或waitpid时就可以得到这些信息。如果一个进程终止而该进程有子进程处于僵尸状态那么它的所有僵尸子进程的父进程ID将被重置为1init进程。继承这些子进程的init进程将清理它们也就是说init进程将wait它们从而去除它们的僵尸状态。
进程一旦变成僵尸进程kill -9 SIGKILL也无法将其杀死因为谁也无法杀死一个已经死去的进程。 进程/线程切换过程切换的资源有哪些
进程/线程上下文切换是操作系统进行任务切换时保存当前任务的状态并加载下一个任务的状态的过程。在上下文切换过程中操作系统需要保存和恢复的资源包括
寄存器
包括通用寄存器如PC、SP等和特殊寄存器如状态寄存器、控制寄存器等。保存当前任务的寄存器状态并加载下一个任务的寄存器状态。
程序计数器PC
保存当前任务执行的下一条指令的地址以便在切换回来时继续执行。
栈指针SP
保存当前任务的栈指针以便在切换回来时继续使用该任务的栈。
内存管理单元MMU
保存当前任务的页表、段表等内存管理信息以便在切换回来时继续使用该任务的内存映射。
文件描述符表
保存当前任务打开的文件描述符信息以便在切换回来时继续使用。
环境变量
保存当前任务的环境变量信息以便在切换回来时继续使用。
其他资源
如信号处理函数、定时器、硬件中断等需要保存当前任务的相关状态并在切换回来时继续处理。
需要注意的是不同操作系统和架构可能会有略微不同的上下文切换过程和需要保存的资源上述列举的是一般情况下的常见资源。