当前位置: 首页 > news >正文

【Linux进程】初悉进程

学习编程就得循环渐进,扎实基础,勿在浮沙筑高台  

 循环渐进Forward-CSDN博客

进程调度简介

1.2进程查看命令

1.3进程的几个要素

二、进程的生命周期

2.1进程状态文字描述

2.2进程状态的切换

2.3task_struct数据结构

2.4进程优先级

⑴优先级的代码表示

⑵Linux内核下的进程分类

⑶优先级的在不同类型进程的分配

2.5进程调度的重要性

⑴提升系统性能

⑵确保公平性

三、进程系统调用

3.1系统调用函数

⑴fork系统调用代码

⑵vfork系统调用代码

⑶clone系统调用代码

⑷进程退出

⑸内核线程

3.2常见的进程调度算法

⑴先来先服务(FCFS)

⑵短作业优先(SJF)

⑶优先级调度

⑷轮转调度(RR)

⑸多级反馈队列调度

⑹高响应比优先调度算法

四、进程调度的实现与优化

4.1调度算法的选择

4.2调度器的设计与实现

4.3进程状态的转换机制


进程调度简介

        在Linux中,进程是最基本的执行单位。进程调度在整个操作系统中属于核心地位,是操作系统实现多任务处理的关键操作,确保每个进程在有限的CPU资源下有序的完成相应操作。

        在Linux操作系统中,同一时间下不仅仅只有一个进程在执行任务而是多个进程同时竞争有限的CPU资源。若没有进程调度操作,整个系统可能会陷入混乱,例如你正在听着歌却突然把歌停了给你播放视频。因此,进程调度尤为重要。

        进程调度的高效性会直接影响到系统的性能。一个高效的进程调度算法能够迅速完成大量进程间的切换,从而确保CPU资源得到最大程度的利用。以轮转调度(Round Robin, RR)算法为例,该算法将CPU时间分割成多个固定的时间片,每个进程依次占用一个时间片进行执行。这种方式确保了所有进程都能获得一定的执行时间,进而提升了系统的整体处理能力。据统计,在合理设定时间片长度的情况下,轮转调度算法能显著提升系统吞吐量,增幅可达20%至30%。

        公平性同样是进程调度中的一项关键考量。它要求每个进程都能获得适当的CPU时间片,以防止某些进程因长时间无法执行而陷入饥饿状态。例如,在优先级调度算法中,若高优先级进程持续不断地产生,可能会导致低优先级进程长时间得不到执行机会。为解决这一问题,可以采取老化等技术手段,逐步提高那些等待时间过长的进程的优先级。

        公平性也是进程调度的重要目标之一。每个进程都应该有机会获得合理的 CPU 时间片,避免饥饿现象的发生。例如,优先级调度算法中,如果源源不断地产生高优先级的进程,那么低优先级的进程可能会长时间得不到执行。为了解决这个问题,可以采用老化等技术,逐渐增加等待很长时间的进程的优先级。

1.2进程查看命令

⑴ps (Process Status)命令是Linux及类Unix系统中最基础的进程查看工具之一,它提供了当前系统中进程状态的一次性快照视图。通过不同的选项,您可以获取到不同级别的进程信息。

以下是一些常用选项及其作用:

  • -e 或 --every:显示系统中所有的进程。

  • -f 或 --full:提供完整的格式输出,包括进程树状关系和环境变量等额外信息。

  • -l 或 --long:长格式输出,包含更多详细信息,如F旗表示进程正在等待文件锁。

  • -u 或 --user:按照用户来显示进程,并显示每个进程的CPU和内存使用情况。

  • -aux 是一个常见的组合选项,用于显示系统中所有用户的全部进程,包括后台进程(不与终端关联的进程)。

  • 进程列表:按照默认排序(通常是CPU使用率或优先级)列出正在运行的进程及其相关信息,如PID、USER(执行进程的用户)、PR(优先级)、NI(nice值,影响优先级)、VIRT(虚拟内存大小)、RES(常驻内存大小)、%CPU和%MEM(CPU和内存使用百分比)等。

  • 系统总体状态:包括系统运行时间、登录用户数、系统负载、CPU和内存的整体使用状况等统计数据。

  • 交互式操作:在top运行过程中,用户可以通过键盘输入相应的命令(如按P键切换到按CPU使用率排序,按M键切换到按内存使用率排序,或使用k键杀死指定进程等)来进行进一步的进程管理和监控。


1.3进程的几个要素

  • 有一段程序待其执行

  • 有进程专用的系统堆栈空间

  • 在内核有task_struct结构体

  • 进程有独立的存储空间,拥有专用的用户空间


二、进程的生命周期

2.1进程状态文字描述

        Linux操作系统属于多任务操作系统,系统中的每个进程能够分时复用CPU时间片,通过有效的进程调度策略实现多任务并行执行。而进程在被CPU调度运行,等待CPU资源分配以及等待外部事件时会属于不同的状态。

共有五种状态:

  • 创建状态:新进程刚刚被创建,尚未开始执行。

  • 就绪状态:进程已准备好所有必需资源,等待CPU分配时间片执行。

  • 执行状态:进程已获得CPU资源并在其中运行。

  • 阻塞状态:进程因等待某个资源或事件而暂时停止运行,从CPU队列中移除。

  • 终止状态:进程已完成执行或被终止,不再存在。

进程状态程序中的体现:

#define TASK_RUNNING			0x00000000
#define TASK_INTERRUPTIBLE		0x00000001
#define TASK_UNINTERRUPTIBLE	0x00000002
#define __TASK_STOPPED			0x00000004
#define __TASK_TRACED			0x00000008
  • TASK_RUNNING 表示进程处于可运行状态。这意味着进程已经准备好在CPU上执行,并且调度器可以选择它来进行运行。当进程获取到CPU时间片时,它就会进入运行状态。

  • TASK_INTERRUPTIBLE 表示进程处于可中断睡眠状态。这种状态下,进程正在等待某个事件发生(例如I/O操作完成、锁可用等),并且如果收到信号或者等待的条件满足,它可以被唤醒并重新加入到可运行队列中。在可中断睡眠期间,进程可以响应信号并改变其状态。

  • TASK_UNINTERRUPTIBLE 表示进程处于不可中断睡眠状态。类似可中断睡眠,进程同样在等待某种资源或事件,但是在此状态下,进程不会响应任何信号,即使接收到信号也不会立即醒来,除非等待的资源变为可用或特定条件达成。

  • __TASK_STOPPED 标志意味着进程已停止执行,通常是因为收到了SIGSTOP或SIGTSTP这样的停止信号,或者是调试器暂停了进程。停止的进程不会消耗CPU资源,直到收到SIGCONT信号恢复执行。

  • __TASK_TRACED 表示进程正在被调试器或其他跟踪工具追踪,并进入了跟踪停止状态。在这种状态下,进程同样不会执行,等待调试器的进一步操作,比如单步执行、继续执行等。

        这些状态标志会被组合在一个进程控制块(PCB,在Linux内核中表现为task_struct结构体的一个成员变量state)中,以表示进程的当前状态。调度器根据这些状态决定何时何地将进程投入运行或从运行状态移除。在实际的内核源码中,为了准确反映进程状态,这些宏可能会与其他标志位一起使用或组合起来形成更复杂的状态标识。


2.2进程状态的切换

如下图,便是进程进行状态之间的切换,这些工作都是有调度器来完成的。


2.3task_struct数据结构

        进程是操作系统调度的一个实体,需要对进程所必须资源做一个抽象化,此抽象化为进程控制块 (PCB,Process Control BLock) ,PCB在Linux内核里面采用task_struct结构体来描述进程控制块。Linux内核涉及进程和程序的所有算法都围绕名为task_struct的数据结构而建立操作。具体Linux内核源码task_struct结构体核心成员如下(task_struct结构体过于庞大,暂时了解几个重要成员)task_struct定义在include\linux\sched.h:

  • __state:表示当前进程状态,例如可运行、睡眠、僵死等。

  • stack:指向进程的内核栈。

  • usage:引用计数,用于跟踪进程使用情况。

  • prio、static_prio和normal_prio:描述进程的调度优先级和策略。

  • se、rt和dl:分别对应CFS(完全公平调度器)、实时调度和Deadline调度的调度实体。

  • mm:指向进程的内存描述符结构(mm_struct),管理进程的虚拟内存。

  • active_mm:在没有独立内存空间时,指向当前活动的内存描述符。

  • exit_state、exit_code和exit_signal:进程退出时的状态、退出码和发送给父进程的信号。

  • pid和tgid:分别代表进程ID和线程组ID。

  • real_parent、parent、children和sibling:用于构建进程间的父子、兄弟关系,形成进程树。

  • files:指向进程打开的文件表,即files_struct结构体,记录所有已打开的文件描述符。

  • signal和sighand:管理和处理进程接收到的信号。

  • blocked、real_blocked和saved_sigmask:记录进程当前屏蔽的信号集合。

  • nsproxy:命名空间代理,用于管理和切换不同命名空间。

  • fs:指向文件系统信息结构,记录进程的当前工作目录、根目录等文件系统相关信息。

 其他字段还包括了进程的调度统计信息、时间统计、内存页面错误统计、POSIX定时器、安全特性、审计信息等。


2.4进程优先级

⑴优先级的代码表示

描述进程的调度优先级和策略,之后的任务调度以及时间片分配都要用到优先级:

int				prio;int				static_prio;int				normal_prio;unsigned int	rt_priority;
  • int prio: 这个字段代表进程的动态优先级,它是根据进程的行为和系统负载动态调整的。在传统的Linux调度器(如CFS调度器)中,这个优先级通常被映射到调度实体(sched_entity)的一个虚拟运行时间(vruntime),而不是一个直观意义上的数字大小,较大的vruntime意味着较低的优先级。

  • int static_prio: 静态优先级,也称为nice值,在Linux中范围是-20至19,数值越小表示优先级越高。静态优先级可以通过nice值或者用户权限改变,但不会像动态优先级那样频繁变化。

  • int normal_prio: 此字段在某些Linux调度器实现中可能用来表示经过nice值调整后的正常优先级,它结合了静态优先级和可能的额外优先级调整因素。

  • unsigned int rt_priority: 实时优先级,仅适用于实时调度策略(如SCHED_FIFO或SCHED_RR)。实时进程有固定的优先级分配,rt_priority值越大,表示进程的实时优先级越高,抢占其他进程的可能性也就越大。实时进程一般不受nice值的影响,其优先级高于普通进程。在实时调度策略下,rt_priority用于确定进程在实时进程队列中的相对位置。

⑵Linux内核下的进程分类

在Linux内核中,进程可以按照其调度需求和优先级的不同分为不同的类别,主要包括:

  • SCHED_FIFO:实时进程中,优先级高的进程总是优先执行,一旦开始运行,除非进程主动放弃CPU(如阻塞等待I/O或睡眠),否则不会被优先级相同或更低的其他进程抢占。

  • SCHED_RR:同样是实时进程,但它在用完时间片后会重新加入队列等待下一次调度,这样可以保证在相同优先级的实时进程中实现时间片轮转。

  • 普通进程(Normal Process):又称为分时进程,这类进程在Linux系统中遵循默认的分时调度策略,如CFS(Completely Fair Scheduler)。它们按照各自权重(nice值)和虚拟运行时间(vruntime)来获取CPU时间片。nice值可以在[-20, 19]范围内调整,数值越小,优先级越高,但总体来说,普通进程之间是公平共享CPU资源的。

  • 实时进程(Real-time Process):实时进程在满足特定条件的情况下需要得到及时响应,具有更高的优先级。Linux内核提供两种实时调度策略:SCHED_FIFO(先进先出)和SCHED_RR(轮转调度)。

⑶优先级的在不同类型进程的分配

  • 限期进程的优先级是-1;

  • 实时进程的优先级1-99,优先级数值最大,表示优先级越高;

  • 普通进程的静态优先级为: 100-139,优先级数值越小,表示优先级越高,可通过修改nice值改变普通进程的优先级,优先级等于120加 上nice值;


2.5进程调度的重要性

⑴提升系统性能

        进程调度对系统性能的提升起着关键作用。通过合理地分配 CPU 资源,进程调度可以极大地提高 CPU 利用率。例如,在完全公平调度器(CFS)中,根据进程的虚拟运行时间来分配 CPU 时间,确保每个进程都能获得相对公平的执行机会,从而有效提高 CPU 的利用率。据统计,采用 CFS 的系统中,CPU 利用率可以提高 15% 至 20%。

        系统吞吐量是衡量系统性能的另一个重要指标。良好的进程调度算法可以在单位时间内完成更多的进程,从而提高系统吞吐量。以多级反馈队列调度为例,它将就绪队列分成多个优先级不同的队列,每个队列采用不同的调度算法。短作业可以在高优先级队列中快速得到执行,而长作业则在低优先级队列中逐步执行,这样可以兼顾不同类型进程的需求,提高系统的整体吞吐量。实验表明,使用多级反馈队列调度的系统,吞吐量可以比传统的先来先服务调度提高 30% 至 40%。

        此外,进程调度还可以降低周转时间、等待时间和响应时间。周转时间是指进程从提交到完成所花费的时间,等待时间是进程在就绪队列中等待的时间,响应时间是从进程提交到首次获得 CPU 时间的时间间隔。通过合理的调度算法,如短作业优先调度,可以优先执行短作业,减少这些时间指标。研究显示,在特定的工作负载下,短作业优先调度可以将平均周转时间降低 20% 至 30%,响应时间降低 15% 至 20%。

⑵确保公平性

        公平性是进程调度的核心目标之一。为了避免进程饥饿现象,各种调度算法都采取了不同的措施。在优先级调度中,虽然高优先级的进程会优先获得 CPU 资源,但为了防止低优先级进程长时间得不到执行,可以采用动态调整优先级的方法。例如,随着低优先级进程的等待时间增加,逐渐提高其优先级,使其有机会获得 CPU 执行时间。

        同时,一些调度算法还通过限制高优先级进程的执行时间来确保公平性。例如,在实时调度中,硬实时任务虽然要求在严格的时间限制内完成,但也不能无限占用 CPU 资源。调度算法会在保证硬实时任务按时完成的前提下,合理分配 CPU 时间给其他进程,以实现系统的整体公平性。


三、进程系统调用

3.1系统调用函数

        当运行应用程序的时候,调用fork()/vfork()/clone()函数就是系统调用。系统调用就是应用程序如何进入内核空间执行任务,程序使用系统调用执行一系列的操作: 比如创建进程、文件IO等等。

系统调用框图(使用Linux版本为6.1的内核,不同的内核其系统调用有点差异) 如下所示:

⑴fork系统调用代码

#ifdef __ARCH_WANT_SYS_FORK
SYSCALL_DEFINE0(fork)
{
#ifdef CONFIG_MMUstruct kernel_clone_args args = {.exit_signal = SIGCHLD,};return kernel_clone(&args);
#else/* can not support in nommu mode */return -EINVAL;
#endif
}

⑵vfork系统调用代码

#ifdef __ARCH_WANT_SYS_VFORK
SYSCALL_DEFINE0(vfork)
{struct kernel_clone_args args = {.flags		= CLONE_VFORK | CLONE_VM,.exit_signal	= SIGCHLD,};return kernel_clone(&args);
}
#endif

⑶clone系统调用代码

#ifdef __ARCH_WANT_SYS_CLONE
#ifdef CONFIG_CLONE_BACKWARDS
SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,int __user *, parent_tidptr,unsigned long, tls,int __user *, child_tidptr)
#elif defined(CONFIG_CLONE_BACKWARDS2)
SYSCALL_DEFINE5(clone, unsigned long, newsp, unsigned long, clone_flags,int __user *, parent_tidptr,int __user *, child_tidptr,unsigned long, tls)
#elif defined(CONFIG_CLONE_BACKWARDS3)
SYSCALL_DEFINE6(clone, unsigned long, clone_flags, unsigned long, newsp,int, stack_size,int __user *, parent_tidptr,int __user *, child_tidptr,unsigned long, tls)
#else
SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,int __user *, parent_tidptr,int __user *, child_tidptr,unsigned long, tls)
#endif
{struct kernel_clone_args args = {.flags		= (lower_32_bits(clone_flags) & ~CSIGNAL),.pidfd		= parent_tidptr,.child_tid	= child_tidptr,.parent_tid	= parent_tidptr,.exit_signal	= (lower_32_bits(clone_flags) & CSIGNAL),.stack		= newsp,.tls		= tls,};return kernel_clone(&args);
}
#endif

⑷进程退出

①、进程主动终止: 从main()函数返回,链接程序会自动添加到exit()系统调用; exit系统调用在内核定义如下\kernel\exit.c:

SYSCALL_DEFINE1(exit, int, error_code)
{do_exit((error_code&0xff)<<8);
}

②、进程被动终止: 进程收到一个自己不能处理的信号;进程收到 SIGKILL等终止信息。

⑸内核线程

        定义:它是独立运行在内核空间的进程,与普通用户进程区别在于内核线程没有独立的进程地址空间。task_struct数据结构里面有一个成员指针mm设置为NULL,它只能运行在内核空间。内核创建一个内核线程代码体现如下:

/** Create a kernel thread.*/
pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
{struct kernel_clone_args args = {.flags		= ((lower_32_bits(flags) | CLONE_VM |CLONE_UNTRACED) & ~CSIGNAL),.exit_signal	= (lower_32_bits(flags) & CSIGNAL),.fn		= fn,.fn_arg		= arg,.kthread	= 1,};return kernel_clone(&args);
}

3.2常见的进程调度算法

⑴先来先服务(FCFS)

        先来先服务调度算法是一种最简单的调度算法,它按照进程到达的先后顺序进行调度。当一个进程进入就绪队列时,它会按照到达的顺序排队等待 CPU 的分配。这种算法的优点是实现简单,公平性较高,每个进程都按照其到达的顺序依次获得 CPU 时间。然而,它也存在明显的缺点。对于长进程来说,可能会长时间占用 CPU,导致后续到达的短进程和 I/O 繁忙型作业等待时间过长。例如,假设有三个进程 P1、P2 和 P3,P1 的执行时间为 30 秒,P2 的执行时间为 5 秒,P3 的执行时间为 20 秒。如果按照先来先服务的算法调度,P1 先执行,那么 P2 和 P3 就需要等待 30 秒后才能开始执行,这大大增加了短进程和 I/O 繁忙型作业的等待时间,降低了系统的整体效率。

⑵短作业优先(SJF)

        短作业优先调度算法优先调度执行时间最短的进程。这种算法的目的是减少平均等待时间,提高系统的吞吐量。然而,它也存在一些问题。首先,它可能导致长作业饥饿,因为长作业可能一直等待短作业执行完毕后才能获得 CPU 时间。其次,准确估计作业的执行时间是非常困难的。在实际应用中,程序员很难准确估计作业的执行时间,通常会偏长估计,这可能导致算法的效果不如预期。例如,如果有一个长作业需要执行 100 秒,而不断有短作业到来,那么长作业可能永远也得不到调度,从而出现饥饿现象。

⑶优先级调度

        优先级调度算法根据进程的优先级进行调度。每个进程都被赋予一个优先级,优先级高的进程优先获得 CPU 时间。这种算法可以根据进程的重要性或紧急程度来分配 CPU 资源,具有一定的灵活性。但是,它也可能导致低优先级进程饥饿。如果不断有高优先级进程到来,低优先级进程可能长时间得不到执行。静态优先级调度在进程创建时分配优先级,并在整个执行过程中保持不变;动态优先级调度则根据进程的行为和状态动态调整优先级。例如,在一些实时系统中,紧急任务被赋予高优先级,以确保它们能够及时得到处理。但是,如果高优先级任务过多,低优先级任务可能会被长时间忽略。

⑷轮转调度(RR)

        轮转调度算法将 CPU 时间分成固定大小的时间片,所有进程轮流获得一个时间片的 CPU 使用权。这种算法具有较好的公平性,每个进程都能在一定时间内获得 CPU 时间。然而,时间片的大小对系统性能有很大影响。如果时间片太小,会导致进程切换频繁,增加系统开销;如果时间片太大,轮转调度算法就会退化为先来先服务算法。此外,轮转调度算法不利于处理紧急作业,因为每个进程都需要等待轮到自己才能获得 CPU 时间。例如,假设有一个紧急任务需要立即执行,但按照轮转调度算法,它可能需要等待很长时间才能获得 CPU 时间。

⑸多级反馈队列调度

        多级反馈队列调度算法结合了多种调度策略,根据进程的特性将其分配到不同的队列中,每个队列采用不同的调度算法。这种算法具有较高的灵活性,可以适应不同类型的进程。例如,高优先级的短作业可以分配到高优先级队列中,采用短作业优先调度算法;长作业可以分配到低优先级队列中,采用先来先服务调度算法。然而,这种算法相对复杂,需要维护多个队列,增加了系统的开销和管理难度。

⑹高响应比优先调度算法

        高响应比优先调度算法权衡了短作业和长作业,兼顾了等待时间和执行时间。响应比是等待时间与执行时间的比值,响应比高的进程优先获得 CPU 时间。这种算法既照顾了短作业,又考虑了作业到达的先后次序,不会使长作业长期得不到服务。但是,计算响应比会增加系统开销,因为每次调度都需要计算每个进程的响应比。例如,在一个有多个进程等待调度的系统中,计算响应比需要消耗一定的时间和计算资源。


四、进程调度的实现与优化

4.1调度算法的选择

        不同的场景和需求对进程调度算法有着不同的要求。在批处理系统中,主要追求高吞吐量和系统资源的充分利用。例如,短作业优先算法可以在一定程度上提高批处理系统的效率,因为它优先处理执行时间短的作业,从而在单位时间内可以完成更多的作业。据统计,在一些大型数据处理中心采用短作业优先算法,系统吞吐量可以提高 15% 至 20%。

        对于交互式系统,响应时间是关键指标。此时,轮转调度算法可能更为合适,因为它可以确保每个进程都能在较短的时间内获得 CPU 时间,从而提高系统的响应速度。例如,在图形用户界面环境下,用户期望每个操作都能得到及时的反馈,轮转调度算法可以保证各个进程轮流执行,使得用户操作不会被长时间阻塞。

        而在实时系统中,满足截止时间是最重要的目标。实时系统通常采用抢占式调度算法,如实时优先级调度,确保紧急任务能够在规定的时间内得到处理。例如,在飞机飞行控制系统中,对响应时间的要求极为严格,任何延迟都可能导致严重后果,实时优先级调度算法可以确保关键任务优先执行。


4.2调度器的设计与实现

        调度器的设计通常采用模块化的方式,以便于适应不同的系统需求和优化目标。以 Linux 的 CFS(完全公平调度器)为例,它通过为每个进程安排一个虚拟运行时钟 vruntime,实现了公平性。当一个进程得以执行时,vruntime 的值不断增大,而没有运行的进程的 vruntime 保持不变。调度器总是选择 vruntime 最小的进程执行,从而确保每个进程都能获得相对公平的 CPU 时间。

        CFS 的设计思路简单而有效,它根据每个进程的权重分配运行时间。例如,假设有两个进程 A 和 B,权重分别为 1 和 2,调度周期为 30ms。那么进程 A 的运行时间是 30*(1)/(1+2)=10ms,进程 B 的运行时间是 30*(2)/(1+2)=20ms。同时,CFS 通过调整 vruntime 的增长速度来体现不同进程的优先级,优先级高的进程 vruntime 增长得较慢,从而获得更多的运行机会。

        为了降低调度延迟带来的不公平性,CFS 采用了红黑树数据结构来管理就绪队列。红黑树可以快速地找到 vruntime 最小的进程,从而减少调度时间。此外,CFS 还支持按组来分配时间片,通过 cgroup 机制,可以将 CPU 资源划分为不同的组,以便更好地满足不同应用场景的需求。


4.3进程状态的转换机制

        进程在其生命周期内会经历多种状态的转换,这些转换受到资源分配的影响。例如,当一个进程从创建态转变为就绪态时,它需要获得除 CPU 以外的所有必要资源。一旦这些资源分配完成,进程就处于就绪状态,等待 CPU 的分配。

        当进程获得 CPU 资源并开始执行时,它处于运行态。然而,在运行过程中,进程可能会因为等待某个事件(如等待 I/O 操作完成、等待资源分配等)而进入等待态。在等待态下,进程会被暂时挂起,以释放 CPU 资源供其他进程使用。当等待的事件发生时,进程会被唤醒并重新进入就绪态。

        此外,进程还可能因为时间片用完或被更高优先级的进程抢占 CPU 而从运行态回到就绪态。而当一个进程完成其任务或出现无法克服的错误时,它会进入终止态,等待操作系统进行善后处理。


学习编程就得循环渐进,扎实基础,勿在浮沙筑高台  

相关文章:

【Linux进程】初悉进程

学习编程就得循环渐进&#xff0c;扎实基础&#xff0c;勿在浮沙筑高台 循环渐进Forward-CSDN博客 进程调度简介 1.2进程查看命令 1.3进程的几个要素 二、进程的生命周期 2.1进程状态文字描述 2.2进程状态的切换 2.3task_struct数据结构 2.4进程优先级 ⑴优先级的代…...

Python学习之路(5)— 使用C扩展

Python学习之路&#xff08;5&#xff09;— 使用C扩展 一、前言 参考&#xff1a;https://www.cnblogs.com/yinguo/p/4641349.html Python C扩展是指用C语言编写的代码&#xff0c;然后编译成Python可以调用的库。这样可以提高Python代码的执行效率&#xff0c;或者实现某些…...

动态规划34:446. 等差数列划分 II - 子序列

动态规划解题步骤&#xff1a; 1.确定状态表示&#xff1a;dp[i]是什么 2.确定状态转移方程&#xff1a;dp[i]等于什么 3.初始化&#xff1a;确保状态转移方程不越界 4.确定填表顺序&#xff1a;根据状态转移方程即可确定填表顺序 5.确定返回值 题目链接&#xff1a;446.…...

PPT画图——如何设置导致图片为600dpi

winr&#xff0c;输入regedit打开注册表 按路径找&#xff0c;HKEY_CURRENT_USER\Software\Microsoft\Office\XX.0\PowerPoint\Options&#xff08;xx为版本号&#xff0c;16.0 or 15.0或则其他&#xff09;。名称命名&#xff1a;ExportBitmapResolution 保存即可&#xff0c;…...

【模块系列】STM321.69TFT屏幕

前言 在翻翻自己的器件盒的时候&#xff0c;发现这块好久之前买的TFT屏了&#xff0c;想起还没有用STM32点亮过&#xff0c;手头上正好有立创的梁山派STM32F4&#xff0c;就试着按照网上的文章教程顺便移植个LVGL看看&#xff0c;然后就有了就本文。 代码工程命名的是LvglDemo&…...

大模型辅助测试的正确打开方式?

测试的基本目的之一&#xff0c;是对被测对象进行质量评估。换言之&#xff0c;是要提供关于被测对象质量的“确定性”。因此&#xff0c;我们很忌讳在测试设计中引入“不确定性”&#xff0c;比如采用不可靠的测试工具、自动化测试代码逻辑复杂易错、测试选择假设过于主观等等…...

三相电的相电压、线电压、额定值、有效值,变比,零序电压,零序电流,三相三线制的三角形连接,三相四线制的星形连接

在二次设备配置中经常有根电压系统相关的名词&#xff0c;本身不是学电气的&#xff0c;有些名词经常查了忘&#xff0c;后续工作所有遇到跟电气相关的知识总结在此帖&#xff0c;便于后续直接查看&#xff0c;避免每次都要重新查、重新梳理。 相电压和线电压的关系是根号3倍&a…...

电商网站的基础用户数在100万,日活跃用户数在1万左右,系统下单TPS最大支持1000,应用服务要保证高可用。请预估该网站每天的使用成本。

要预估一个电商网站每天的使用成本&#xff0c;我们需要考虑多个因素&#xff0c;包括计算资源、数据库、缓存、存储、网络流量、负载均衡、安全服务、监控与日志等。以下是基于您提供的信息&#xff08;基础用户数100万&#xff0c;日活跃用户数1万&#xff0c;系统下单TPS最大…...

线性代数期末总复习的点点滴滴(1)

一、可逆矩阵、行列式、秩的关系 1.行列式与可逆矩阵的关系 所以&#xff0c;不难看出矩阵可逆的充分必要条件是该矩阵的行列式不为0。 2.接着来看&#xff0c;满秩和矩阵行列式的关系 不难看出满秩和行列式不为0是等价的。 3.再来看&#xff0c;满秩和矩阵可逆的关系 说明了…...

python+reportlab创建PDF文件

目录 字体导入 画布写入 创建画布对象 写入文本内容 写入图片内容 新增页 画线 表格 保存 模板写入 创建模板对象 段落及样式 表格及样式 画框 图片 页眉页脚 添加图形 构建pdf文件 reportlab库支持创建包含文本、图像、图形和表格的复杂PDF文档。 安装&…...

2024最新qrcode.min.js生成二维码Demo

找了一堆代码一堆GPT&#xff0c;终于给写对了&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><…...

【Microi吾码】开源力量赋能低代码创新,重塑软件开发生态格局

我的个人主页 文章专栏&#xff1a;Microi吾码 一、引言 在当今数字化浪潮汹涌澎湃的时代&#xff0c;软件开发的需求呈现出爆发式增长。企业为了在激烈的市场竞争中脱颖而出&#xff0c;不断寻求创新的解决方案以加速数字化转型。传统的软件开发方式往往面临着开发周期长、技…...

Github - 如何提交一个带有“verified”标识的commit

Github - 如何提交一个带有“verified”标识的commit 前言(Why) 今天在Github上浏览某项目的commit记录的时候发现&#xff0c;有的commit记录带有verified绿色标识&#xff0c;有的带有橘色的Unverified标识&#xff0c;还有的什么都不显示。 既然我是根正苗红的作者(bushi)…...

HCIA笔记9--NAT、ACL与链路聚合

1. ACL ACL: 访问控制列表, Access Control List。 通过定义规则来允许或拒绝流量的通过。 1.1 ACL分类 1.2 配置实例 如图所示&#xff0c;对R2的访问只允许192.168.1.0/24网段。 我们可以配置基本acl来限制 acl 2000 acl number 2000 rule 5 permit source 192.168.1.0 0…...

SCSA:探索空间与通道注意力之间的协同效应

文章目录 摘要1 引言2 相关工作2.1 多语义空间信息2.2 注意力分解 3 方法3.1 共享多语义空间注意力&#xff1a;空间与通道分解3.2 渐进式通道自注意力3.3 协同效应3.4 注意力机制的整合 4 实验4.1 实验设置4.2 图像分类4.3 目标检测4.4 分割4.5 消融研究 5 可视化与分析5.1 注…...

深度学习助力股市预测:LSTM、RNN和CNN模型实战解析

作者&#xff1a;老余捞鱼 原创不易&#xff0c;转载请标明出处及原作者。 写在前面的话&#xff1a;众所周知&#xff0c;传统的股票预测模型有着各种各样的局限性。但在我的最新研究中&#xff0c;探索了一些方法来高效预测股市走势&#xff0c;即CNN、RNN和LSTM这些深度学习…...

组件库TDesign的表格<t-table>的使用,行列合并以及嵌入插槽实现图标展示,附踩坑

碎碎念&#xff1a;有点难用&#xff0c;不丝滑&#xff08;以下介绍的难点不是真的难&#xff0c;只是有点点点难用&#xff09; 背景&#xff1a;需要实现表格的行列合并以及图标的嵌入&#xff0c;想到使用组件库组件来方便开发 链接&#xff1a;TDesign Web Vue Next 难点…...

jwt在express中token的加密解密实现方法

在我们前面学习了 JWT认证机制在Node.js中的详细阐述 之后&#xff0c;今天来详细学习一下token是如何生成的&#xff0c;secret密钥的加密解密过程是怎么样的。 安装依赖 express&#xff1a;用于创建服务器jsonwebtoken&#xff1a;用于生成和验证JWTbody-parser&#xff1…...

结构体、共用体的字节对齐

结构体 结构体嵌套时&#xff1a;先算一下嵌套的结构体大小 嵌套进来的结构体大小为16字节&#xff0c;仍然进行&#xff0c;8字节对齐 typedef struct {char name[20];//20字节//000开始 20字节 019 struct{int day; //000开始 4字节 003char swx; //004开始 1…...

【YOLOv3】源码(train.py)

概述 主要模块分析 参数解析与初始化 功能&#xff1a;解析命令行参数&#xff0c;设置训练配置项目经理制定详细的施工计划和资源分配日志记录与监控 功能&#xff1a;初始化日志记录器&#xff0c;配置监控系统项目经理使用监控和记录工具&#xff0c;实时跟踪施工进度和质量…...

三维GIS开发cesium智慧地铁教程(5)Cesium相机控制

一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点&#xff1a; 路径验证&#xff1a;确保相对路径.…...

AI Agent与Agentic AI:原理、应用、挑战与未来展望

文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例&#xff1a;使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例&#xff1a;使用OpenAI GPT-3进…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统

医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上&#xff0c;开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识&#xff0c;在 vs 2017 平台上&#xff0c;进行 ASP.NET 应用程序和简易网站的开发&#xff1b;初步熟悉开发一…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例

使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件&#xff0c;常用于在两个集合之间进行数据转移&#xff0c;如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model&#xff1a;绑定右侧列表的值&…...

【网络安全产品大调研系列】2. 体验漏洞扫描

前言 2023 年漏洞扫描服务市场规模预计为 3.06&#xff08;十亿美元&#xff09;。漏洞扫描服务市场行业预计将从 2024 年的 3.48&#xff08;十亿美元&#xff09;增长到 2032 年的 9.54&#xff08;十亿美元&#xff09;。预测期内漏洞扫描服务市场 CAGR&#xff08;增长率&…...

Cinnamon修改面板小工具图标

Cinnamon开始菜单-CSDN博客 设置模块都是做好的&#xff0c;比GNOME简单得多&#xff01; 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作

一、上下文切换 即使单核CPU也可以进行多线程执行代码&#xff0c;CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短&#xff0c;所以CPU会不断地切换线程执行&#xff0c;从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

vue3+vite项目中使用.env文件环境变量方法

vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量&#xff0c;这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

2023赣州旅游投资集团

单选题 1.“不登高山&#xff0c;不知天之高也&#xff1b;不临深溪&#xff0c;不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

关键领域软件测试的突围之路:如何破解安全与效率的平衡难题

在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件&#xff0c;这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下&#xff0c;实现高效测试与快速迭代&#xff1f;这一命题正考验着…...