一文读懂Linux中的进程、线程

news2024/11/28 4:48:30

一文读懂Linux中的进程、线程

大家好,我是木荣君,这次我们来聊一聊Linux中进程和线程。进程和线程的概念非常重要,本篇来详细介绍下这两者的概念。我们在实际开发中,经常会听到这两个词,如果我们不了解这些词背后的概念,那么不能称之为一个合格的软件工程师。

程序

简单来说,程序可以描述为存在磁盘文件中的任何可执行文件。它包含一组完成特定的操作指令集合。它是一个被动的实体,不会因操作系统重新启动而消失。计算机中的多任务操作就是指用户可以在同一时间内运行多个应用程序,每个正在执行的应用程序被称为一个任务。Linux就是一个支持多任务的操作系统,比起单任务系统它的功能增强了许多。多任务操作系统使用某种调度策略支持多个任务并发执行。事实上,单核处理器在某一时刻只能执行一个任务。每个任务创建时被分配时间片(ms级),任务执行(占用CPU)时,时间片递减。操作系统会在当前任务的时间片用完时调度执行其他任务。由于任务会频繁地切换执行,因此给用户多个任务同时运行的感觉。

程序、进程和线程之间的关系如下图所示

在这里插入图片描述

进程

进程:程序的执行实例,是指一个具有独立功能的程序在某个数据集合上的一次动态执行过程,它是操作系统进行资源分配的基本单元。进程是应用程序运行的载体。进程是一种抽象的概念,从来没有统一的标准定义。

进程具有的特征:

  • 动态性:进程是程序的一次执行过程,是临时的,有生命期的,是动态产生和消亡的;
  • 并发性:任何进程都可以同其他进程一起并发执行;
  • 独立性:进程是系统进行资源分配的基本单位;
  • 结构性:进程由指令集、数据和进程控制块三部分组成。

进程状态

Linux系统下我们可以通过ps命令查看进程的状态信息

状态含义
R, TASK_RUNNING就绪态或者运行态,进程就绪可以运行,但是不一定正在占有CPU
S, TASK_INTERRUPTIBLE浅度睡眠,等待资源,可以响应信号,一般是进程主动sleep进入的状态
D, TASK_UNINTERRUPTIBLE深度睡眠,等待资源,不响应信号,典型场景是进程获取信号量阻塞
Z, TASK_ZOMBIE僵尸态,进程已退出或者结束,但是父进程还不知道,没有回收时的状态
T, TASK_STOPED停止,调试状态,收到SIGSTOP信号进程挂起

Linux下进程相关API

API作用
system()通过调用shell启动一个新进程
exec()以替换当前进程映像的方式启动一个新进程
fork()以复制当前进程映像的方式启动一个新进程,子进程中fork()返回0,父进程fork()返回为子进程ID
wait()父进程挂起,等待子进程结束

特殊进程

孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。孤儿进程不会浪费资源。
僵尸进程:一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵尸进程。

进程间通信

  • 信号
    进程里可以捕捉到信号进行相应处理。

  • 管道PIPE
    管道的操作也是类似文件的操作。popen()函数类似于fopen()函数,返回的是对象指针。pipe()函数类似于open()函数,返回的是对象描述符。
    管道是在亲属进程(同一父进程创建出的相关进程)之间进行数据传输的。

  • 命名管道FIFO
    命名管道可用于无亲属关系的进程间通信。mkfifo()/mknod()将在文件系统中创建一个有路径和名称的文件。把这个管道文件当作普通文件用就行了,就可以实现进程间通信。

  • 信号量
    信号量是一个特殊的变量,程序对其访问都是原子操作,且只允许对它进行等待(即P(信号变量))和发送(即V(信号变量))信息操作。

  • 消息队列
    消息队列独立于进程而存在。

  • 共享内存
    通信的进程间共享一块内存进行数据交换

进程的内存模型

在这里插入图片描述

  • 在32位的操作系统中每一个进程的虚拟地址空间为4GB。其中1G为内核空间3G为用户空间,每一个进程的用户空间又可以分为:用户栈、共享库、用户堆、数据段和代码段。

  • 用户栈:用来保存各种了临时数据,包括函数中的参数传递,和函数内的局部变量。栈的扩展方向是自顶向下,栈底地址为高地址,栈顶为低地址,栈的出入遵循先进后出原则。

  • 共享库:用来保存程序执行时所需要依赖的共享代码库,这些代码库文件的实际地址会被会被映射到用户栈下方的虚拟地址,并被标记为只读。

  • 用户堆:它管理的是用户程序在运行过程中动态分配的内存,需要时可以通过手动申请,用完之后在手动清空。堆的扩展方向与栈相反,堆底在低地址,堆顶在高地址,当用户申请内存,堆顶指针会向上生长。

  • 数据段:主要保存的是程序中的全局变量、静态变量以及字符串常量,这些变量的生存周期通常是伴随程序的整个运行周期。

  • 代码段:代码段主要保存的是编译完成的二进制代码。

内核地址空间在进程用户态运行时通常是不可见的,只有进程进入到内核态时才能进行内核内存访问。

线程

线程-也是操作系统提供的抽象概念,是程序执行中一个单一的顺序控制流程,是程序执行流的最小单元,是处理器调度和分派的基本单位。一个进程可以有一个或多个线程,同一进程中的多个线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等。但同一进程中的多个线程有各自的调用栈和线程本地存储

线程相比进程的优势

  • 线程会共享内存地址空间。
  • 创建线程花费的时间要少于创建进程花费的时间。
  • 终止线程花费的时间要少于终止进程花费的时间。
  • 线程之间上下文切换的开销, 要小于进程之间的上下文切换。
  • 线程之间数据的共享比进程之间的共享要简单。
  • 充分利用多处理器的可并行数量。线程会提高运行效率,但当线程多到一定程度后,可能会导致效率下降,因为会有线程调度切换。

线程的缺点

  • 健壮性降低:多个线程之中, 只要有一个线程不够健壮存在bug就会导致整个进程挂掉

  • 线程模型作为一种并发的编程模型,效率并没有想象的那么高。多线程复杂度高、易出错,而且多线程难以测试和定位的问题。

通过我们巧妙的编程可以避免线程带来的缺点,合理利用多线程可以达到事半功倍的效果。而工作中多线程是不可避免的方式。

线程内存空间布局

在这里插入图片描述

线程创建

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);

参数
1、thread:线程标识符,是一个出参
2、attr:线程属性
3、star_routine:函数指针,保存线程入口函数的地址
4、arg:给线程入口函数传参
返回值:成功返回0,失败返回

创建线程时传入参数注意

  • 不可以传入临时变量。临时变量是有生命周期的,值也会改变,可能导致内存问题。
  • 结构体变量。原因和临时变量一样。
  • 可以使用堆上申请的变量。
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>

void *ThrFun(void *arg)
{
    int *p = (int*)arg;

    printf("this is thread function:%p, data:%d\n",pthread_self(),*p);

    pthread_exit(NULL);
}
int main()
{
    int i = 1;
    pthread_t thrId;

    // 不要出入临时变量i
    int ret = pthread_create(&thrId, NULL, ThrFun, (void*)&i);

    if(ret != 0)
    {
        perror("pthread_create");
        return -1;
    }
    while(1)
    {
        sleep(1);
    }

    return 0;
}

线程退出

#include <pthread.h>
void pthread_exit(void * rval_ptr)
参数说明:
rval_ptr:线程返回值,由调用pthread_join()的线程获取。
注:调用在线程内调用此函数,相当于直接调用了return,但不同的是在线程中的任意函数调用了pthread_exit()都具有退出线程的同样效果。

获取线程ID

pthread_t pthread_self(void);
返回值:返回当前线程的ID

判断两个线程ID是否相同

int pthread_equal(pthread_t t1,pthread_t t2);
参数说明:
t1:线程1的ID
t2:线程2的ID
返回值:0表示不相等,不为0表示相等
注:pthread_tunsigned long类型 ,但不能通过值是否相等来简单的判断t1、t2是否相等,需要通过此函数判断。

终止线程

int pthread_join( pthread_t thread_id, void **retvalue ); 
参数说明:
thread_id:要连接的线程的ID
retvalue:该值非空时,将保存线程终止前调用returnpthread_exit()时的返回值。
注: 若线程未分离,则必须要调用pthread_join()进行连接,否则在线程终止时将产生僵尸线程。僵尸线程过多将无法创建新的线程
  若传入之间已经连接过的线程ID,将导致无法预知行为。

分离线程

#include<pthread.h>
int pthread_detach(pthread_t thread_id);
参数说明:
thread_id:要分离的线程ID
返回值:0表示成功,或返回大于零的错误码
注:一旦分离,无法恢复可连接状态,它是只影响终止线程以后的事情。
   可以这样使用pthread_detach(pthread_self());

多线程同步

线程同步的两种方式:互斥量(mutex)和条件变量(condition)

互斥量

防止多个线程同时访问同一共享变量

# 创建

静态初始化
pthread_mutex_t mtx=PTHREAD_MUTEX_INITIALIZER;

动态初始化
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr) 
参数说明:
mutex:要初始化的互斥量
mutexattr:互斥量的属性,若为NULL则使用缺省(默认)的属性。
返回值:0表示成功,或返回大于0的错误码
注:
有自动或动态分配的互斥量要使用pthread_mutex_destroy()销毁,静态分配则不需要。
以下情况必须使用动态初始化
- 动态分配在堆中的互斥量
- 互斥量是在栈中分配的自动变量
- 静态分配的互斥量但不使用缺省属性

# 销毁
int pthread_mutex_destroy(pthread_mutex_t *mutex);
参数说明:
mutex:要销毁的互斥量
返回值:0表示成功,或返回大于0的错误码
注:
当互斥量未锁定,且后续无任何线程企图再锁定它时,销毁才安全
若互斥量驻留在动态分配的内存,先销毁再free此内存区域
自动分配的互斥量,在宿主函数返回前销毁
销毁的互斥量可以使用pthread_mutex_init()函数重新初始化,再次使用

# 加锁
int pthread_mutex_lock(pthread_mutex_t *mutex);
参数说明:
mutex:需要加锁的互斥量
返回值:0表示成功,或返回其他大于0的错误码
注:若互斥量未锁定,将锁定并立即返回。若其他线程锁定,调用将阻塞线程直到互斥量被解锁,然后锁定互斥量再返回。 

int pthread_mutex_trylock(pthread_mutex_t *mutex);
参数pthread_mutex_lock()函数一样,但不同的是若互斥量锁定会失败返回EBUSY错误。当轮询调用此函数,若存在其他很多线程使用pthread_mutex_lock等待同一互斥量,可能将永远不能获得上锁权。
尝试加锁,若互斥量已被加锁等待指定时间再返回

int pthread_mutex_timedlock(pthread_mutex_t *restrict mutex,const struct timespec *restrict abstime);
参数:
mutex:互斥量
abstime:超时指定愿意等待的绝对时间(与相对时间对比而言,指定在时间X之前可以阻塞等待,而不是说愿意阻塞Y秒)。这个超时时间是用timespec结构来表示,它用秒和纳秒来描述时间。
成功返回0,失败返回大于0错误码。

# 解锁
int pthread_mutex_lock(pthread_mutex_t *mutex);
参数说明,同加锁
注:不应该解锁未锁定的互斥量
   不应该解锁其他线程锁定的互斥量
   若不止一个线程等待某互斥量解锁,不确定哪个线程上锁该互斥量。

条件变量

条件变量允许一个线程改变某个共享变量时通知其他线程,并让其他线程一直阻塞等待(休眠等待)这一变化状态。条件变量总是与互斥量结合使用。

静态分配条件变量:
pthread_cond_t=PTHREAD_COND_INITIALIZER;

动态分配条件变量:
int pthread_cond_init(pthread_cond_t *cond,pthread_condattr_t *attr);
参数说明:
cond:要初始化的条件变量
attr:初始化的条件变量属性,若为NULL,则使用缺省属性。
返回值:0表示成功,或返回大于0的错误码
注:对已初始化的条件变量,再次初始化,结果行为未定义。


销毁条件变量
int pthread_cond_destroy(pthread_cond_t *cond)
参数说明:与pthread_cond_init()函数对应参数类似。
注:
自动或动态初始化的条件变量应有pthread_cond_destroy()销毁,静态分配的条件变量不用销毁。
应在没有任何线程等待条件变量销毁,动态分配的条件变量应在free前销毁,自动分配的应在宿主函数返回前销毁。
被pthread_cond_destroy()销毁的条件变量,可以再次调用pthread_cond_init()初始化后使用。

# 等待某个条件变量的函数
int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);
参数说明:
cond:指定等待的条件变量
mutex:配合使用的互斥锁,防止多线程pthread_cond_wait()竞争。
返回值:0表示成功,或大于0的错误码
注:
pthread_cond_wait()必须配合pthread_mutex_lock()pthread_mutex_unlock()使用。此函数会阻塞等待直到pthread_cond_signal()pthread_cond_broadcast()通知。
mutex互斥锁必须是普通锁(PTHREAD_MUTEX_TIMED_NP)或者适应锁(PTHREAD_MUTEX_ADAPTIVE_NP),且在调用pthread_cond_wait()前必须由本线程加锁(pthread_mutex_lock()),而在更新条件等待队列以前,mutex保持锁定状态,并在线程挂起进入等待前解锁。在条件满足从而离开pthread_cond_wait()之前,mutex将被重新加锁,以与进入pthread_cond_wait()前的加锁动作对应。

# 带超时条件等待某个条件变量函数
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,const struct timespec   *abstime);
cond:指定等待的条件变量
mutex:配合使用的互斥锁,防止多线程pthread_cond_wait()竞争。
abstime:与pthread_mutex_timelock()对应参数相同
返回值:0表示成功,或大于0的错误码
注:此函数与pthread_cond_wait函数行为类似,超时则返回ETIMEOUT错误码。

#唤醒一个等待该条件的线程
int pthread_cond_signal(pthread_cond_t *cond);
cond:指定唤醒的条件变量
返回值:0表示成功,或大于0的错误码
注:
存在多个等待线程时按入队顺序激活其中一个会存在虚假唤醒、消息遗漏问题。虚假唤醒即多核处理器可能唤醒多个等待同一条件变量的线程,所以需要加入判断条件,例如
    pthread_mutex_lock(&lock);
    while (condition_is_false)
    { 
        pthread_cond_wait(&cond, &lock);
    }
    pthread_mutex_unlock(&lock);
消息遗漏即如果在一个线程调用pthread_cond_wait的过程中但未进入block状态,此时有线程调用了pthread_cond_signal或者pthread_cond_broadcast,那么此次消息将被遗漏掉,因为没有任何线程在pthread_cond_wait的block状态。这类问题的解决办法是设置一个pthread_cond_signal或者pthread_cond_broadcast的计数器count,在调用pthread_cond_wait之前先对这个count进行判断,如果count != 0 则说明已经错过了消息,可以不用等待,直接往下执行即可。例如:
    if (!count)
    {
        pthread_mutex_lock(&lock);
        while (condition_is_false)
        {
            pthread_cond_wait(&cond, &lock);
        }
        pthread_mutex_unlock(&lock);
    }

唤醒所有等待该条件的线程
int pthread_cond_broadcast(pthread_cond_t *cond);
参数说明:
与pthread_cond_wait()函数相同。
注:此函数数推荐使用在所有等待线程执行的任务不同,否则线程处理结果的效率可能不如pthread_cond_signal()
    pthread_mutex_lock(&lock);
    while (condition_is_false)
    {
        pthread_cond_wait(&cond, &lock);
    }
    pthread_mutex_unlock(&lock);
}

唤醒所有等待该条件的线程
int pthread_cond_broadcast(pthread_cond_t *cond);
参数说明:
与pthread_cond_wait()函数相同。
注:此函数数推荐使用在所有等待线程执行的任务不同,否则线程处理结果的效率可能不如pthread_cond_signal()
``

👇👇👇👇👇 点击下方Linux兵工厂,关注去领取海量Linux学习资料和硬核文章 👇👇👇👇👇
在这里插入图片描述----------------------------------------------------------------------------👇👇👇👇👇----------------------------------

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/364351.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深入浅出C++ ——二叉搜索树

文章目录一、二叉搜索树概念二、二叉搜索树操作1. 二叉搜索树的查找2. 二叉搜索树的插入3. 二叉搜索树的删除三、二叉搜索树的实现四、二叉搜索树的性能分析一、二叉搜索树概念 二叉搜索树又称二叉排序树/二次查找树&#xff0c;它是一棵空树或者是每颗子树都具有以下性质的二叉…

Spring Boot 框架 集成 Knife4j(内含源代码)

Spring Boot 框架 集成 Knife4j&#xff08;内含源代码&#xff09; 源代码下载链接地址&#xff1a;https://download.csdn.net/download/weixin_46411355/87480176 目录Spring Boot 框架 集成 Knife4j&#xff08;内含源代码&#xff09;源代码下载链接地址&#xff1a;[htt…

Bmp图片格式介绍

Bmp图片格式介绍 介绍 BMP是英文Bitmap&#xff08;位图&#xff09;的简写&#xff0c;它是Windows操作系统中的标准图像文件格式&#xff0c;能够被多种Windows应用程序所支持。随着Windows操作系统的流行与丰富的Windows应用程序的开发&#xff0c;BMP位图格式理所当然地被…

JetPack板块—Android X解析

Android Jetpack简述 AndroidX 是Android团队用于在Jetpack中开发&#xff0c;测试&#xff0c;打包&#xff0c;发布和版本管理的开源项目。相比于原来的Android Support库,AndroidX 可以称得上是一次重大的升级改进。 和Support库一样&#xff0c;AndroidX与Android 操作系…

投出1000份简历,苦于软件测试没有项目经验,全部石沉大海,辞职5个月,我失业了......

想要找一份高薪的软件测试工作&#xff0c;简历项目必不可少&#xff08;即使是应届生&#xff0c;你也要写上实习项目&#xff09;。所以很多自学的朋友找工作时会碰到一个令人颇感绝望的拦路虎&#xff1a;个人并没有实际的项目工作经验怎么办&#xff1f; 怎么办&#xff1f…

6.1 反馈的基本概念及判断方法

一、反馈的基本概念 1、什么是反馈 反馈也称为 “回授”。在电子电路中&#xff0c;将输出量&#xff08;输出电压或输出电流&#xff09;的一部分或全部通过一定的电路形式作用到输入回路&#xff0c;用来影响其输入量&#xff08;放大电路的输入电压或输入电流&#xff09;…

【软件测试】接口自动化测试你真的会做吗?资深测试工程师的总结......

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 目的&#xff1f; 通…

离线环境拷贝迁移 conda envs 环境(蛮力方法,3行命令)

前言 最近要使用 GPU 服务器做实验&#xff0c;可惜的是&#xff0c;有网络连接的服务器显卡旧&#xff0c;算力不够&#xff1b;显卡较新的机器没有联网。于是有需求将旧机器上配置好的 conda 环境迁移至新机器。网上给的默认方法生成 yaml 文件迁移等 需要联网&#xff0c;只…

孪生生产线:法兰工厂数据驱动的颠覆性创新

2018 年&#xff0c;世界经济论坛(WEF)携手麦肯锡公司共同倡议并正式启动了全球“灯塔工厂网络项目”(Lighthouse Network)&#xff0c;共同遴选率先应用工业革命 4.0 技术实现企业盈利和持续发展的创新者与示范者。这就使得工厂系统需要对各流水线及生产运行成本方面进行多角度…

Neuron Selectivity Transfer 原理与代码解析

paper&#xff1a;Like What You Like: Knowledge Distill via Neuron Selectivity Transfercode&#xff1a;https://github.com/megvii-research/mdistiller/blob/master/mdistiller/distillers/NST.py本文的创新点本文探索了一种新型的知识 - 神经元的选择性知识&#xff0c…

整型在内存中的存储(详细剖析大小端)——“C”

各位CSDN的uu们你们好呀&#xff0c;今天小雅兰的内容是整型在内存中的存储噢&#xff0c;现在&#xff0c;就让我们进入整型在内存中的存储的世界吧 数据类型详细介绍 整型在内存中的存储&#xff1a;原码、反码、补码 大小端字节序介绍及判断 数据类型介绍 前面我们已经学…

【扫盲】数字货币科普对于完全不了解啥叫比特币的小伙伴需要的聊天谈资

很多人并不清楚&#xff0c;我们时常听说的比特币&#xff0c;以太坊币&#xff0c;等等这些东西到底是一场骗局还是一场货币革命&#xff1f; 下面就围绕这数字货币的历史以及一些应用场景开始分析这个问题。 一、 开端 一切从2008年中本聪&#xff08;Satoshi Nakamoto&…

shiro反序列化漏洞与无依赖CB链分析

环境搭建 git clone https://github.com/apache/shiro cd shiro git checkout shiro-root-1.2.4将 shiro/samples/web/pom.xml 中的jstl依赖改为1.2: <dependency><groupId>javax.servlet</groupId><artifactId>jstl</artifactId><version&g…

【数据结构与算法】3.(单向、无向、带权)图,广度、深度优先搜索,贪心算法

文章目录1.图简介2.图的存储方式2.1.邻接矩阵存储方法2.2.邻接表存储方法3.有向、无向图和查询算法3.1.数据结构3.2.广度优先算法BFS3.3.深度优先算法DFS3.3.1.DFS查询单条路径3.3.2.DFS查询所有路径4.带权图和贪心算法4.1.贪心算法4.2.基于带权无向图使用贪心算法查询最优路径…

混合精度训练,FP16加速训练,降低内存消耗

计算机中的浮点数表示&#xff0c;按照IEEE754可以分为三种&#xff0c;分别是半精度浮点数、单精度浮点数和双精度浮点数。三种格式的浮点数因占用的存储位数不同&#xff0c;能够表示的数据精度也不同。 Signed bit用于控制浮点数的正负&#xff0c;0表示正数&#xff0c;1表…

MAC地址IP地址 端口

网络结构&#xff1a; 服务器-客户机&#xff08;C/S&#xff09;Client-Server结构&#xff0c;如QQ,LOL都拥有客户端 优点&#xff1a;响应速度快&#xff0c;形式多样&#xff0c;安全新较高缺点&#xff1a;安装软件和维护&#xff0c;不能跨平台LINUX/windows/MAC浏览器-…

C语言——柔性数组

目录0. 前言1. 思维导图2. 柔性数组的特点3. 柔性数组的使用4. 柔性数组的优势5. 结语0. 前言 柔性数组是在C99标准时引入&#xff1a; 结构中的最后一个元素允许是未知大小的数组&#xff0c;这就叫柔性数组成员。 代码示例&#xff1a; typedef struct flexible_arr {int a…

leetcode 1011. Capacity To Ship Packages Within D Days(D天内运送包裹的容量)

数组的每个元素代表每个货物的重量&#xff0c;注意这个货物是有先后顺序的&#xff0c;先来的要先运输&#xff0c;所以不能改变这些元素的顺序。 要days天内把这些货物全部运输出去&#xff0c;问所需船的最小载重量。 思路&#xff1a; 数组内数字顺序不能变&#xff0c;就…

【Storm】【一】简介

介绍 1.1 简介 Storm 是 Apache 旗下免费开源的分布式实时计算框架。Storm可以轻松、可靠地处理无限数据流&#xff0c;对实时分析、在线机器学习、连续计算、分布式RPC&#xff0c;ETL等提供高效、可靠的支持。 1.2 什么是分布式计算 分布式计算&#xff0c;将一个任务分解…

云解析专家解密《狂飙》剧中京海市人民政府域名访问真相

这段时间&#xff0c;最火的国产剧当属《狂飙》无疑。尽管不久前迎来了大结局&#xff0c;但这部剧的热度依然不减&#xff0c;成为大家茶余饭后热议的话题。 出于对这部剧的喜爱&#xff0c;小编开启了二刷模式&#xff0c;在重温剧情的同时&#xff0c;对于其中的一些细节也…