当前位置: 首页 > 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;实时跟踪施工进度和质量…...

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…...

【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表

1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

相机从app启动流程

一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

现代密码学 | 椭圆曲线密码学—附py代码

Elliptic Curve Cryptography 椭圆曲线密码学&#xff08;ECC&#xff09;是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础&#xff0c;例如椭圆曲线数字签…...

【决胜公务员考试】求职OMG——见面课测验1

2025最新版&#xff01;&#xff01;&#xff01;6.8截至答题&#xff0c;大家注意呀&#xff01; 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:&#xff08; B &#xff09; A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

今日科技热点速览

&#x1f525; 今日科技热点速览 &#x1f3ae; 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售&#xff0c;主打更强图形性能与沉浸式体验&#xff0c;支持多模态交互&#xff0c;受到全球玩家热捧 。 &#x1f916; 人工智能持续突破 DeepSeek-R1&…...

代理篇12|深入理解 Vite中的Proxy接口代理配置

在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...

基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解

JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用&#xff0c;结合SQLite数据库实现联系人管理功能&#xff0c;并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能&#xff0c;同时可以最小化到系统…...

CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝

目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为&#xff1a;一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...