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

Linux 进程基础(三):进程是什么、进程的创建与查看

摘要:

目录

  • ➡️〇、导入:OS 的管理对象与管理“起点”
    • 1. OS管理的对象是谁?
    • 2. OS 何时开始管理对象:以U盘插入为例
      • (1)硬件插入与检测:物理连接≠立即管理
      • (2)驱动程序加载:管理的核心起点🟢
      • (3)资源分配与逻辑映射:从物理设备到可操作对象
    • 3. 类比理解:学校管理 🆚 OS管理
  • 一、💻进程是什么?
    • 1. 概念上:正在执行的程序
    • 2. 实际上:担当分配资源的实体
  • 二、进程管理的基石:描述进程
    • 1. PCB:进程控制块
    • 2. Linux:task_struct
      • (1)核心字段解析
      • (2)双链表结构简析
  • 三、如何查看进程?
    • 1. 查看进程信息的方法
    • 2. 区分 cwd 与 pwd
  • 四、如何创建进程?
    • 1. 命令行中直接启动进程:bash
      • 1)bash 是一个进程,且被内核统一管理
        • 🤔bash 的 Parent Process 是用户态吗?登录进程何时启动?
      • 2)bash 是内核与用户之间的 “交互中介”,但并非唯一中介
        • 🤔系统调用是操作系统内部的代码吗?
        • 🤔开发人员写的代码直接使用系统调用函数,算 “直接调用” 吗?bash 在其中起什么作用?
        • 🤔为什么登录程序和 bash 都要 “先创建子进程再替换”?
    • 2. 通过代码创建进程:fork
      • fork函数特殊的返回值机制
      • 进程的独立性与写时拷贝 (Copy-on-Write, COW)


➡️〇、导入:OS 的管理对象与管理“起点”

OS怎么算管理了对象👉管理的对象是谁?什么时候开始管理的?例如, U盘插入到电脑里就被管理起来了吗?

OS 对 对象的管理是一个涉及硬件检测、驱动加载、资源分配的复杂过程。以下将以U盘插入为例拆解具体流程:

1. OS管理的对象是谁?

OS管理的对象可分为硬件资源软件资源两大类,具体包括:

  • 硬件资源
    • 存储设备(硬盘、U盘、SSD等)
    • 输入输出设备(键盘、鼠标、显示器、打印机等)
    • 计算资源(CPU、内存)
    • 网络设备(网卡、路由器等)
  • 软件资源
    • 进程 与线程(程序运行实例)
    • 文件系统(文件、目录、权限)
    • 内存空间(虚拟内存、物理内存分配)
    • 网络连接(Socket、端口)

2. OS 何时开始管理对象:以U盘插入为例

(1)硬件插入与检测:物理连接≠立即管理

  • 动作起点:U盘插入USB接口。
  • 系统反应:USB控制器检测到接口电压变化(硬件层面的物理信号)。控制器向CPU发送中断请求(IRQ),告知“有设备接入”。

此时OS仅知道“有硬件插入”,但尚未开始真正管理,因为:

  • 不知道设备类型(U盘、键盘或其他)。
  • 无法操作设备(无驱动程序、未分配资源)。

(2)驱动程序加载:管理的核心起点🟢

  • 步骤1:设备识别
    • U盘通过USB接口发送设备描述符(包含厂商ID、产品ID等信息)。
    • OS根据描述符查找对应的驱动程序(Windows在注册表/驱动库,Linux在/lib/modules)。
  • 步骤2:驱动初始化
    • 加载驱动程序到内存,执行初始化函数(如注册设备操作接口)。
    • 驱动向OS注册设备类型(如“存储设备”),并声明可支持的操作(读写、格式化等)。

驱动加载完成时,OS才真正开始管理设备

  • 此时可:
    • 通过驱动控制设备硬件(如发送指令读取U盘存储介质)。
    • 为设备分配系统资源(如内存缓冲区、中断号)。

(3)资源分配与逻辑映射:从物理设备到可操作对象

  • 步骤1:分配设备标识符
    • Windows分配盘符(如F:),Linux创建设备文件(如/dev/sdb)。
    • 建立设备与文件系统的映射关系(如FAT32、NTFS文件系统)。
  • 步骤2:文件系统挂载
    • 扫描U盘文件系统结构(目录、文件元数据)。
    • 为用户提供可视化接口(如资源管理器中显示U盘图标)。
  • 用户可见结果:此时U盘可被读写操作,即OS完成了从“物理设备”到“可管理资源”的转换。
  • 非管理阶段:插入瞬间至驱动加载前,OS仅知道设备物理存在,但无法执行任何操作(类似“看到人但不知道身份”)。
  • 管理开始阶段:驱动程序加载并初始化后,OS获得设备控制权,可进行:
    • 状态监控(如U盘剩余空间、读写状态)。
    • 资源调度(如分配CPU时间片处理U盘读写请求)。
    • 安全管理(如权限控制、病毒扫描)。

3. 类比理解:学校管理 🆚 OS管理

场景学校管理类比OS设备管理对应逻辑
物理进入人员进入校园区域U盘插入USB接口
身份识别核查证件(学生证、工作证)读取设备描述符(厂商ID等)
注册登记录入系统(学生档案、员工表)驱动程序加载并注册设备
开始管理纳入考勤、权限管理分配盘符、文件系统挂载
可操作控制安排课程、工作任务读写文件、格式化等操作

PS.特殊情况说明

  • 无驱动程序时:若OS找不到U盘驱动(如老旧设备或自定义硬件),则无法管理,设备显示为“未知设备”(类似学校里未登记的访客,无法使用校园系统)。
  • 热插拔与冷启动管理差异
    • U盘(热插拔):插入时动态加载驱动。
    • 内置硬盘(非热插拔):系统启动时(BIOS阶段)已检测并加载驱动,管理起点为系统启动完成时。
U盘USB控制器CPU驱动程序内核(资源管理)用户插入USB接口检测到电压变化发送中断请求(告知设备接入)响应中断,触发设备处理流程非管理阶段启动驱动加载流程请求设备描述符(设备识别)返回设备描述符(如类型、厂商信息)查找匹配的驱动程序完成驱动初始化(准备交互)管理开始阶段申请资源分配分配设备标识符(如/dev/sdb或盘符)挂载文件系统(识别分区格式)通知设备就绪进行读写操作(通过内核接口)U盘USB控制器CPU驱动程序内核(资源管理)用户

一、💻进程是什么?

1. 概念上:正在执行的程序

  • e.g. 打开电脑上的浏览器,浏览器这个程序开始运行,它就成为了一个进程;
  • e.g. 启动音乐播放器播放歌曲,音乐播放器程序也变成了一个进程。

它们都处于运行状态。

2. 实际上:担当分配资源的实体

计算机的资源就像是城市里的各种基础设施,如道路、电力、水源等。进程在运行时,需要获取 CPU 的计算资源来执行代码,需要占用内存空间来存储数据和程序指令,还可能需要访问磁盘、网络等其他资源OS 就像城市的管理者,会根据进程的需求,合理地分配这些资源,让各个进程都能有序运行。

进程(Process)程序(Program) 的区别:

  • 程序:它是一组静态的指令集合,就好比是一本菜谱,静静地躺在计算机的磁盘上,不会主动做任何事情。🌰 下载的游戏安装包、办公软件的安装文件……
  • 进程:当程序被加载到内存中并开始执行时,它就变成了进程。进程是动态的,具有生命周期,会经历创建、运行、暂停、终止等阶段。就像根据菜谱开始烹饪美食的过程,从准备食材、烹饪到最终上菜,这一系列动态的操作就是进程。

二、进程管理的基石:描述进程

想要管理进程,得先把进程是什么、有哪些特点搞清楚。就像要管理好一群人,得先了解每个人的情况一样,只有描述清楚进程,后续管理操作才能顺利进行。

在计算机系统运行时,当我们一边用音频播放器听歌,一边运行游戏客户端打游戏,同时还打开电子书阅读软件看小说、视频播放程序刷剧时,这些应用程序对应的进程都会同时被加载到内存空间里运行。虽然从简单概念来说,程序加载就是把数据从硬盘等外存复制到内存,但实际的进程管理远比这复杂得多。
在这里插入图片描述

多个进程会同时运行,操作系统必须有一套完善的管理方法。 首先,系统需要详细记录每个进程的关键信息:

  • 进程标识符就像是每个进程的“身份证号”,能唯一确定一个进程;
  • 进程的运行状态则反映了它当前的情况,比如正在运行、准备运行或是因为等待资源而暂停;
  • 此外,进程的优先级占用了哪些系统资源等,也都是进程的重要属性。

这些信息合起来,就构成了对单个进程的完整描述。

对多进程进行统一集中的管理,就好比图书馆里有很多图书卡片,如果卡片散乱摆放,管理员找书就很困难。OS需要一种特殊的数据结构,把这些分散的进程信息整合起来。进程控制块 (Process Control Block,PCB) 就是这个关键 “工具”。PCB 里存储了进程标识符、运行状态、资源使用情况、程序下一步执行位置(程序计数器)等重要数据。通过链表、队列等数据结构,系统能把所有进程的 PCB 串联起来,形成一个进程管理 “目录”。这样一来,操作系统就能轻松地对进程进行创建、调度、终止等全流程管理,保障整个系统稳定高效地运行。

1. PCB:进程控制块

  • PCB(Process Control Block,进程控制块),可以理解为记录进程的“个人档案📄”的专属结构体 struct,包含了进程的所有属性合集,用于记录和管理进程的各种信息。
  • 注意:即使可执行程序文件被删除了,正在运行的进程依然可以继续运行,因为进程运行时依赖的是加载到「内存」中的代码和数据,而不是磁盘上的程序文件。

2. Linux:task_struct

Linux 系统中的 PCB 「具体表现」为 task_struct。task_struct(双链表) 就是用于描述进程的结构体 struct。当系统创建一个进程时,就会在内存中创建一个 task_struct 实例,里面包含了进程的各种重要信息。下面我们来详细看看它的核心字段:
代码片段-图例

(1)核心字段解析

  • 标识符
    • pid(Process identity,进程标识符):就像每个人都有独一无二的身份证号,每个进程都有自己的 pid,用于在系统中唯一标识这个进程。
    • ppid(Parent Process identity):表示该进程的 Parent 进程的 pid。在 Linux 中,通过命令行启动的进程,它们的 parent process 通常都是 bash。🌰 在终端中输入 ls 命令查看文件列表,这个 ls 进程就是 bash 进程的 child process。
  • 状态:用于表示进程当前所处的状态,例如运行态(正在使用 CPU 执行)、就绪态(准备好运行,等待 CPU 分配时间片)、阻塞态(因为等待某个资源,如 I/O 操作完成而暂停)。
  • 优先级:决定了进程在竞争 CPU 资源时的优先程度,优先级高的进程更容易获得 CPU 时间片来执行。
  • 程序计数器:记录了进程下一条要执行的指令在内存中的地址。
  • 内存指针:指向进程所占用的内存空间,方便操作系统管理进程的内存资源。
  • 上下文数据:保存了进程在运行过程中的各种中间数据和寄存器状态,当进程暂停或恢复运行时,这些数据可以保证进程能够继续正确执行。
  • I/O 状态信息:记录了进程进行输入输出操作(如读写文件、网络通信)的相关状态。
  • 记账信息:用于统计进程占用 CPU 时间、内存使用量等资源使用情况,方便操作系统进行资源管理和计费(在一些商业系统中)。
  • other:还可能包含其他一些与进程相关的信息。

(2)双链表结构简析

prev/next指向其他节点(形成双链表)
1
0..n
list_head
+ list_head* prev // 指向链表前一个节点
+ list_head* next // 指向链表后一个节点
+void list_add(list_head* new, list_head* head)
+void list_del(list_head* entry)
+void list_move(list_head* entry, list_head* new_head)
+bool list_empty(list_head* head)
task_struct
+ pid_t pid // 进程ID
+ int state // 进程状态(就绪/运行/阻塞等)
+ list_head run_list // 双链表节点(用于加入就绪队列等)
+ ... // 其他进程属性(内存、优先级等)

在这里插入图片描述
如上图:

在 Linux 中,task_struct 就像一个带多个 “魔术扣” 的文件夹(比如图中的 p1),每个魔术扣就是 list_head(如 run_listwait_list)。这些魔术扣的特点是:

  1. 只扣住同类文件夹:同一个魔术扣只能连接状态相同的进程(比如 run_list 魔术扣只连接 “可运行” 的进程);
  2. 不存文件夹完整地址:魔术扣本身只记录前后相邻魔术扣的位置,但通过 “魔术算法” 能反向推算出自己所属文件夹的位置。

当进程状态变化时(比如从 “运行” 变 “等待”),内核只需:

  • 将该进程的 run_list 魔术扣从 ready_queue 链上摘下;
  • wait_list 魔术扣挂到 wait_queue 链上。

如何挂载到链表?

当内核需要将进程加入某个队列时:

  1. 找到目标链表的头节点(例如调度器的就绪队列)。
  2. 修改指针:将进程的run_list标签插入到链表中。
// 伪代码:将进程添加到就绪队列struct task_struct *p = ...; // 要添加的进程struct list_head *ready_queue = ...; // 就绪队列头// 将进程的run_list标签插入到就绪队列list_add(&p->run_list, ready_queue);// 等价于以下指针操作:
p->run_list.next = ready_queue->next;
p->run_list.prev = ready_queue;
ready_queue->next->prev = &p->run_list;
ready_queue->next = &p->run_list;
  • 链表操作只涉及list_head的指针,不影响task_struct的其他部分。
  • 同一个进程可以通过不同的list_head同时存在于多个链表中。

三、如何查看进程?

1. 查看进程信息的方法

在 Linux 系统中,我们可以通过多种方式查看进程的相关信息📋:

  • /proc(系统文件):这是一个非常神奇的虚拟文件系统,它里面存储了系统中所有进程的相关信息。
    • 每个进程在 /proc 目录下都有一个以其 pid 命名的子目录,比如 pid1000 的进程,它的信息就存储在 /proc/1000 目录下。
    • 在这个目录中,我们可以找到进程的各种信息文件,如记录进程状态的 status 文件、记录进程命令行参数的 cmdline 文件等。
      在这里插入图片描述
  • getpid(function):在编程中,如果我们想获取当前进程的 pid,可以使用 getpid 函数。例如在 C 语言中,只需要调用 getpid() 函数,它就会返回当前进程的 pid

2. 区分 cwd 与 pwd

  • cwd(Current Working Directory,当前工作目录)
    • 它是进程的一个系统属性,表示 进程当前的工作目录
    • 在 Linux 中,我们可以通过 /proc/{进程ID}/cwd 这个符号链接查看进程的 cwd
    • 在编程中(如 C/C++),可以使用 getcwd() 函数获取当前进程的 cwd
  • pwd(Print Working Directory,打印工作目录)
    • 这是 Linux/Unix 系统的内置命令,用于在终端中显示当前所在的工作目录的绝对路径。
  • 关键点:默认情况下,程序启动的路径就是当前所在路径(即 cwd)。不过我们可以通过 chdir 函数来更改进程的工作目录 (cwd)。

四、如何创建进程?

在 Linux 系统中,创建进程主要有以下两种方式:

1. 命令行中直接启动进程:bash

这是最常见的手动启动方式。当我们在终端中输入一个命令,如ls。从本质上讲,启动进程的过程就是创建进程的过程。命令行启动的进程都是 bash 的 Child Process

⚠注意:bash 并非所有用户进程的 Parent Process,而是 “用户通过 bash 交互而启动的进程” 的 Parent Process。

1)bash 是一个进程,且被内核统一管理

  • bash 本质上是一个用户态应用程序,当用户登录 Linux 系统(如通过终端、SSH)时,系统会启动一个 bash 进程(进程类型为interactive shell)。
  • bash 是一个进程,由内核的进程管理模块统一管控:内核会为 bash 分配 PID(进程 ID)、管理其生命周期(创建、运行、暂停、终止)、调度 CPU 时间片,并通过进程控制块(PCB)记录其状态(如运行态、就绪态)。
  • bash 的 Parent Process 通常是登录相关进程(如sshd、getty等),而 bash 自身会作为 “用户通过它启动的命令 / 程序” 的 parent 进程(通过fork()系统调用创建子进程)。
🤔bash 的 Parent Process 是用户态吗?登录进程何时启动?

🟢首先明确:所有由用户直接交互的进程(包括 bash 及其 Parent Process)都属于用户态。

bash 的 Parent Process (如 sshd、getty)本质是 “用户态的服务程序”,它们不在内核里,而是运行在用户空间(和 bash、ls 等程序一样,只是功能是处理登录)。

登录相关进程(如 sshd)通常是 “守护进程”(后台服务),随操作系统启动而启动,之后一直驻留在内存中等待触发(比如等待用户的 SSH 连接请求)。它们由系统的初始化进程(如 systemd)创建,属于用户态的 “系统服务”,但并非内核的一部分

2)bash 是内核与用户之间的 “交互中介”,但并非唯一中介

用户无法直接调用系统调用 (需要通过程序代码触发),而 bash 的核心作用就是作为用户与内核之间的 “翻译官” 和 “协调者”:

用户态程序(bash)内核(Kernel)硬件资源(CPU、内存、磁盘等)发起系统调用请求(如open()操作文件、fork()创建进程)直接操作硬件资源(分配CPU时间、读写内存/磁盘等)返回硬件操作结果通过系统调用接口返回处理结果用户态程序(bash)内核(Kernel)硬件资源(CPU、内存、磁盘等)

用户通过终端输入命令(如ls、mkdir),bash 首先解析命令(识别命令名、参数、管道等):

对于简单命令(如ls),bash 会通过fork()创建一个子进程,再通过execve()系统调用加载/bin/ls程序替换子进程;程序运行过程中(如ls需要读取目录),会通过自身代码中的系统调用(如getdents())向内核发起请求,内核处理后将结果返回给程序,最终通过 bash 传递给用户。

对于内置命令(如cd、export),bash 会直接执行(无需创建子进程),必要时仍通过系统调用与内核交互(如cd需要调用chdir()系统调用切换目录)。

🤔系统调用是操作系统内部的代码吗?

🟢是的,系统调用的实现代码属于内核的一部分,封装在操作系统内核中。

从代码角度看,系统调用是内核源码里的一组函数(比如处理文件操作的sys_open、进程创建的sys_fork),这些函数直接操作硬件资源,属于内核空间的代码。

用户态程序(包括 bash、程序员写的代码)无法直接访问内核代码,只能通过 “系统调用接口”(一种约定的触发方式,比如特定的 CPU 指令)间接调用。可以理解为:内核在自己的 “地盘”(内核空间)提供了一组 “办事窗口”(系统调用),用户态程序只能通过窗口递请求,不能直接闯进内核的 “办公室”。

🤔开发人员写的代码直接使用系统调用函数,算 “直接调用” 吗?bash 在其中起什么作用?

🟢算 “直接调用”(相对于通过 bash 间接触发而言),且此时 bash 通常不参与工作。

  • 开发人员写的代码(比如 C 程序)中调用的open()fork()等函数,本质是通过 glibc 等库封装的 “系统调用接口”,最终会触发内核的系统调用(比如sys_open)。这个过程不需要 bash 参与,程序直接与内核交互。

    • 举例:你写了一个 C 程序test.c,里面有pid_t pid = fork();,编译后运行./test。此时:若你通过 bash 输入./test启动程序,bash 的作用仅为 “创建子进程并替换为 test 程序”(启动它);
  • 程序运行时,fork()直接触发内核的系统调用,整个过程 bash 已经 “脱手”,只是等待程序结束后继续接受命令。

核心区别:bash 是 “命令行交互中介”,而程序中的系统调用是 “代码级直接交互”,两者场景不同。

🤔为什么登录程序和 bash 都要 “先创建子进程再替换”?

🟢这是 Unix-like 系统的经典设计,核心目的是保持源进程的持续存在,避免被新程序 “覆盖”。

  • 对于登录程序(如 sshd)
    sshd 的作用是 “持续监听 SSH 连接”,如果它直接 “变身” 为 bash,那么处理完一个用户的连接后,sshd 本身就消失了,无法再处理其他用户的新连接。
    • 所以设计上:
      sshd (Parent) 先通过fork()创建一个 “临时副本”(子进程 - sshd (Child)),自己继续监听新连接;
      ②这个临时副本再通过execve()“变身” 为 bash,专门服务当前用户。
      ③这样既不影响 sshd 的持续工作,又能为用户提供 bash 交互。
  • 对于 bash 处理外部命令(如 ls
    bash 的核心作用是 “持续等待用户输入命令”,如果它直接 “变身” 为 ls,那么 ls 执行完后,bash 就消失了,用户无法再输入下一个命令。
    • 所以设计上:
      bash (Parent) 先通过fork()创建一个 “自己的副本”(子进程 - bash (Child)),自己继续等待用户输入;
      ②这个副本再通过execve()“变身” 为 ls,执行完后自动退出。
      ③这样 bash 始终保持存在,用户可以连续输入命令(lscdmkdir 等)。
Usersshd (Parent)sshd (Child)bashls发起SSH连接请求接受连接fork() - 创建子进程继续监听新连接execve() - 变身为bash提供交互界面输入命令 "ls"解析命令fork() - 创建子进程继续等待用户输入执行命令返回命令结果执行完毕后退出Usersshd (Parent)sshd (Child)bashls

2. 通过代码创建进程:fork

在编程中,我们可以使用 fork 函数来创建新的进程。

fork函数特殊的返回值机制

  • 成功时:它会返回两个值,一个是当前进程(Parent Process)的 pid,另一个是新创建的 Child Processpid
    • 为什么会有两个返回值呢? 这是因为在创建子进程的过程中,系统会执行一系列操作:
      1. 首先找到 Parent Process 的 PCB 对象。
      2. 然后使用 malloc 分配内存创建子进程的 task_struct
      3. 接着根据 Parent Process 的 PCB 初始化子进程的 PCB。
      4. 让子进程的 PCB 指向 Parent Process 的代码数据。
      5. 最后将子进程放入调度队列等待执行。
    • 在这个过程结束后,fork 函数会返回。当 Parent Process 被调度执行时,fork 返回子进程的 pid;当子进程被调度执行时,fork 返回 0。实际上,操作系统是通过寄存器巧妙地实现了返回值返回两次。
    • 而且,fork 之后,Parent Process 和子进程共享代码,但这些代码是只读的,不能被修改。
Parent Process内核Child Process调用 fork() 函数1. 找到Parent Process的PCB2. 分配内存创建Child Process的task_struct3. 根据Parent Process PCB初始化Child ProcessPCB4. Child Process PCB指向Parent Process的代码数据5. 将Child Process放入调度队列调度Parent Process执行,fork返回Child Process PID使用Child Process PID继续执行调度Child Process 执行fork返回0(通过寄存器设置)使用0作为返回值继续执行Parent Process和Child Process共享只读代码Parent Process内核Child Process
  • 失败时fork 函数会返回 -1,通常是因为系统资源不足(如内存不足)等原因导致创建进程失败。
开始
调用fork()函数
内核执行创建子进程操作
1. 查找 Parent Process 的 PCB
2. 分配子进程task_struct
3. 初始化子进程PCB
4. 建立代码共享
5. 放入调度队列
创建成功?
Parent Process获得返回值:子进程的PID
Parent Process继续执行后续逻辑
结束
子进程获得返回值:0
子进程继续执行后续逻辑
返回值: -1
处理创建失败
(通常是资源不足)

进程的独立性与写时拷贝 (Copy-on-Write, COW)

  • 这里还有一个重要的概念 —— 进程的独立性:虽然父进程和子进程共享代码,但为了保证每个进程的独立性和数据安全,各个进程需要拥有自己私有的数据。
  • Linux 采用了写时拷贝(Copy-on-Write, COW) 技术来实现这一点:
    • 当某个进程试图修改共享的数据时,系统才会为其复制一份数据,让该进程在自己的副本上进行修改。
    • 例如,我们通过 fork 创建进程,并用一个变量接受 fork 的返回值,就会发现同一个变量在父进程和子进程中具有不同的数值,甚至通过调试可以看到这个变量的地址是相同的。
    • 但实际上,这个地址并不是物理地址,而是虚拟地址,操作系统会通过地址映射机制将其转换为不同的物理地址,从而保证每个进程的数据独立。

END

http://www.lryc.cn/news/609892.html

相关文章:

  • 文本转语音(TTS)脚本
  • 基于TurboID的邻近标记质谱(PL-MS)实验指南:从质粒构建到质谱鉴定
  • 【嵌入式电机控制#24】BLDC:霍尔测速(高难度,重理解)
  • 聊聊IT行业初创团队质量管理前期准备
  • 十二、请求响应-请求:数组参数和集合参数
  • 编码器-解码器架构:从原理到实践
  • 压缩与归档命令
  • Linux 逻辑卷管理
  • Javascript面试题及详细答案150道之(046-060)
  • Redis之Hash和List类型常用命令
  • Dubbo 3.x源码(32)—Dubbo Provider处理服务调用请求源码
  • 《算法导论》第 1 章 - 算法在计算中的作用
  • Java开发时出现的问题---语言特性与基础机制陷阱
  • 从HTTP到WebSocket:打造极速实时通讯体验
  • 安全扫描:目标主机支持RSA密钥交换问题
  • 国产化低代码平台如何筑牢企业数字化安全底座
  • 消防器材检测数据集介绍-9,600 张图片 智慧安防系统 建筑施工安全监管 AI 消防巡检机器人 自动审核系统 公共场所安全监测
  • Solidity全局变量与安全实践指南
  • [论文阅读] 人工智能 + 教学 | 从代码到职业:用机器学习预测竞赛程序员的就业潜力
  • 安全扫描:目标使用过期的TLS1.0 版协议问题
  • 【乐企板式文件】不动产销售类发票已支持
  • MySQL三大日志详解(binlog、undo log、redo log)
  • 赋能未来:数字孪生驱动能源系统智能化升级
  • 【项目实践】在系统接入天气api,根据当前天气提醒,做好plan
  • Linux(centos)安全狗
  • 【芯片设计专用执行单元:PWM如何重塑能源与智能控制】
  • sqli-labs靶场less29~less35
  • 2025.08.04 移除元素
  • 【测试工程思考】测试自动化基础能力建设
  • 使用mybatis生成器生成实体类mapper和查询参数文件,实现简单增删改查。使用log4j输出日志到控制台。使用配置文件注册Bean,配置视图解析器