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

Linux 进程基础概念-进程状态、进程构成、进程控制

目录

Linux 进程

进程基础概念

进程状态

进程的构成

进程控制

进程创建和终止


Linux 进程

参考:

  • 「linux操作系统」进程的切换与控制·到底有啥关系? - 知乎 (zhihu.com),Linux进程解析_deep_explore的博客-CSDN博客,腾讯面试:进程的那些数据结构 - 知乎 (zhihu.com),如何在Linux下的进行多进程编程(初步) - 知乎 (zhihu.com),彻底搞定面试官,linux的进程里面的一些细节 - 知乎 (zhihu.com),操作系统进程的概念,进程的状态及状态转换,进程控制程小智的博客-CSDN博客进程的状态及其转换。

  • Linux 进程详解 - 程序员大本营 (pianshen.com)。Linux进程基础教程详解Linux脚本之家 (jb51.net)。

  • 【Linux】Linux进程的创建与管理Yngz_Miao的博客-CSDN博客linux 创建进程。

  • 《Linux System Prorgrammin》,Linux系统编程 _ 中文版 _ by _ 哈工大(翻译)-第五章-进程管理。

  • Linux 操作系统 C 语言编程入门。

进程基础概念

程序与进程

通俗的讲程序是一个包含可以执行代码的文件,是一个静态的文件。而进程是一个开始执行但是还没有结束的程序的实例。就是可执行文 件的具体实现。一个程序可能有许多进程,而每一个进程又可以有许多子进程。

进程状态

  1. 创建态:进程正在被创建,尚未转到就绪态。

  2. 就绪态:进程获得了除处理机以外的一切所需资源,一旦得到处理机便可立即运行。

    • 状态特点:处理机(或者理解为调度器)资源:只缺处理机。资源获得:已获得所需资源。当获得处理机时:立即运行。

    • 状态转换:就绪态——>运行态:处于就绪态的进程被调度后,获得处理机资源,于是进程由就绪态切换为运行态。

  3. 运行态:进程正在处理机上运行;对于单处理机,同一时刻只有一个进程处于运行态。

    • 状态转换:运行态——>就绪态:情况1:处于运行态的进程在时间片用完后,不得不让出处理机,进而转换为就绪态。情况2:在可剥夺的操作系统中,当有更高优先级的进程就绪时,调度程序将正在执行的进程转换为就绪态,让更高优先级的进程执行。

    • 状态转换:运行态——>阻塞态(主动行为):进程请求某一资源(如外设)的使用或等待某一事件的发生(如I/O操作的完成)时,它就从运行态转换为阻塞态。进程以系统调用的形式请求操作系统提供服务,这是一种特殊的,由用户态程序调用操作系统内核过程的形式。

  4. 阻塞态:又称等待态,进程正在等待某一事件而暂停运行/休眠,如等待某资源或IO完成,即使处理机空闲,该进程也不能运行。

    • 状态特点:处理机(或者理解为调度器)资源:可能缺;也可能不缺。资源获得:等待某资源可用或等待一件事情完成。当获得处理机时:即使处理机空闲,当等待的事情没有完成,仍无法运行。

    • 状态转换:阻塞态——>就绪态(被动行为,需要其他相关进程的协助):进程等待的事件到来,如I/O操作结束或中断结束时,中断处理程序必须把相应进程的状态由阻塞态转换为就绪态。

  5. 终止态:进程正从系统中消失,可能是进程正常结束或其他原因退出运行。

对应到 Linux 内核中,各个进程状态的标志:

  • TASK_RUNNING 说明进程已经准备好了,就看操作系统给不给分时间片在 CPU 上执行了,进程获得了时间片,就是执行状态,不分配时间片就是就绪状态。代表状态的字段又不用变。

    • 其实 TASK_RUNING 这个字段既对应了进程的就绪态又对应了进程的运行态。

    • 只有在该状态的进程才可能在 CPU上运行。而同 一时刻可能有多个进程处于可执行状态,这些进程的 task_struct结构(进程控制块)被放入对应 CPU的可执行队列中(一个进程最多只能出现在一个 CPU的可执行队列中)。进程调度器的任务就是从各个 CPU的可执行队列中分别选择一个进程在该 CPU 上运行。

    • 只要可执行队列不为空,其对应的 CPU就不能偷懒,就要执行其中某个进程。一般称此时的 CPU“忙碌”。对应的, CPU“空闲”就是指其对应的可执行队列为空,以致于 CPU无事可做。

    • 很多操作系统教科书将正在 CPU上执行的进程定义为 RUNNING状态、而将可执行但是尚未被调度执行的进程定义为 READY状态,这两种状态在 linux下统一为 TASK_RUNNING状态。

  • TASK_INTERRUPTIBLETASK_UNINTERRUPTIBLE 是两种睡眠状态,对应上面的阻塞状态。TASK_INTERRUPTIBLE 可以再被信号唤醒,TASK_UNINTERRUPTIBLE 不可被信号唤醒。

    • TASK_INTERRUPTIBLE,可中断的睡眠状态。处于这个状态的进程因为等待某某事件的发生(比如等待 socket连接、等待信号量),而被挂起。这些进程的 task_struct结构被放入对应事件的等待队列中。当这些事件发生时(由外部中断触发、或由其他 进程触发),对应的等待队列中的一个或多个进程将被唤醒。通过 ps命令我们会看到,一般情况下,进程列表中的绝大多数进程都处于 TASK_INTERRUPTIBLE状态(除非机器的负载很高)。

    • TASK_UNINTERRUPTIBLE,不可中断的睡眠状态。与 TASK_INTERRUPTIBLE状态类似,进程处于睡眠状态,但是此刻进程是不可中断的。不可中断,指的并不是 CPU不响应外部硬件的中断,而是指进程不响应异步信号。即 kill -9 无法 关掉/杀死 这种进程。TASK_UNINTERRUPTIBLE 状态存在的意义就在于,内核的某些处理流程是不能被打断的。如果响应异步信号,程序的执行流程中就会被插入一段用于处理异步信号的流程(这个插入的流程可能只存在于内核态,也可能延伸到用户态),于是原有的流程就被中断了。

      在进程对某些硬件进行操作时(比如进程调用 read 系统调用对某个设备文件进行读操作,而 read 系统调用最终执行到对应设备驱动的代码,并与对应的物 理设备进行交互),可能需要使用 TASK_UNINTERRUPTIBLE 状态对进程进行保护,以避免进程与设备交互的过程被打断,造成设备陷入不可控的 状态。这种情况下的 TASK_UNINTERRUPTIBLE 状态总是非常短暂的,通过 ps 命令基本上不可能捕捉到。Linux系统中也存在容易捕捉的 TASK_UNINTERRUPTIBLE状态。执行 vfork系统调用后,父进程将进入TASK_UNINTERRUPTIBLE状态,直到子进程调用 exit或 exec。

  • TASK_STOPPED 是在进程收到 SIGSTOP 以及 SIGTTIN 等信号的状态,你 Linux 进程运行起来按 Ctrl + z 后进程就是这个状态。

    • 向进程 发送一个 SIGSTOP信号,它就会因响应该信号而进入 TASK_STOPPED状态(除非该进程本身处于 TASK_UNINTERRUPTIBLE状态而不响应信号)。( SIGSTOP与 SIGKILL信号一样,是非常强制的。不允许用户进程通过 signal系列的系统调用重新设置对应的信号处理函数。)

    • 向进程发送一个 SIGCONT信号,可以让其从 TASK_STOPPED状态恢复到 TASK_RUNNING状态。

  • TASK_TRACED 是进程被监视的状态。

    • 当进程正在被跟踪时,它处于 TASK_TRACED这个特殊的状态。“正在被跟踪”指的是进程暂停下来,等待跟踪它的进程对它进行操作。比如在 gdb中 对被跟踪的进程下一个断点,进程在断点处停下来的时候就处于 TASK_TRACED状态。而在其他时候,被跟踪的进程还是处于前面提到的那些状态。

    • TASK_STOPPED和 TASK_TRACED状态判断。对于进程本身来说, TASK_STOPPED和 TASK_TRACED状态很类似,都是表示进程暂停下来。而 TASK_TRACED状态相当于在 TASK_STOPPED之上多了一层保护,处于 TASK_TRACED状态的进程不能响应 SIGCONT信号而 被唤醒。只能等到调试进程通过 ptrace系统调用执行 PTRACE_CONT、 PTRACE_DETACH等操作(通过 ptrace系统调用的参数指定 操作),或调试进程退出,被调试的进程才能恢复 TASK_RUNNING状态。

  • TASK_DEAD - EXIT_ZOMBIE,退出状态,进程成为僵尸进程。EXIT_DEAD 是最终状态,进入这个状态代表进程要从系统中删除了EXIT_ZOMBIEEXIT_DEAD 的前一个状态,这个时候进程已经终止,但父进程还没有用 wait() 等系统调用来获取他的终止信息,这个状态的进程叫做僵尸进程。这个状态 kill 命令是杀不死的,你们可以想以下应该怎样清楚僵尸进程,以及怎样避免僵尸进程的存在。

    关于 退出 相关的 进程状态(上面四个),更多可详见  Linux进程解析_deep_explore的博客-CSDN博客。

Linux 进程状态转换示意图:

系统进程常见的 STAT 代码:

就绪队列与阻塞队列:

就绪队列:系统中处于就绪状态的进程可能有多个,通常把它们排成一个队列。只要就绪队列不空,CPU就总是可以调度进程运行,保持繁忙,这与就绪进程的数目没有关系;除非就绪队列为空,此时CPU进入等待态,CPU效率下降。

阻塞队列:系统通常将处于阻塞态的进程也排成一个队列,甚至根据阻塞原因不同,设置多个阻塞队列。

进程的构成

引自 进程的那些数据结构 - 知乎 (zhihu.com),Linux下的task_struct结构体 - 百度文库 (baidu.com)。

进程一般由以下几个部分组成:

  • 进程控制块(PCB):每个进程在创建时, 系统都会为进程创建一个相应的 PCB。PCB 是进程存在的唯一标志。

    • 创建进程实质就是创建进程的 PCB。PCB 要能展示进程身份和关系,标记任务状态,标记权限,帮助任务调度等等。

    • Linux 内核中是把进程和线程统一当作任务来实现的,Linux 内核的 进程控制块 是 task_struct 结构体,里面包含有:

      • The identifier of the process (a process identifier , or PID) ;(进程的标识自身的唯一标识符 PID)

      • Register values for the process including, notably, the program counter and stack pointer values for the process;(进程调度时候退出时间片(保存现场)与进入时间片(恢复现场)时候用到的寄存器值包括栈指针 SP、程序计数器 PC 等等)

      • The address space for the process;(进程的地址空间)

      • Priority (in which higher priority process gets first preference. eg., nice value on Unix operating systems);(优先级)

      • Process accounting information, such as when the process was last run, how much CPU time it has accumulated, etc;

      • Pointer to the next PCB i.e. pointer to the PCB of the next process to run;

      • I/O Information (i.e. I/O devices allocated to this process, list of opened files, etc).

    • pid_t pid;    // 展示自己进程的 id
      pid_t tgid;  // 进程主线程的id
      struct task_struct *group_leader;  // 指向主线程地址

      每个进程都会创建一个主线程,所以如果只是单独一个进程,以及进程默认创建的主线程,那么 pidtgid 都会是自己。如果是一个进程创建的子线程,那么 pid 就是自己的 idtgid 就指向进程主线程的 id。

    • struct task_struct __rcu * real_parent;
      struct task_struct __rcu * parent;   // 指向父进程
      struct list_head children;   // 父进程的所有子进程都在子进程链表中,这里指向链表的头部。
      struct list_head sibling;  // 连接兄弟进程

      进程是一个树状的结构(使用链表组成的树),除了 0 号进程外,所有的进程都是由父进程创建的,所以对父进程的操作很容易就会影响到子进程。所以进程的数据结构中自然要显示出进程有哪些父子进程以及兄弟进程。

  • 程序段:程序段是进程中能被进程调度程序调度到 CPU 上执行的程序代码段。

  • 数据段:可以是进程对应程序加工的原始数据,也可以是程序执行时产生的中间 结果或结果数据。

进程控制

进程控制的主要功能是对系统中的所有进程实施有效的管理,它具有创建新进程、撤销已有进程、实现进程状态转换等功能。简而言之,进程控制就是为了实现进程状态转换。

一般 进程控制 的 程序段 是 “原子操作” 的,执行过程 期间不允许被中断;它使用 “关中断指令” 和 “开中断指令” 这两个特权指令实现原子性。

进程创建和终止

进程控制之进程创建和终止 相关的概念。

引起进程创建的事件

  • 用户登陆:分时系统中,用户登陆成功,系统会为其建立一个新的进程。

  • 作业调度:多道批处理系统中,有新的作业放入内存时,会为其建立一个新的进程。

  • 提供服务:用户向操作系统提出某些请求时,会新建一个进程处理该请求。启动程序执行都会创建一个新进程。

  • 应用请求:由用户进程主动请求创建一个子进程。

操作系统创建新进程的过程

  1. Step1:为新进程分配一个唯一的进程标识号,并申请一个空白PCB(PCB是有限的),若PCB申请失败,则创建失败。

  2. Step2:为进程分配所需资源,如文件、内存、I/O设备和CPU时间等。这些资源从操作系统获得,或从其父进程获得。如果资源不足(如内存),则此时并不是创建失败,而是处于创建态,等待内存资源。

  3. Step3:初始化PCB,主要包括初始化标志信息、初始化处理机状态信息和初始化处理机控制信息,以及设置进程的优先级等。

  4. Step4:若进程就绪队列能够接纳新进程,则将新进程插入就绪队列,等待被调度运行。

父进程创建子进程

允许一个进程创建另一个进程,此时创建者称为父进程,被创建的进程称为子进程。子进程可以继承父进程所拥有的资源;当子进程被撤销时,应将其从父进程那里获得的资源归还给父进程;当父进程被撤销时,通常也会同时撤销其所有的子进程。父进程和子进程共享一部分资源,但不能共享虚拟地址空间,在创建子进程时,会为子进程分配资源,如虚拟地址空间等。

父进程与子进程当然可以并发执行。进程控制块(PCB)是进程存在的唯一标志,每个进程都有自己的PCB。父进程与子进程不能同时使用同一临界资源,临界资源一次只能被一个进程使用(临界资源就是加了锁机制,只能被互斥地访问)。

Linux 系统创建进程都是由已存在的进程创建的(除了0号进程),被创建的进程叫做子进程,创建子进程的进程就做父进程。Linux 进程串起来是一颗树的结构。

引起进程终止的事件

  • 正常结束:表示进程的任务已完成并准备退出运行。

  • 异常结束:表示进程在运行时,发生了某种异常事件,使程序无法继续运行,如存储区越界、保护错、非法指令、特权指令错、运行超时、算术运算错、I/O故障等。

  • 外界干预:指进程应外界的请求而终止运行,如操作员或操作系统干预、父进程请求和父进程终止。

操作系统终止进程的过程

  1. Step1:根据被终止进程的标识符(PID),检索出该进程的PCB,从中读出该进程的状态。

  2. Step2:若被终止的进程正处于运行态,应立即终止该进程的运行,将处理机资源分配给其他进程。

  3. Step3:若该进程还有子孙进程,则应当将其所有子孙进程终止。

  4. Step4:将该进程所拥有的全部资源,或归还给其父进程,或归还给操作系统。

  5. Step5:该PCB从所在队列中删除。

查看和释义各个进程

我们在 Linux 系统上通过 ps - ef 命令查看系统目前的进程。

  • UID 就是用户的标识符(通过 root 用户创建的进程 UID 就是 root,如果我自己创建的话就应该是我的用户名。

  • PID 就表示的是当前进程的 id。

  • PPID 就表示当前进程的父进程 id。

通过 0 号进程创建 1 号进程和 2 号进程,然后通过 1 号进程去创建用户态进程,再通过 2 号进程创建内核态进程,就生成了 Linux 进程树。

  • 0号进程:在内核初始化的过程中,会先通过指令 struct task_struct init_task = INIT_TASK(init_task) 创建 0 号进程。这是唯一一个没有通过 fork 或者 kernel_thread 产生的进程。是进程列表的第一个。但是这个进程不是实际意义上的进程,类似与链表头。所以虽然 0 号进程是在内核态创建的,但不能说 0 号进程是内核态的第一个进程,反而要说 2 号进程是内核态的第一个进程。

  • 1号进程:通过调用指令 kernel_thread(kernel_init, NULL, CLONE_FS) 从内核态切换到用户态来创建的,1号进程是所有用户态的祖先。进程1也叫做init进程,它是内核初始化时创建的第2个内核线程,其运行代码为内核函数init()。只要系统不结束,init进程就永不中止,它负责创建和监控操作系统外层所有进程的活动。

  • 2号进程:通过调用指令 kernel_thread(kthreadd, NULL, ClONE_FS | CLONE_FILES) 来创建,2号进程负责所有内核态的进程的调度和管理,是内核态所有进程的祖先。(注意,内核态不区分线程和进程,所以说进程和线程都可以,都是任务)。

pstree 命令来显示整个进程树, Linux基础命令---显示进程树pstree_weixin_34023863的博客-CSDN博客。

相关文章:

Linux 进程基础概念-进程状态、进程构成、进程控制

目录 Linux 进程 进程基础概念 进程状态 进程的构成 进程控制 进程创建和终止 Linux 进程 参考: 「linux操作系统」进程的切换与控制到底有啥关系? - 知乎 (zhihu.com),Linux进程解析_deep_explore的博客-CSDN博客,腾讯面试…...

Unity Animation、Animator 的使用

文章目录 1. 添加动画2. Animation2.1 制作界面2.2 制作好的 Animation 动画2.3 添加和使用事件 3. Animator3.1 制作界面3.2 一些参数解释3.3 动画参数 4. Animator中相关类、属性、API4.1 类4.2 属性4.3 API4.4 几个关键方法 5. 动画播放和暂停控制 1. 添加动画 选中待提添加…...

Flink--2、Flink部署(Yarn集群搭建下的会话模式部署、单作业模式部署、应用模式部署)

星光下的赶路人star的个人主页 你必须赢过,才可以说不在乎输赢 文章目录 1、Flink部署1.1 集群角色1.2 Flink集群搭建1.2.1 集群启动1.2.2 向集群提交作业 1.3 部署模式1.3.1 会话模式(Session Mode)1.3.2 单作业模式(Per-Job Mod…...

执行Django 的迁移命令报错[1193, Unknown system variable default_storage_engine]

在学习“”编写你的第一个 Django 应用程序,第2部分”时候,遇到一个问题。 执行迁移命令 python manage.py makemigrations polls 后,报错: migrations.py:109: RuntimeWarning: Got an error checking a consistent migration …...

Himall商城-公共方法

目录 1 Himall商城-公共方法 1.1 /// 根据订单id获取订单项 1.2 /// 根据订单项id获取售后记录 1.3 /// 判断订单是否正在申请售后 Himall商城-公共方法 #region 公共方法 public static List<InvoiceTitleInfo> GetInvoiceTitles(long userid) {...

海域可视化监管:浅析海域动态远程视频智能监管平台的构建方案

一、方案背景 随着科技的不断进步&#xff0c;智慧海域管理平台已经成为海洋领域监管的一种重要工具。相比传统的视频监控方式&#xff0c;智慧海域管理平台通过建设近岸海域视频监控网、海洋环境监测网和海上目标探测网络等&#xff0c;可实现海洋管理的数字化转型。 传统的…...

使用Spring Boot + MyBatis实现多数据源

一、引言 在开发中&#xff0c;我们经常会遇到需要连接多个数据库的情况。使用Spring Boot和MyBatis框架可以很方便地实现多数据源的配置和使用。本文将详细介绍如何在Spring Boot项目中使用多数据源。 二、实操 1、添加所需的依赖&#xff1a; <!-- Spring Boot Starte…...

C++中的无限循环

C中的无限循环 while、 do…while 和 for 循环都包含一个条件表达式&#xff0c;在它为 false 时循环结束。如果您指定的条件总是为 true&#xff0c;循环就不会结束。 无限 while 循环类似于下面这样&#xff1a; while(true) // while expression fixed to true {DoSomethi…...

Spark2x原理剖析(二)

一、概述 基于社区已有的JDBCServer基础上&#xff0c;采用多主实例模式实现了其高可用性方案。集群中支持同时共存多个JDBCServer服务&#xff0c;通过客户端可以随机连接其中的任意一个服务进行业务操作。即使集群中一个或多个JDBCServer服务停止工作&#xff0c;也不影响用…...

tomcat安装、部署JSPGOU项目、Tomcat多实例

安装 官网找包 Apache Tomcat - Welcome! tomcat 8 准备运行环境 安装tomcat catalina.sh 服务脚本管理文件 server.xml 主配置文件 修改8009&#xff08;删除注释&#xff09; 启动tomcat 访问 为了避免每次进入绝对路径启动tomcat 法二&#xff1a; 三&#xff1a;部署…...

257. 二叉树的所有路径

题目链接&#xff1a; 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 我的想法&#xff1a; 层次遍历不好解&#xff0c;可用找到叶子节点&#xff0c;但是他有一个回溯过程&#xff0c;他要一直保留路径节点&#xff0c;层次迭代不好加回溯。 递归…...

windows10使用wheel安装tensorflow2.13.0/2.10.0

安装过程 安装虚拟环境安装virtualenv安装满足要求的python版本使用virtualenv创建指定python版本的虚拟环境 安装tensorflow安装tensorflow-docs直接下载使用wheel下载 在VSCode编辑器中使用虚拟环境下的包 注意&#xff1a; tensorflow 2.10.0是最后一个支持GPU的版本 安装虚…...

sql-gen:点击生成SQL、RO、VO的工具

sql-gen仓库地址&#xff1a;码云 Github 1. 概述 sql-gen是一个用于提高后端接口开发效率的小工具&#xff0c;主要有如下功能&#xff1a; 生成连表SQL语句根据WHERE条件来生成封装查询条件的实体类&#xff08;RO&#xff09;根据SELECT列来生成封装查询结果的实体类&…...

pytorch从0开始安装

文章目录 一. 安装anaconda1.安装pytorch前需要先安装anaonda&#xff0c;首先进入官网&#xff08;Anaconda | The Worlds Most Popular Data Science Platform&#xff09;进行安装相应的版本。2.接着按如图所示安装,遇到下面这个选项时&#xff0c;选择all users.3.选择自己…...

Java 语言实现最小生成树算法(如Prim算法、Kruskal算法)

引言&#xff1a; 在图论中&#xff0c;最小生成树是指一个无向图的生成树&#xff0c;其所有边的权值之和最小。解决最小生成树问题的两种主要算法是Prim算法和Kruskal算法。本文将深入探讨这两种算法并比较它们的优缺点&#xff0c;以帮助读者更好地理解最小生成树算法的原理…...

什么是Linux的Overcommit和OOM

overcommit_memory参数说明&#xff1a; 设置内存分配策略&#xff08;可选&#xff0c;根据服务器的实际情况进行设置&#xff09; /proc/sys/vm/overcommit_memory 可选值&#xff1a;0、1、2。 0&#xff0c; 表示内核将检查是否有足够的可用内存供应用进程使用&#xf…...

解决防火墙导致虚拟机不能ping通宿主机的问题

今天&#xff0c;无缘无故的&#xff0c;虚拟机突然用不了&#xff0c;网络连上不了&#xff0c;一番折腾翻找&#xff0c;最后才发现&#xff0c;是因为虚拟机ping不同宿主主机了&#xff0c;连网关都ping不通了&#xff0c;但是&#xff0c;宿主主机却可以ping通虚拟机 。 最…...

数据结构:线性表(栈的实现)

文章目录 1. 栈(Stack)1.1 栈的概念1.2 栈的结构链表栈数组栈 2. 栈的定义3. 栈的实现3.1 初始化栈 (StackInit)3.2 入栈 (StackPush)3.3 出栈 (StackPop)3.4 检测栈是否为空 (StackEmpty)3.5 获取栈顶元素 (StackTop)3.6 获取栈中有效元素个数 (StackSize)3.7 销毁栈 (StackDe…...

python如何将一个dataframe快速写入clickhouse

目录 前言思路与核心代码优缺点分析 前言 dataframe是用python做数据分析最场景的数据结构了&#xff0c;如何将dataframe数据快速写入到clickhouse数据库呢&#xff1f;这里介绍几种方法&#xff0c;各有优劣势&#xff0c;可以结合自己的使用场景挑用。 思路与核心代码 假…...

Tiny Player Mac:小而美,音乐播放的极致体验

对于追求音质和操作简便的Mac用户来说&#xff0c;Tiny Player Mac是一款不可多得的音乐播放器。它以简洁的界面、强大的功能和优异的性能&#xff0c;吸引了无数用户的目光。接下来&#xff0c;让我们一起了解这款小而美的音乐播放器。 Tiny Player Mac支持多种音频格式&#…...

使用VSCode开发Django指南

使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架&#xff0c;专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用&#xff0c;其中包含三个使用通用基本模板的页面。在此…...

练习(含atoi的模拟实现,自定义类型等练习)

一、结构体大小的计算及位段 &#xff08;结构体大小计算及位段 详解请看&#xff1a;自定义类型&#xff1a;结构体进阶-CSDN博客&#xff09; 1.在32位系统环境&#xff0c;编译选项为4字节对齐&#xff0c;那么sizeof(A)和sizeof(B)是多少&#xff1f; #pragma pack(4)st…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力

引言&#xff1a; 在人工智能快速发展的浪潮中&#xff0c;快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型&#xff08;LLM&#xff09;。该模型代表着该领域的重大突破&#xff0c;通过独特方式融合思考与非思考…...

将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?

Otsu 是一种自动阈值化方法&#xff0c;用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理&#xff0c;能够自动确定一个阈值&#xff0c;将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...

在WSL2的Ubuntu镜像中安装Docker

Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包&#xff1a; for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

淘宝扭蛋机小程序系统开发:打造互动性强的购物平台

淘宝扭蛋机小程序系统的开发&#xff0c;旨在打造一个互动性强的购物平台&#xff0c;让用户在购物的同时&#xff0c;能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机&#xff0c;实现旋转、抽拉等动作&#xff0c;增…...

鸿蒙(HarmonyOS5)实现跳一跳小游戏

下面我将介绍如何使用鸿蒙的ArkUI框架&#xff0c;实现一个简单的跳一跳小游戏。 1. 项目结构 src/main/ets/ ├── MainAbility │ ├── pages │ │ ├── Index.ets // 主页面 │ │ └── GamePage.ets // 游戏页面 │ └── model │ …...

虚幻基础:角色旋转

能帮到你的话&#xff0c;就给个赞吧 &#x1f618; 文章目录 移动组件使用控制器所需旋转&#xff1a;组件 使用 控制器旋转将旋转朝向运动&#xff1a;组件 使用 移动方向旋转 控制器旋转和移动旋转 缺点移动旋转&#xff1a;必须移动才能旋转&#xff0c;不移动不旋转控制器…...

Pandas 可视化集成:数据科学家的高效绘图指南

为什么选择 Pandas 进行数据可视化&#xff1f; 在数据科学和分析领域&#xff0c;可视化是理解数据、发现模式和传达见解的关键步骤。Python 生态系统提供了多种可视化工具&#xff0c;如 Matplotlib、Seaborn、Plotly 等&#xff0c;但 Pandas 内置的可视化功能因其与数据结…...