进程和线程的简单解释(下面会有一些有趣的解释)计算机的核心是CPU,它承担着所有的计算任务,就像一个工厂,一直在运转假设工厂的力量是有限的,只能供应A车间使用。也就是说,当一个车间开始工作时,其他车间必须停止工作。其背后的含义是,单核CPU一次只能运行一个任务进程,就像工厂车间一样,代表CPU能够处理的单个任务。任何时候,CPU总是运行一个进程,其他进程都处于非运行状态。在一个车间里,可以有很多工人,他们合作完成一项任务。线程就像车间里的工人。一个进程可以包含多个线程。车间内的空间由工人共享。比如很多房间可以由每个worker进出,这象征着一个进程的内存空间是共享的,每个线程都可以使用共享的内存。但是每个房间的大小都不一样,有的房间最多只能住一个人,比如厕所。里面有人的时候,其他人是进不来的。这意味着当一个线程使用了一些共享内存时,其他线程必须等待它结束才能使用这块内存。防止他人进入的一个简单方法是在门上加一把锁。上锁后,在门口排队,等开锁后才能进入。这叫做“互斥锁”,防止多个线程同时读写某个内存区域。还有一些房间可以同时容纳N个人,比如厨房。也就是说,如果人数大于N,多出来的人只能在外面等着。和。这就像某些内存区域,只能提供给固定数量的线程。这时候的解决办法就是在门口挂N把钥匙。有进取心的人拿一把钥匙,出来的时候把钥匙挂回去。当后来到的人发现钥匙是空的时,他就知道必须在门口排队等候了。这个方法叫做“semaphore”来保证multiple不难看出,“mutex”是“semaphore”的特例(当N=1时),也就是说可以用后者代替前者,但由于“互斥”相对简单高效,所以在资源独占的情况下,操作系统仍然采用这种设计,所以归纳为三点:以多进程的形式,允许多个任务以多线程的形式同时运行,是允许的,但是任务分成不同的部分运行,提供协调机制。一方面,它防止了进程和线程之间的冲突,另一方面,它允许进程和线程之间共享资源。以上内容来自对进程和线程的简单讲解。进程,线程之间的关系。比如打开Word的任务是打开一个进程,但是在操作Word的时候,可以同时进行打字、拼写检查等操作。像这样,在一个进程内部,同时运行着多个“子任务”。从上面的例子我们可以知道一个进程是由多个线程组成的。一个进程必须至少有一个线程。实际上,线程是操作系统中最小的执行单元。进程和线程的区别。进程之间不共享任何状态。进程的调度由操作系统完成,每个进程都有自己独立的内存空间。入口与场地之间的通信主要通过信号传输的方式实现。实现方式有很多种,比如信号量、管道、事件等,任何一种方法的通信效率都需要通过内核,导致通信效率比较低。因为是一个独立的内存空间,所以上下文切换时需要先保存调用栈的信息,各个CPU寄存器的信息,虚拟内存,打开相关句柄,所以上下文进程在它们之间切换的开销为很高,沟通很麻烦。线程间的共享变量解决了通信麻烦的问题。需要锁定对变量的访问。一个进程可以有多个线程,但是每个线程都会共享父进程向系统申请资源。这包括虚拟内存、文件等,因为是共享资源,所以创建一个线程所需要的系统资源比一个进程要小很多,相应的可以创建的线程数也变得比较大。另外在调度方面,因为内存是共享的,切换上下文的时候需要保存。东西比较少,让上下文切换变得更有效率。进程基础知识所谓进程,其实就是操作系统中运行的程序。在终端中,通过php运行一个php文件,相当于创建了一个进程。该进程将存储在系统中,应用程序属于它。自身的内存空间、系统资源以及运行相应的程序对于一个进程来说,它的核心内容分为两部分:一是它的内存,这块内存是进程创建的时候从系统分配的,会存放所有创建的变量在这片内存环境中;另一个是它的上下文环境,我们知道进程是运行在操作系统中的,所以对于程序来说,它的运行依赖于操作系统分配给它的资源,操作系统的一些状态。操作系统中可以运行多个进程。对于一个进程,他可以创建自己的子进程。当我们在一个进程中创建多个子进程时,子进程和父进程一样,都有自己的内存空间。以及上下文环境:如图:父子进程和子进程会复制父进程的内存空间和上下文环境。子进程会复制父进程的IO句柄,即fd描述符。不受影响。修改子进程的内存空间不会修改父进程或其他子进程的内存空间。例如:父进程通过fopen打开文件后得到一个IO句柄fd,子进程复制父进程后也会得到这个fd。如果父进程和子进程同时对一个文件进行操作,会导致文件混淆,所以需要互斥锁。例如:父进程中的变量x=1,父进程派生子进程后,子进程也会有变量x=1,但修改父进程中的变量x不会影响变量x的值子进程中的变量x。Swoole的进程结构Swoole的高效不仅仅是底层用C写的,它的进程结构模型也让它能够高效的处理业务;进程结构图:Swoole这些进程的作用:Master进程:主进程第一层:master进程,这是swoole的主进程。这个过程是由swoole的核心事件处理驱动的。在这个过程中,可以看出它有一个MainReactor和若干个Reactor。所有swoole监听的事件都会在这些线程中实现,比如客户端连接,信号处理等。Master进程是一个多线程程序。注意:按照我们之前的理解,多个线程运行在单个进程的上下文中。事实上,单个进程中的每个线程都有自己的上下文,但是因为它们共存于同一个进程中,所以它们也共享这个进程,包括它的代码、数据等等。回来继续说Master进程。Master进程是我们的主进程,它掌管着生死。如果挂了,那下面的一切都得完蛋了。Master进程,包括主线程、多个Reactor线程等,每个线程都有自己的用途。例如主线程用于Accept、信号处理等操作,而Reactor线程是处理tcp连接、处理网络IO、收发数据的线程。说明两点:主线程的accept操作,socket服务器经常使用accept来阻塞,上一节介绍socket编程的时候有一张图,可以看看信号处理,信号相当于一个消息,比如我们经常操作的Ctrl+C其实就是给Master进程的主线程发送一个SIGINT信号,也就是说你可以终止它。信号有很多种,后面会有介绍。通常,主线程处理完一个新的连接后,会把这个连接分配给一个固定的Reactor线程,这个Reactor线程会一直负责监听这个socket(上面socket更新为socket,是用到的一个文件用于与另一个进程的跨网络通信,且文件可读可写),也就是说,当socket可读时,会读取数据,并将请求分配给worker进程,这就解释了第三个参数$worker进程中回调onReceive的fromId在第一篇介绍swoole中解释过的意思;当套接字可写时,数据将发送到tcp客户端。Managerprocess:管理进程我们知道,在Master-Worker模型中,只有一个Master,Worker是从父进程Master进程复制过来的,可以有多个Worker进程。注意:在Linux中,父进程可以通过调用fork函数来创建新的子进程。子进程是父进程的副本,它们几乎相同但不完全相同。两者最大的区别在于它们都有自己独立的进程ID,即PID。对于多线程的Master进程,如果要多个Worker进程,就必须fork操作,但是fork操作是不安全的。所以在swoole中,有一个专职的Manager进程,Manager进程负责worker/task进程。分叉操作和管理。也就是说,“保姆”Manager进程拥有全权管理worker进程的创建和回收。通常是由于程序原因,worker进程被意外杀死或异常退出。为了保证服务的稳定性,Manager进程会重启一个新的worker进程。“死”,可以叉出千千万万个你。当然,我们不太关心Master进程和Manager进程。业务逻辑的真正实现是在工作进程/任务进程中完成的。Manager进程与worker/task进程的关系Worker进程:Worker进程worker进程属于swoole的主逻辑进程。用户处理来自客户端的系统请求,接受Reactor线程投递的请求包,执行PHP回调函数处理数据并产生响应数据并发发送给Reactor线程,Reactor线程发送到TCP客户端。可以是异步非阻塞模式,也可以是同步阻塞模式。任务进程:异步任务worker进程taskWorker是swoole提供的异步工作进程。为了处理一些比较耗时的同步任务,可以在worker进程中传递更多的学习内容。可以访问码农到架构师的培养路径
