入门:
一 Linux操作系统进程和线程的概念
程和线程的关系就好比是工厂车间和车间工人的关系,进程就像是一个工厂车间,线程就像是车间里的工人,每个工厂车间有一个入口和出口,这就好比执行进程程序的主函数;每个工厂车间都有自己的地址空间,这个空间里边可以包含不同工种的工人,这就好比一个进程的地址空间,包含文本区域,数字区域,堆栈;一个工厂车间可以容纳1个或n车间工人,进程和线程是一对一或一对多的关系,一个进程至少包含一个线程;车间里的工人共享车间里的空间,这象征着一个进程的内存空间是共享的,每个线程都可以使用共享内存;每个车间可以供不同的工人使用,但每个车间的大小不一,容纳人数都有上限,比如说每个厕所可以容纳1人,每个厨房可以容纳n人,但车间里的每个工人都有上厕所和吃饭的需求,那怎么解决这个问题呢?分批次进行!这就好比线程里的锁机制,当n个线程争夺同一资源时,就在这个资源上加把锁,当线程使用完毕,资源释放后才会供给后边的资源使用。有人可能会问,怎么确定使用该资源的先后顺序呢?按照优先级的高低来确定,优先级高的先使用,优先级低的后使用,同一级别按照先来后到的顺序使用。
我们大致对进程和线程有一个基本的概念之后,接下来再来看下进程和线程之间的区别:
(1)进程的执行过程是顺序执行的,虽然在执行过程中可能发生中断或暂停,但该进程所拥有的资源只为该线状执行过程服务。就好比一次只能给一个车间供电的工厂,当一个车间A正在工作时,另外一个更高级的车间B也要开启工作时,那么此时车间A就要断电,但车间A的一切设施和位置都不会发生变化,等车间B断电后,车间A继续工作。这是进程宏观上的线性执行过程。而线程的改变只是改变了CPU执行过程,而没有发生进程所拥有资源的变化。除了CPU之外,计算机内的软硬件资源的分配与线程无关,线程只能共享它所属进程的资源。这就好比一个车间里的工人,他们可以互换位置,但他们还是在同一车间。
(2)进程在执行过程中与线程还是有区别的。进程是执行中的程序,每个独立的进程有一个程序运行的入口、顺序执行序列和程序的出口,这就是程序中的主函数。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。就好比每个车间都有一个进口和出口,可以单独生产一件产品,但这依赖于车间里的工人协同工作才能完成。
(3)通过进程和线程的执行过程我们可以看出,进程和线程是一对一或一对多的关系,一个进程至少包含一个线程,进程拥有一个完整的虚拟地址空间,它的空间大小是在设计它事就已经确定的,不随工人的多少,体积大小而改变,也就是说,不依赖于线程而独立存在;反之,线程是进程的一部分,没有自己的地址空间,与进程内的其他线程一起共享分配给该进程的所有资源。
(4)线程在很少做进程调度和切换的实时系统中可以有效地提高系统的执行效率,但并不是在所有计算机系统中都是适用的。这就好比同一车间工人总是做同一种产品的产能要比经常切换车间,切换工种,做不同产品的产能要高,因为他们更换车间,熟悉环境,熟悉生产流程都需要花时间。这也就是说线程的创建要比进程的创建开销要小的多。
(5)从逻辑角度来看,多线程的意义在于一个应用程序中,他们可以实现应用程序的多个功能,但并不能实现一个完整的应用程序。就好比生产一个复杂的产品,每个车间只是生产该产品一个或多个零部件,一个完成的产品还是要靠整个工厂来完成。换言之,进程的调度和管理以及资源分配还是要靠操作系统来完成,这就是进程和线程的重要区别。
二 Linux进程/线程切换调度的基本知识
1.进程是资源分配的基本单位
2.线程是CPU调度的基本单位
3.一个进程下可能有多个线程
4.线程共享进程的资源
使用fork创建进程,使用pthread_create创建线程。两个系统调用最终都都调用了do_dork,而do_dork完成了task_struct结构体的复制,并将新的进程加入内核调度。
三 进程间通信的基本知识,如管道、UnixSocket、消息队列、共享内存
进程间通信:进程之间的沟通交流
进程间为什么要沟通交流?
在实际工作中往往会出现在一个系统中好几个进程协同工作,那么这些进程就需要沟通交流,完成协作,而由于进程的独立性, 进程间的沟通变得困难,复杂。因此就产生了各种进程间通信方式,来解决如何进行进程间通信的问题。
进程间通信的目的:
数据传输:一个进程需要将它的数据发送给另一个进程;
资源共享:多个进程间共享同样的资源;
通知事件:一个进程需要向另一个或一组进程发消息,通知它们发生了某种事件(如进程终止时要通知父进程)。
进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变。
进程间通信方式:
1.管道
管道:传输资源。本质上是内核的一块缓冲区。(特性:半双工,单向通信)。 Linux一切皆文件,操作系统为管道提供操作的方法:文件操作
⽤用fork来共享管道原理
管道分为:匿名管道/命名管道
匿名管道
没有名字的管道(仅用于具有亲缘关系(父子,兄弟等)的进程间通信)。
1.只能用于具有亲缘关系的进程间通信;
2.管道是半双工单向通信;(两个文件描述符,用一个,另一个不用,不用的文件描述符就要close)
3.管道的生命周期随进程(打开管道的所有进程退出,管道释放);
4.管道是面向字节流传输数据。(面向字节流:数据无规则,没有明显边界,收发数据比较灵活:对于用户态,可以一次性发送也可以分次发送,当然接受数据也如此;而面向数据报:数据有明显边界,数据只能整条接受 )
5.内核会对管道操作进行同步与互斥;
命名管道
命名管道:文件系统可见,是一个特殊类型(管道类型)文件,命名管道可以应用于同一主机上任意进程间通信。
UnixSocket:
https://blog.csdn.net/Nurke/article/details/77621782
消息队列:
1.通过异步处理提高系统性能(削峰、减少响应所需时间);2.降低系统耦合性。
不直接读写数据库 中间要有一个reids
缓存穿透:过滤Key 布隆过滤器
共享内存:
共享内存,顾名思义就是允许两个不相关的进程访问同一个逻辑内存,共享内存是两个正在运行的进程之间共享和传递数据的一种非常有效的方式。
特别提醒:共享内存并未提供同步机制,也就是说,在第一个进程结束对共享内存的写操作之前,并无自动机制可以阻止第二个进程开始对它进行读取,所以我们通常需要用其他的机制来同步对共享内存的访问,例如信号量。
四:协成
协程可以理解为纯用户态的线程,其通过协作而不是抢占来进行切换。相对于进程或者线程,协程所有的操作都可以在用户态完成,创建和切换的消耗更低。Swoole可以为每一个请求创建对应的协程,根据IO的状态来合理的调度协程,这会带来了以下优势:
开发者可以无感知的用同步的代码编写方式达到异步IO的效果和性能,避免了传统异步回调所带来的离散的代码逻辑和陷入多层回调中导致代码无法维护。
五 swoole使用
连接tcp
//创建Server对象,监听 127.0.0.1:9501端口
$serv = new Swoole\Server("127.0.0.1", 9501);
//监听连接进入事件
serv, $fd) {
echo "Client: Connect.\n";
});
//监听数据接收事件
serv, from_id, serv->send(data);
});
//监听连接关闭事件
serv, $fd) {
echo "Client: Close.\n";
});
//启动服务器
$serv->start();
连接 UDP
https://wiki.swoole.com/wiki/page/477.html
六 工具
netstat是一个用来查询网络状态的重要工具,是一个控制台命令,是一个监控TCP/IP网络中非常有用的 工具,它可以显示路由表、实际的网络连接以及每一个网络接口设备的状态信息。可以让用户知道哪些网络连接正在运作,使用的时候如果不带参数,netstat用来显示活动的TCP连接。netstat用于显示IP、TCP、UDP和CMP协议相关的统计数据,一般用于检验本机各端口的网络连接情况。
七 异常
无法连接到服务器的简单检测手段
在Linux下,使用netstat -an | grep 端口,查看端口是否已经被打开处于Listening状态
上一步确认后,再检查防火墙问题
注意服务器所使用的IP地址,如果是127.0.0.1回环地址,则客户端只能使用127.0.0.1才能连接上
用的阿里云服务或者腾讯服务,需要在安全权限组进行设置开发的端口
网友评论