操作系统-线程

2023-11-09

说明:文中内容大部分都是大部分都是《操作系统-精髓与设计原理 第八版》的原文,自己做了一些删改,使其更易于理解。

本章讲述一些与进程管理相关的高级概念,这些概念在很多现代操作系统中都可以找到。实际上,它包含了两个独立的概念:一个与资源所有权有关,一个与执行相关。这一区别使得许多操作系统中出现和发展了称为线程(thread)的结构。

一 进程和线程

在迄今为止的讨论中,进程具有如下两个特点:

  • 资源所有权
  • 调度/执行

这两个特点是独立的,因此操作系统应能分别处理它们。很多操作系统,特别是近期开发的操作系统已在这样做。为区分这两个特点,我们通常将分派的单位称为线程或轻量级进程(Light Weight Process,LWP),而将拥有资源所有权的单位称为进程(process)或任务(task)。

1.1 多线程

多线程是指操作系统在单个进程内支持多个并发执行路径的能力。每个进程中仅执行单个线程的传统方法(此时还未提出线程的概念)称为单线程方法(single-threaded approach)。

在多线程环境中,进程定义为资源分配单元和一个保护单元。与进程相关联的有:
• ·容纳进程映像的虚拟地址空间。
• ·对处理器、其他进程(用于进程间通信)、文件和I/O资源(设备和通道)的受保护访问。

一个进程中可能有一个或多个线程,每个线程都有:
• 一个线程执行状态(运行、就绪等)。
• 未运行时保存的线程上下文;线程可视为在进程内运行的一个独立程序计数器。
• 一个执行栈。
• 每个线程用于局部变量的一些静态存储空间。
• 与进程内其他线程共享的内存和资源的访问。


单线程多线程进程模型

图4.2从进程管理的角度说明了线程和进程的区别。

在单线程进程模型中(无明确的线程概念),进程的表示包括其进程控制块和用户地址空间,以及在进程执行中管理调用/返回行为的用户栈和内核栈。进程正运行时,处理器寄存器由该进程控制;进程未运行时,将保存这些处理器寄存器中的内容。

在多线程环境中 进程仍然只有一个与之关联的进程控制块和用户地址空间,但每个线程现在会有许多单独的栈和一个单独的控制块,控制块中包含寄存器值、优先级和其他与线程相关的状态信息。

因此,进程中的所有线程共享该进程的状态和资源,所有线程都驻留在同一块地址空间中,并可访问相同的数据。当某个线程改变了内存中的一个数据项时,其他线程在访问这一数据项时会看到这一变化。若一个线程以读权限打开一个文件,那么同一进程中的其他线程也能从这个文件中读取数据。
单线程和多线程进程模型

比较性能后会发现线程的如下优点:
1.在已有进程中创建一个新线程的时间,远少于创建一个全新进程的时间。Mach开发人员的研究表明,线程创建要比在UNIX中创建进程快10倍。
2.终止线程要比终止进程所花的时间少。
3.同一进程内线程间切换的时间,要少于进程间切换的时间。
4.线程提高了不同执行程序间通信的效率。在多数操作系统中,独立进程间的通信需要内核介入,以提供保护和通信所需的机制。但是,由于同一进程中的多个线程共享内存和文件,因此它们无须调用内核就可互相通信。
总结起来就是创建、终止、切换时间和通信效率的提高。

因此,若将一个应用程序或函数实现为一组相关联的执行单元,则用一组线程要比用一组分离的进程更有效。此外,在单处理器上使用线程结构,但其可简化逻辑上从事几种不同工作的程序的结构。

这里给出在单用户多处理系统中使用线程的4个例子:

  • 前台后台工作
  • 异步执行
  • 执行速度:一个线程在读取数据时被I/O操作阻塞,另一个线程仍然可以继续运行。
  • 模块化程序结构

在支持线程的操作系统中,调度和分派是在线程基础上完成的,因此大多数与执行相关的信息可以保存在线程级的数据结构中。但是,有些活动会影响进程中的所有线程,因此操作系统必须在进程级对它们进行管理。例如,挂起操作会把一个进程的地址空间换出内存,以便为其他进程的地址空间腾出位置。因为一个进程中的所有线程共享同一个地址空间,因此它们会同时被挂起。类似地,进程终止时会使得进程中的所有线程都终止。

1.2 线程功能

类似于进程,线程也具有执行状态,且可彼此同步。下面依次介绍线程的这两种功能。

线程状态
和进程一样,线程的主要状态有运行态、就绪态和阻塞态。一般来说,挂起态对线程没有意义,因此这类状态仅适用于进程。特别地,如果一个进程被换出,由于所有线程都共享该进程的地址空间,因此所有线程都须被换出。

有4种与线程状态改变相关的基本操作:

  • 派生:典型情况下,在派生一个新进程时,同时也会为该进程派生一个线程。随后,进程中的线程可在同一进程中派生另一个线程,并为新线程提供指令指针和参数;新线程拥有自己的寄存器上下文和栈空间,并放在就绪队列中。
  • 阻塞:线程需要等待一个事件时会被阻塞(保存线程的用户寄存器、程序计数器和栈指针),处理器转而执行另一个就绪线程。
  • 解除阻塞:发生阻塞一个线程的事件时,会将该线程转移到就绪队列中。
  • 结束:一个线程完成后,会释放其寄存器上下文和栈。

线程同步
一个进程中的所有线程共享同一个地址空间和诸如打开的文件之类的其他资源。
一个线程对资源的任何修改都会影响同一进程中其他线程的环境,因此需要同步各种线程的活动,以便它们互不干扰且不破坏数据结构。例如,两个线程都试图同时往一个双向链表中增加一个元素时,可能会丢失一个元素或破坏链表结构。

二 线程分类

2.1 用户级和内核级线程

线程分为两大类,即用户级线程(User-Level Thread,ULT)和内核级线程(Kernel-Level Thread,KLT),后者又称内核支持的线程或轻量级进程。

用户级线程

在纯ULT软件中,管理线程的所有工作都由应用程序完成,内核意识不到线程的存在。图4.5(a)说明了纯ULT方法。任何应用程序都可使用线程库设计成多线程程序。线程库是管理用户级线程的一个例程包,它含有创建和销毁线程的代码、在线程间传递消息和数据的代码、调度线程执行的代码,以及保存和恢复线程上下文的代码。

用户级线程和内核级线程

默认情况下,应用程序从单个线程开始,并在该线程中开始运行。这个应用程序及其线程将分配给一个由内核管理的进程。应用程序在运行(进程处于运行态)的任何时刻,都可派生一个在相同进程中运行的新线程。线程派生是通过调用线程库中的派生例程实现的。通过过程调用,控制权传递给派生例程。线程库为新线程创建一个数据结构,然后使用某种调度算法,把控制权传递给该进程中处于就绪态的一个线程。当控制权传递给线程库时,需要保存当前线程的上下文,然后在控制权从线程库中传递给一个线程时,恢复那个线程的上下文。上下文实际上包括用户寄存器的内容、程序计数器和栈指针。

上段描述的所有活动发生在用户空间中和一个进程内,内核并不知道这些活动。内核继续以进程为单位进行调度,并为进程指定一个执行状态(就绪态、运行态、阻塞态等)。下面的例子将阐述线程调度和进程调度的关系。假设进程B在其线程2中执行,进程和作为进程一部分的两个用户级线程的状态如图4.6(a)所示。此时可能会发生如下情况之一:

  • 在线程2中执行的应用程序代码进行一个阻塞进程B的系统调用。例如,执行一次I/O调用。这会把控制权转交给内核,随后内核启动I/O操作,把进程B置于阻塞态,并切换到另一个进程。在此期间,根据线程库维护的数据结构,进程B的线程2仍处于运行状态。注意,从在处理器上执行的角度来看,线程2实际上并不处于运行态,只是在线程库看来它处于运行态。
  • 时钟中断把控制权传递给内核,内核确定当前正运行的进程B已用完其时间片。内核把进程B置于就绪态并切换到另一个进程。同时,根据线程库维护的数据结构,进程B的线程2仍处于运行态。
  • 线程2运行到需要进程B的线程1执行某些动作的一个点。此时,线程2进入阻塞态,而线程1从就绪态转换到运行态。进程自身保留在运行态。

在线程的调度过程中,可以认为进程一直是在运行之中的。因为在进程不在运行的时候,可以认为进程内部一切都停止了。当进程再次运行,进程内部才继续进行。

使用ULT而非KLT的优点如下:

  1. 所有线程管理数据结构都在一个进程的用户地址空间中,线程切换不需要内核模式特权,因此进程不需要为了管理线程而切换到内核模式,进而节省了两次状态转换(从用户模式到内核模式,以及从内核模式返回用户模式)的开销。
  2. 调度因应用程序的不同而不同。一个应用程序可能更适合简单的轮转调度算法,而另一个应用程序可能更适合基于优先级的调度算法。为了不要乱底层的操作系统调度程序,可以做到为应用程序量身定做调度算法。
  3. ULT可在任何操作系统中运行,不需要对底层内核进行修改以支持ULT。线程库是供所有应用程序共享的一组应用级函数。
    总结:减少模式切换开销、自定义调度算法、操作系统平台无关

使用ULT而非KLT的缺点如下:

  1. 在典型的操作系统中,许多系统调用都会引起阻塞。因此,在ULT执行一个系统调用时,不仅会阻塞这个线程,也会阻塞进程中的所有线程。这在之前的运行情况之中的第一点有说明。一个线程启动可以阻塞的操作,如I/O操作,将把执行权归还内核,内核会直接阻塞这个进程,也就阻塞了所有线程。
  2. 在纯ULT策略中,多线程应用程序不能利用多处理技术。内核一次只把一个进程分配给一个处理器,因此一个进程中只有一个线程可以执行,这相当于在一个进程内实现了应用级多道程序设计。虽然多道程序设计可明显提高应用程序的速度,但同时执行部分代码更会使某些应用程序受益。
    总结:一个线程阻塞,则同一个进程中所有线程阻塞;无法使用多处理器技术

现在已有解决这两个问题的方法

解决问题1
使用一种称为“套管”(jacketing)的技术。“套管”的目标是把一个产生阻塞的系统调用转化为一个非阻塞的系统调用。例如,替代直接调用一个系统I/0例程,让线程调用一个应用级的I/O套管例程,这个套管例程中的代码用于检查并确定I/O设备是否忙。如果忙,该线程进入阻塞态并把控制权传送给另一个线程。这个线程重新获得控制权后,套管例程会再次检查I/O设备。
这就有点像线程提示操作系统产生一个进程,这个新进程去执行I/O操作,执行完成后提示这个线程,在完成之前,这个线程都是阻塞,但是原来的进程就可以执行别的线程而不被阻塞。
解决问题2
把应用程序写成一个多进程程序而非多线程程序。但是,这种方法消除了线程的主要优点:每次切换都变成进程间的切换而非线程间的切换,导致开销过大。

内核级线程

在纯KLT软件中,管理线程的所有工作均由内核完成。应用级没有线程管理代码,只有一个到内核线程设施的应用编程接口(API)。Windows是这种方法的一个例子。

图4.5(b)显示了纯KLT方法。内核为进程及进程内的每个线程维护上下文信息。调度由内核基于线程完成。

这种方法克服了ULT方法的两个缺点: 首先,内核可以同时把同一个进程中的多个线程调度到多个处理器中;其次,进程中的一个线程被阻塞时,内核可以调度同一个进程中的另一个线程。KLT方法的另一个优点是,内核例程自身也可是多线程的。
与ULT方法相比,KLT方法的主要缺点是: 在把控制权从一个线程传送到同一个进程内的另一个线程时,需要切换到内核模式。

为说明两种方法的区别,表4.1给出了在单处理器VAX机上运行类UNIX操作系统的测量结果。表中进行了两个基准测试,即Null Fork和Signal-Wait,前者测量创建、调度、执行和完成一个调用空过程的进程/线程的时间(即派生一个进程/线程的开销),后者测量进程/线程给正在等待的进程/线程发信号,然后在某个条件上等待所需要的时间(即两个进程/线程的同步时间)。可以看出,ULT和KLT之间、KLT和进程之间都有一个数量级以上的性能差距。
线程和进程操作执行时间
从表中可以看出,虽然使用KLT多线程技术与使用单线程的进程相比,速度明显提升,但使用ULT与使用KLT相比,速度再次得以提升。速度的再次提升是否能实现,取决于应用程序的性质。应用程序中的大多数线程切换都需要内核模式访问时,基于ULT的方案不见得会比基于KLT的方案好。

混合方法

有些操作系统提供混合ULT和KLT的方法【见图4.5(c)】。在混合系统中,线程创建完全在用户空间中完成,线程的调度和同步也在应用程序中进行。一个应用程序中的多个用户级线程会被映射到一些(小于等于用户级线程数)内核级线程上。为使整体性能最佳,程序员可为特定应用程序和处理器调节KLT的数量。
在混合方法中,同一个应用程序中的多个线程可在多个处理器上并行地运行,某个会引起阻塞的系统调用不会阻塞整个进程。设计正确时,这种方法可结合纯ULT方法和纯KLT方法的优点,并克服它们的缺点。
Solaris操作系统是使用混合方法的很好例子。最新版的Solaris将ULT/KLT关系限制为1:1。

三 多核和多线程

使用多核系统支持单个多线程应用程序的情况可能会出现在工作站、游戏机或正运行处理器密集型应用的个人计算机上。这时会带来性能和应用程序设计上的一些问题。本节首先介绍在多核系统上运行的多线程应用程序性能,然后介绍采用多核系统性能设计应用程序的一个具体示例。

3.1多核系统上的软件性能

多核组织结构带来的性能提升,取决于应用程序有效利用并行资源的能力。我们首先介绍运行在多核系统上的单个应用程序。Amdahl定律声称
Amdahl公式
该定律假设程序执行时间的(1-f)分之一所涉及的代码本质上是串行的,其余f分之一所涉及的代码是无限并行的,并且没有调度开销。

该定律看上去使得多核组织结构的前景很迷人。然而,如图4.7(a)所示,即使是一小部分串行代码也会显著影响性能。假设只有10%的代码本质上是串行的(即f=0.9),那么在一个8处理器的多核系统上运行该程序也仅有4.7倍的性能提升。另外,多处理器任务调度和通信以及高速缓存一致性维护都会给软件带来额外的开销。这就使得性能曲线达到峰值后便开始下降。图4.7(b)是一个有代表性的例子。
多核的性能影响
尽管如此,软件工程师们一直在努力解决这个问题,而且发现大量应用程序可以有效利用多核系统。研究了一系列数据库应用程序,这些程序采取了很多措施来降低硬件组织结构、操作系统、中间件和数据库应用软件本身的串行部分比例。 从图4.8中可以看出,数据库管理系统和数据库应用程序能有效地使用多核系统。还有许多不同类型的服务器程序能够有效使用并行化的多核组织结构,因为服务器程序通常会并行地处理许多相对独立的事务。

多处理器硬件上数据库负载的伸缩性
除通用服务器软件外,其他类型的应用程序也可从多核系统中直接获益,因为它们的吞吐量能随着处理器核心的数量伸缩。【MCDO06】给出了如下示例:

  • 原生多线程应用程序:多线程应用程序的特征是具有少数几个高度线程化的进程。线程化应用程序的例子包括Lotus Domino和SiebelCRM(客户关系管理)。
  • 多进程应用程序: 多进程应用程序的特征是具有多个单线程的进程。多进程应用程序的例子包括Oracle数据库、SAP和PeopleSoft。
  • Java 应用程序: Java从根本上支持线程的概念。不仅Java语言本身能够很方便地支持多线程应用程序开发,Java虚拟机也是一个多线程进程,它为Java应用程序提供调度机制和内存管理。能够直接从多核系统资源中获益的Java应用程序包括Sun公司的Java应用服务器、BEA公司的WebLogic、IBM公司的WebSphere和开源的Tomcat应用服务器。基于J2EE开发的所有应用程序也可直接从多核技术中获益。
  • 多实例应用程序: 即使个别应用程序未利用大量的线程来达到伸缩性,仍然可以通过并行运行多个应用程序的实例来从多核组织结构中获益。多个应用程序实例需要一定程度上的隔离性时,可使用虚拟化技术(虚拟出支撑操作系统的硬件)为每个实例提供独立、安全的环境。

3.2应用示例:

Valve 娱乐科技公司开发了众多游戏和Source 游戏引擎。Source是玩家数量最多的游戏引擎之一。Valve公司在自己的游戏中使用Source引擎,并通过颁发许可证的方式来允许其他游戏开发者使用Source引擎。

近年来,Valve使用多线程技术重新编写了Source引擎,以充分利用Intel和AMD多核处理器芯片的性能。改进后的Source引擎代码为Valve公司的游戏如《半条命2》提供了更为强大的支持。

从Valve的角度来看,线程根据其粒度定义为如下几种:
• 粗粒度线程:分配到各个处理器上的各个模块(称为系统)。在Source引擎中,一个处理器负责渲染,一个处理器负责AI(人工智能),一个处理器负责物理计算,以此类推。这种策略非常简单。从本质上讲,每个主要模块都是单线程的,由一个时间轴线程来协调所有其他线程的同步。
• 细粒度线程:分布在多个处理器上的许多相似或相同的任务。例如,在数据数组上迭代的一个循环可分割为一些小循环,而小循环则在各个线程上并行执行。
• 混合线程:这涉及为某些系统选择性使用细粒度线程,或为其他系统使用单个线程。

Valve公司发现,使用粗粒度线程策略时,在双处理器上运行程序的性能是在单处理器上运行程序的性能的两倍,但这种性能提升仅在某些专门设计的情形下才能达到。在真实的游戏环境中,性能约能提升为原来的1.2倍。Valve公司还发现有效地利用细粒度线程非常困难,因为每个工作单元耗费的时间是变化的,而且管理输出和结果的时间轴所涉及的编程相当复杂。

Valve公司还发现,随着8颗核心甚至16颗核心的多核系统的出现,混合线程方法最具应用前景,因此它可实现最佳的加速比。Valve识别了那些只在单处理器上运行时才非常有效率的系统。例如,混音系统几乎不与用户交互,它只处理自身的数据集,且不受窗口的帧配置限制。其他模块(如场景渲染)可组织为许多线程,这类模块既可以在单个处理器上运行,也可以在多个处理器上运行,因此能获得更好的性能。

根据系统特性来选择使用的单个线程或多个线程,可以有效的提高加速比。如果在可以使用多个线程的系统中使用了单个线程,性能自然会有所损失。而在应该使用单个线程的地方使用了多个线程来执行反而会使性能下降,也同时增加了编程的复杂性。

四 Linux的进程和线程管理

4.1 Linux进程

Linux中的进程或任务由一个task struct数据结构表示。task struct数据结构包含以下各类信息:

  • 状态:进程的执行状态(执行态、就绪态、挂起态、停止态、僵死态)。这些状态将在下面进一步讲述。
  • 调度信息:Linux调度进程所需要的信息。一个进程可能是普通的或实时的,并具有优先级。
  • 实时进程在普通进程前调度,且在每类中使用相关的优先级。一个计数器会记录允许进程执行的时间量。
  • 标识符:每个进程都有唯一的一个进程标识符,以及用户标识符和组标识符。组标识符用于给一组进程指定资源访问特权。
  • 进程间通信:Linux支持UNIXSVR4中的IPC机制,详见第6章。
  • 链接:每个进程都有一个到其父进程的链接及到其兄弟进程(与它有相同的父进程)的链接,以及到所有子进程的链接。
  • 时间和计时器:包括进程创建的时刻和进程所消耗的处理器时间总量。一个进程可能还有一个或多个间隔计时器,进程通过系统调用来定义间隔计时器,计时器期满时,会给进程发送一个信号。计时器可以只用一次或周期性地使用。
  • 文件系统:包括指向被该进程打开的任何文件的指针和指向该进程当前目录与根目录的指针。
  • 地址空间:定义分配给该进程的虚拟地址空间。
  • 处理器专用上下文:构成该进程上下文的寄存器和栈信息。

图4.15给出了Linux中一个进程的执行状态,如下所示:

  • 运行:这个状态值对应于两个状态。一个运行进程要么正在执行,要么准备执行。
  • 可中断:这是一个阻塞态,此时进程正在等待一个事件(如一个I/O操作)的结束、一个可用的资源或另一个进程的信号。
  • 不可中断:这是另一个阻塞态。它与可中断状态的区别是,在不可中断状态下,进程正在等待一个硬件条件,因此不会接收任何信号。
  • 停止:进程被中止,并且只能由来自另一个进程的主动动作恢复。例如,一个正在被调试的进程可被置于停止态。
  • 僵死:进程已被终止,但由于某些原因,在进程表中仍然有其任务结构。
    Linux进程/线程模型

4.2 Linux线程

传统UNIX系统支持在每个进程中只执行一个线程,但现代UNIX系统通常支持在一个进程中含有多个内核级线程。如同传统UNIX系统那样,老版本的Linux内核不支持多线程。多线程应用程序需要用一组用户级程序库来编写,以便将所有线程映射到一个单独的内核级进程中,最著名的是pthread(POSIX thread)库。现代UNIX提供内核级线程。Linux提供一种不区分进程和线程的解决方案,这种解决方案使用一种类似于Solaris轻量级进程的方法,将用户级线程映射到内核级进程。组成一个用户级进程的多个用户级线程则映射到共享同一个组ID的多个Linux内核级进程上。因此,这些进程可以共享文件和内存等资源,使得同一个组中的进程调度切换时不需要切换上下文

在Linux中通过复制当前进程的属性可创建一个新进程。新进程创建后,可以共享资源,如文件、信号处理程序和虚存。两个进程共享相同的虚存时,可将它们视为一个进程中的线程。 然而,没有给线程单独定义数据结构,因此Linux中的进程和线程没有区别。Linux用clone()命令代替通常的fork()命令来创建进程。该命令包含了下面所示的一组标识作为参数。传统的fork()系统调用在Linux上是用所有克隆标志清零的clone()系统调用实现的。

克隆标识包括以下实例:

  • CLONE_NEWPID:创造新的进程ID命名空间。
  • CLONE PARENT:调用者及其创建的任务共享同一个父进程。
  • CLONE_SYSVSEM:共享System V SEM_UNDO语义。
  • CLONE_THREAD:将该进程插入父进程的同一个线程组。该标志为真时,它隐含设置了
    CLONE_PARENT。
  • CLONE_VM:共享地址空间(内存描述符和所有页表)。

当Linux内核执行从一个进程到另一个进程的切换时,会检查当前进程的页目录地址是否与将被调度的进程的相同。若相同,则它们共享同一个地址空间,所以此时上下文切换仅是从代码的一处跳转到代码的另一处。

虽然属于同一个进程组的克隆进程共享同一内存空间,但不能共享同一个用户栈。所以clone()调用会为每个进程创建独立的栈空间。

五 小结

某些操作系统区分进程和线程的概念,前者涉及资源的所有权,后者涉及程序的执行。这种方法可提高性能,方便编码。在多线程系统中,可在一个进程内定义多个并发线程,实现方法是使用用户级线程或内核级线程。用户级线程对操作系统是未知的,它们由一个在进程的用户空间中运行的线程库创建并管理。用户级线程非常高效,因为从一个线程切换到另一个线程不需要进行状态切换,但一个进程中一次只有一个用户级线程可以执行,如果一个线程发生阻塞,整个进程都会被阻塞。进程内包含的内核级线程是由内核维护的。由于内核认识它们,因而同一个进程中的多个线程可在多个处理器上并行执行,一个线程的阻塞不会阻塞整个进程,但从一个线程切换到另一个线程时需要进行模式转换。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

操作系统-线程 的相关文章

  • 计算机网路基础 - 一些基本概念与网络结构

    1 基本概念 计算机网络 通信技术 计算机技术 是两项技术紧密结合的产物 通信系统的基础模型 计算机网络 是指将地理位置不同 具有独立功能的多台计算机及其外部设备 通过通信线路连接 在网络操作系统 网络管理软件及网络通信协议的管理和协调下
  • 条件变量(condition variable)详解

    原理 假设我们需要解决这样一个问题 一个列表记录需要处理的任务 一个线程往此列表添加任务 一个线程processTask处理此列表中的任务 这个问题的一个关键点在于processTask怎么判断任务列表不为空 一般有两种方法 一 proce
  • Tomcat7安装及配置教程

    Apache Tomcat7 0安装及配置教程 Apache Tomcat7 0官方网站链接 http tomcat apache org apache tomcat 7 0 73 windows x64 先解压下载的压缩包 然后在bin目
  • Minikube 架构及启动流程剖析

    原文作者 wzqnls 编辑 夏天 对于要学习 Kubernetes 或者需要本地开发的开发人员来说 Minikube 是一个不错的选择 通过使用 Minikube 这个工具 我们可以非常快捷地在本地部署一套单节点的 Kubernetes
  • 小白学协程笔记2-c语言实现协程-2021-2-10

    文章目录 前言 一 c语言中协程切换方式 二 使用setjmp 和 longjmp实现协程切换 1 setjmp和longjmp函数简介 2 协程实现 三 使用switch case实现协程切换 1 switch case小技巧 2 协程实
  • 虚拟内存的最大容量与实际容量区别

    虚拟内存的最大容量与实际容量区别 1 概念介绍 虚拟内存的最大容量是计算机的地址结构 CPU寻址范围决定的 虚拟内存的实际容量是内存与外存之和 CPU寻址范围 两者的最小值 2 例题介绍 某计算机的地址结构是64位 按字节编址 内存大小51
  • 虚拟机管理程序、虚拟化和云: 深入剖析 PowerVM 虚拟机管理程序

    预备知识 Power 是没有限制的虚拟化 一些企业打算依靠 PowerVM 虚拟化将多个工作负载整合到较少系统上 从而提高服务器利用率 降低成本 Power VM 为基于 Power Systems 平台的高级 RAS 功能和领先性能为 A
  • Linux使用nvida-smi查看GPU类型

    nvida smi提供一个查看GPU信息的方法 然而这种方式不能查看GPU型号 型号被省略成了GeForce RTX 208 如果我们需要查看GPU的型号 只需要运行nvidia smi L即可 mrfive ubuntu nvidia s
  • CF、SF、OF、ZF标志位

    没学汇编 这种题我真是做一道错一道 OF overflow flag 溢出标志位 溢出标志位 OF 1 表示带符号整数运算时结果发生溢出 对于无符号整数运算 OF没有意义 对于有符号数的溢出判断方式有 1 采用一位符号位 思想为 或 则为溢
  • nslookup命令详解

    nslookup命令用于查询DNS的记录 查看域名解析是否正常 在网络故障的时候用来诊断网络问题 nslookup的用法相对来说还是蛮简单的 主要是下面的几个用法 1 直接查询 这个可能大家用到最多 查询一个域名的A记录 nslookup
  • 什么是SSL协议?

    转自 微点阅读 https www weidianyuedu com 什么是SSL协议 SSL协议是一种安全传输协议 SSL是SecureSocketLayer的缩写 即安全套接层协议 该协议最初由Netscape企业发展而来 目前已经成为
  • 操作系统 段页式存储管理

    一 引入 分页系统是以页面作为内存分配的基本单位 能有效地提高内存利用率 但信息共享等不方便 分段系统是以段作为内存分配的基本单位 它能够更好地满足用户多方面的需要 信息共享 动态链接等 但采用分区方式管理物理内存 仍然存在碎片问题 段页式
  • Visual studio 2005 hangs on startup AppHangXProcB1 svchost devenv.exe svchost.exe:{2a811bb2-303b-48b...

    This problem has been torturing me for the whole afternoon and after searching on the web for a long time I finally get
  • 使用inet_ntop转换IPv6地址时在macOS和linux上的行为不一样

    下面这段python代码在macOS和linux时运行的结果是不同的 import socket ip socket inet pton socket AF INET6 1 2 3 0 5 6 7 8 print socket inet n
  • 内存管理——分页分段

    一 分页存储管理 1 页面与页框 1 页面 将一个进程的逻辑地址空间分成若干个大小相等的片 称为页面或页 并为各页加以编号 2 页框 相应于页面 把内存空间分成和页面相同大小的若干个存储块 称为 物理 块或页框 frame 3 页内碎片 在
  • iOS线程初探(四) GCD 和 NSOperation 小结

    参考资料 关于iOS多线程 看我就够了 GCD 在GCD中 有两个概念很重要 那就是任务和队列 任务 其实就是你需要做的事情 一个Block而已 任务有两种执行方式 同步执行和异步执行 同步执行 会阻塞当前线程 直至该任务执行完成后当前线程
  • java IO、NIO、AIO详解

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 一 IO流 同步 阻塞 二 NIO 同步 非阻塞 三 NIO2 异步 非阻塞 正文 回到顶部 概述 在我们学习Java的IO流之前 我们都要了解几个关键词 同步与异步 sy
  • Common块和Bss段的区别

    昨天看 程序员的自我修养 链接 装载与库 发现不是很理解为什么要用common块 然后仔细看了一番 有了自己的理解 common块 用来存放弱符号 而全局未初始化变量是弱符号 但是难道不是应该存放在 bss段吗 为什么要有common块呢
  • Linux(12):磁盘配额(Quota)与进阶文件系统管理

    磁盘配额 Quota 的应用与实作 Quota 的一般用途 针对 www server 例如 每个人的网页空间的容量限制 针对 mail server 例如 每个人的邮件空间限制 针对 file server 例如 每个人最大的可用网络硬盘
  • 八股文打卡day20——操作系统(3)

    面试题 线程同步的方式有哪些 我的回答 多线程同时访问和修改某个数据的话 会造成数据的不一致和冲突问题 所以就需要线程同步 线程同步的方式有 1 互斥锁 互斥锁就是 当一个资源被访问和操作时 会对这个资源加锁 把这个资源锁定 其他线程不能对

随机推荐

  • 内网穿透-Natapp实现免费远程桌面

    很多人都在使用Teamviewer访问远程桌面 但收费很贵 而且经常有一些安全漏洞 下面教大家一个免费安全的远程桌面方法 打开Natapp主页 https natapp cn 点击 立即下载 按钮 下载操作系统匹配的客户端 下载之后 解压至
  • 可能是史上最全的Kubernetes证书解析

    为了避免广告法 题目还是加个可能吧 想要安全就必须复杂起来 证书是少不了的 在Kubernetes中提供了非常丰富的证书类型 满足各种不同场景的需求 今天我们就来看一看Kubernetes中的证书 k8s证书分类 在说证书之前 先想想作为集
  • Shiro简单配置Springboot版(1)

    1 权限的管理 1 1 什么是权限管理 基本上涉及到用户参与的系统都要进行权限管理 权限管理属于系统安全的范畴 权限管理实现对用户访问系统的控制 按照安全规则或者安全策略控制用户可以访问而且只能访问自己被授权的资源 权限管理包括用户身份认证
  • 【论文速递】CCDC2021 - 轻量级网络的结构化注意知识蒸馏

    论文速递 CCDC2021 轻量级网络的结构化注意知识蒸馏 论文原文 Structured Attention Knowledge Distillation for Lightweight Networks 获取地址 https ieeex
  • 【文献调研】再入院预测(1)

    1 基于MIMIC 3数据库的心衰患者诊断与再入院模型研究 1 1 文献来源 太原理工大学 2022年6月 1 2 摘要 背景 利用深度学习去大规模的分析电子健康记录数据仍具有极大的挑战 基于大量医学文本 及时识别心力衰竭患者并建立再入院预
  • 高斯混合模型(GMM)和EM算法详解

    小白一枚 接触到GMM和EM 现将学习到的整理出来 如有错误 欢迎指正 文中涉及到公式的推导比较繁琐 故先在纸上推导出来再拍照发出来 希望大家多多交流 共同进步 接下来将按照思路一步一步进行介绍 1 单高斯模型GSM 一维 单高斯模型很简单
  • 车联网环境下自动驾驶的协同感知技术综述

    论文标题 Cooperative Perception Technology of Autonomous Driving in the Internet of Vehicles Environment A Review 发表期刊 会议 Se
  • SQLServer的基本语句(增,删,改)_02

    SQLserver语句不区分大小写 1 创建数据库 create database hhh hhh为数据库名称 创建一个名为hhh的数据库 2 删除数据库 drop database hhh 删除名为hhh的数据库 两者一般写为 if ex
  • 5、Nginx 配置实例-负载均衡

    文章目录 5 Nginx 配置实例 负载均衡 5 1 实现效果 5 2 准备工作 5 3 实验代码 5 3 1 轮询 默认 5 3 2 weight 5 3 3 ip hash 5 3 4 fair 第三方 尚硅谷 尚硅谷Nginx教程由浅
  • mesh和wifi中继的区别_科普:路由器的无线中继和Mesh的区别是什么?

    大户型和越层户型等改善型性房型越来越普及了 但是这些用户却也面临WiFi网络越来越差的窘境 如何改善WiFi网络就成为了迫在眉睫需要解决的问题 在无线路由的早期 不少人都习惯于使用无线中继的方式来解决这个问题 无线中继组网就是利用AP的无线
  • Web之html、css

    目录 前言 一 HTML 1 定义 2 标签 基本标签 表格标签 表单标签 其他标签及符号 3 属性 二 CSS 1 定义 2 标签选择器 3 基本样式设置 总结 前言 本文主要讲述后端开发者需要的基本web知识点 讲述了html css的
  • element ul中el-calendar日历组件自定义快捷选择年月

    需求 以日历形式展现当前页面 其中 年月可进行下拉选择 默认选中任意月份 用户可以自由点选日期 实现效果 时间筛选
  • linux 指令 间隔,Linux基础命令(五)

    Linux信息显示和搜索文件命令 1 uname 显示系统信息 参数 a显示所有信息 v显示内核版本 n显示主机名称 p显示处理器类型 r显示内核发行版本号 i显示硬件平台 m显示计算机硬件架构 root localhost dir una
  • Camera sensor 基本原理

    1 Camera 工作原理介绍 1 1 结构 一般来说 camera 主要是由 lens 和 sensor IC 两部分组成 其中有的 sensor IC 集成 了 DSP 有的没有集成 但也需要外部 DSP 处理 细分的来讲 camera
  • web基础(二)---------列表、表格、表单

    目录 一 前言 二 正文 1 列表 1 无序列表 2 有序列表 3 自定义标签 2 表格 3 表单 1 input 根据type属性不同 展示不同效果 2 input 占位符 提示信息 3 表单域 划分提交 重置的作用域 form 4 普通
  • Java类加载顺序大乱斗

    代码 加载涉及到静态与初始化 遵循以下规则 类加载从上往下执行 依次执行静态的初始化语句和初始化块 而且类加载优先于对象创建 静态初始化语句和初始化块只加载一次 创建本类的对象时 从上往下执行一次非静态的初始化语向和初始化块 最后执行构造函
  • Spring Boot+Mybatis实现增删改查接口开发+测试(超详细建议收藏)

    前言 Java也是测试必知必会的内容 特别是现在类似spring boot 等Java框架更是成为主流 之前实现的图书增删改查是用Python实现的 没看过的请移步 Flask mysql 实现增删改查接口开发 测试 图文教程附源码 本次给
  • Linux操作系统下取得UUID的方法

    Linux操作系统下取得UUID的方法 2008 12 2 13 40 查看数 1162 Linux下面 有专门生成UUID的命令 uuidgen r t 即可以生成一个32位的字符串 这个是在命令行得到 在 usr include lib
  • 软件工程复习笔记 第七章 --测试

    第七章 测试 前言 测试概述 测试定义 测试本质 软件测试要素 测试技术 测试类型 级别 测试管理 测试方法 静态测试 分析 走查 WalkThrough 审查 Inspection 评审 Review 同行 对等 评审 Peer Revi
  • 操作系统-线程

    说明 文中内容大部分都是大部分都是 操作系统 精髓与设计原理 第八版 的原文 自己做了一些删改 使其更易于理解 本章讲述一些与进程管理相关的高级概念 这些概念在很多现代操作系统中都可以找到 实际上 它包含了两个独立的概念 一个与资源所有权有