初识Linux 进程:进程创建、终止与进程地址空间
目录
0.写在前面
1.进程创建
fork():
exec():
2.进程地址空间
3.进程终止
正常终止(主动退出)
异常终止(被动终止)
0.写在前面
本文将对Linux环境下的进程:包括进程创建、终止与进程等待、替换进行讲解,作者使用XShell连接配置为CentOs 7.6的主机进行演示,希望能帮助你更好理解操作系统的运行原理!
1.进程创建
什么是进程创建?怎么来创建进程?和别的进程有什么关系?别着急,这些问题需要慢慢回答。首先是进程创建的概念:
进程创建的本质是为程序的运行构建独立的执行环境,包括:分配内存空间;创建进程控制块(PCB)......
重点在于进程如何创建!:Linux 中进程创建过两个关键系统调用完成:
fork():
先来看看man-pages关于fork的介绍:
fork()
的作用是创建父进程的副本(子进程)。内核会为子进程分配新的PCB (task_struct),并复制父进程的大部分资源(如内存页表、文件描述符、信号处理等),并且采用写时拷贝优化:
写时复制:子进程与父进程初始时共享同一块物理内存(仅复制页表,不复制代码和数据)。只有当父进程或子进程尝试修改内存时,才会为修改的部分分配新的物理内存并复制数据。这大幅减少了内存占用和创建时间。
再来看看返回值:
如果成功创建子进程会在父进程返回PID,子进程本身返回0,如果创建失败,父进程返回-1,子进程没有,errno出现( 父子进程/多个子进程的运行顺序由调度器决定,不同的平台下不同)
了解了返回值,我们可以根据pid_t类型的fork返回值区分出哪一个是父进程哪一个是子进程,但是既然说创建子进程会直接沿用父进程的代码和数据,并进行写时拷贝,这里能衍生出四个问题:
1. 为什么fork要给子进程返回0,给父进程返回子进程pid?
- 对父进程而言,一个进程可能有多个子进程,没有函数能直接获取所有子进程的PID,fork返回子进程PID便于父进程识别和管理子进程。
- 对子进程而言,它可通过getpid()获取自身PID,fork返回0使其能轻松与父进程区分(进程ID 0由系统特殊使用,子进程PID不可能为0)。2. fork干了什么?
fork创建一个新进程(子进程),子进程是父进程的副本:
- 共享代码段,也就是说代码是共享的,但子进程拥有自己的PCB,且操作系统会拷贝父数据中子进程要修改的部分,(代码一般是共享的,页表和虚拟地址空间同样写时拷贝)父子进程互不干扰。(这属于数据层面的写时拷贝)- 为什么?进程之间是独立的,数据可能被修改,父子进程不能共用一份数据,所以数据必须拷贝一份
- 两进程从fork返回处继续执行,子进程继承父进程打开的文件描述符等资源。3. fork是如何返回两次的?
fork执行时,系统复制父进程的堆栈段,父进程和子进程都停留在fork函数中等待返回。 - 父进程中,fork返回子进程的PID
- 子进程中,fork返回0
补充:父子进程共用代码段,return语句在父子进程中都会执行4. 一个变量为什么会有不同的内容?
fork后,子进程获得父进程数据空间的独立副本,两者数据空间互不共享。 本质上发生了写时拷贝,操作系统重新开辟空间给子进程进行修改。看完前面内容,你可能觉得这个问题有点多余,但如果你去揪出两个进程中返回值的地址,你会发现是相同的。这就关乎进程地址空间了。
exec():
由于这一类系统调用的特殊,作者放到了进程替换中详细介绍~
2.进程地址空间
通常在编程时,提到的栈区堆区常量区之类的,并不是物理地址!如果是物理地址,那么地址相同的变量不可能对应不同值!那么这里可以得出的是栈区堆区保存在虚拟地址空间中,先让我们了解一下虚拟地址空间的结构,这里可以通过一个简单的程序验证一下:
int g_val_1;
int g_val_2=100;void test1()
{printf("code addr: %p\n",test1);//验证字符串常量区const char* str="hello bit";printf("read only string addr: %p\n",str);//验证已初始化的全局变量printf("init global value addr: %p\n",&g_val_2);//验证未初始化的全局变量printf("uninit global value addr: %p\n",&g_val_1);//验证堆区的地址char* mem=(char*)malloc(100);printf("heap addr: %p\n",mem);printf("stack addr: %p\n",&str);printf("stack addr: %p\n",&mem);//验证栈区的地址int a;int b;int c;printf("stack addr: %p\n",&a);printf("stack addr: %p\n",&b);printf("stack addr: %p\n",&c);
}
通过简单的编译命令,我们执行可执行文件查看一下执行结果:
啊哈,这就验证了栈区向下增长,堆区向上增长的结论!直接给出虚拟地址空间的架构:
虚拟地址空间通过页表来对应真实的物理地址:
下面我们来一睹mm_struct的真容:mmstruct部分代码:
struct mm_struct
{ unsigned long total_vm, locked_vm, shared_vm, exec_vm;unsigned long stack_vm, reserved_vm, def_flags, nr_ptes;unsigned long start_code, end_code, start_data, end_data;unsigned long start_brk, brk, start_stack; ......
}
存在虚拟地址空间的意义:
1.让进程以统一的视角看待内存,不用直接管理物理内存上的存储空间与地址;
2.增加进程虚拟地址空间可以让我们访问内存的时候,增加一个转换的过程,可以对寻址请求审查,拦截异常访问,保护物理内存;
3.因为有地址空间和页表的存在,将进程管理模块,和内存管理模块进行解耦合;
再来补充一下页表:
保存在哪里?页表的物理地址(其实是页表的真实地址)临时存储在页目录基址寄存器(如 x86 的 CR3)上面,当进程切换时会被当作上下文保存,页表记录虚拟地址对应的物理地址,有权限标志位参与权限管理,在每一个虚拟地址对应物理地址的同时加上读写权限,那么尝试写入常量区时会被页表发现,还有标志位来判定代码和数据是否以已经被加载到内存中,由于操作系统对大文件采用惰性加载的方式:推迟非必要资源的加载或初始化,直到实际需要时再执行,数据并不会全部加载到内存,此时有了虚拟地址但物理地址是空着的,标识为0,触发缺页中断,从磁盘中将数据加载到内存有了物理地址再补全映射关系。
3.进程终止
这里我们就把写出来的一个程序当作进程,进程终止的触发场景可分为正常终止和异常终止两类:
正常终止(主动退出)
进程因完成任务或主动请求结束,常见方式包括:
- main() 函数返回:程序执行到main()函数末尾,返回一个整数值(如return 0),等价于调用
exit(返回值);
- 调用exit()函数:标准库函数exit(返回码)会执行清理操作(如刷新 IO 缓冲区);
- 调用_exit()系统调用:直接终止进程(不执行清理,不刷新缓冲区),将退出状态传递给内核(exit()最终会调用_exit());
但是正常终止分为两种情况:1.代码执行完毕,结果正确;2.代码执行完毕,结果错误;
父进程会根据子进程main函数的退出码(return的返回值)来判断代码的运行情况:
bash就是父进程,我们的程序运行时就相当于子进程,那么程序中main函数的返回码对bash来说至关重要!
1.返回码为0,运行成功;
2.返回码不为0,不同的返回码对应不同的情况;
| | 让我们来看看C语言中不同的返回码都可以携带哪些信息:
int test2()
{int i=0;for(i=0;i<60;i++){printf("%s\n",strerror(i));//退出码和退出码的描述具有对应关系,再通过strerror来将错误打印出来。//在C语言中,有errno这样的全局变量来保存最近一次的错误码,//可以用perror/strerror来打印错误信息}return 2;//这里故意返回的2,来看看返回码的运用}
补充:如何来查看退出码呢?在命令行界面,用echo $?就可以查看上一个程序的退出码;在程序中可以使用wait/waitpid来获取子进程的退出码(由exit返回),作者放到进程等待讲解!
哈哈,return 2的作用在这里!
异常终止(被动终止)
进程因外部干预或内部错误被迫终止,常见场景包括:
- 收到终止信号:如用户通过
kill
-9 命令发送SIGKILL,
这里的kill命令本质上就是一种信号!
相关文章:
初识Linux 进程:进程创建、终止与进程地址空间
目录 0.写在前面 1.进程创建 fork(): exec(): 2.进程地址空间 3.进程终止 正常终止(主动退出) 异常终止(被动终止) 0.写在前面 本文将对Linux环境下的进程:包括进程创建、终止与进程等待…...
2025年PMP 学习二十二 15章 项目绩效域
2025年PMP 学习二十二 15章 项目绩效域 文章目录 2025年PMP 学习二十二 15章 项目绩效域项目绩效域1.项目绩效域2.项目持续效域3.项目管理中的干系人管理 1.干系人持续效域促进干系人参与的步骤: 2 团队持续效域1 团队持续效域及项目团队人员有关系的活动和职能&…...
顶级流媒体服务商 Spotify 2025.04 故障复盘报告,吃他人的堑长自己的智
2025 年 4 月 16 日,Spotify 经历了一次影响全球用户的中断。以下就是发生了什么以及我们将如何解决它。 背景 我们使用 Envoy Proxy 作为我们的网络外围系统。外围是我们的软件接收用户(您!)网络流量的第一部分。然后ÿ…...
服装收银系统哪个好?服装店进销存管理软件全面评测
在服装批发零售行业,选择一款合适的收银系统和进销存管理软件至关重要。好的系统不仅能提高工作效率,还能帮助商家精准掌握库存、优化销售策略。 本文将全面分析服装收银系统的选择标准,并重点介绍秦丝进销存这一专业解决方案。 一、服装收…...
Java程序员从0学AI(二)
一、前言 在上一篇文章中,我们初步认识了 AI 领域的核心基础概念,如大语言模型(LLM)的参数量特征、提示词(Prompt)对交互效果的关键作用、文本处理单元 Token 的独特定义,以及通过向量转换实现…...
进阶知识:无参的函数装饰器之深入理解@wraps()
进阶知识:无参的函数装饰器之深入理解wraps(func) 一、wraps(func)的本质解析 1.1 核心作用 wraps(func)是functools模块提供的装饰器工具,用于保留被装饰函数的元信息。它通过将被装饰函数的名称(__name__)、文档字符串&#…...
《C 语言 sizeof 与 strlen 深度对比:原理、差异与实战陷阱》
目录 一. sizeof 和 strlen 的对比 1.1 sizeof 1.2 strlen 1.3 对比表格 二. 数组和指针笔试题解析 2.1 一维数组 2.2 字符数组 2.2.1 代码练习一 2.2.2 代码练习二 2.2.3 代码练习三 2.2.4 代码练习四 2.2.5 代码练习五 2.2.6 代码练习六 2.3 二维数组 …...
C++ 初阶 | 类和对象易错知识点(上)
目录 0.引言 1.访问限定符 2.域 3.类的实例化和声明 4.this指针 5.构造函数(自动执行) 6.拷贝构造 7.运算符重载 8.日期类的实现 9.总结 0.引言 今天,小邓儿和大家分享一下,C在类和对象中的易错知识点🤭&am…...
USB转TTL
USB转TTL模块是实现计算机USB接口与TTL电平串口设备(如单片机、嵌入式系统)通信的核心组件,其原理涉及协议转换和电平适配两大关键技术 一、核心功能与应用场景 功能:将计算机的USB信号(高速差分信号、USB协议&#…...
汽车生产中的测试台连接 – EtherCAT 转CANopen高效的网关通信
使用 EtherCAT 和 CANopen协议,实现对汽车零部件的高效生产线末端测试 某电动机、电桥和变速箱制造商之一,正在其生产线上使用ETHERCAT转canopen网关WL-ECAT-COP的解决方案。集成到测试线中的下线测试必须映射众多待测设备的测试应用。该制造商已指定 Et…...
汽车充电过程中--各个电压的关系(DeepSeek)
在电动汽车的充电过程中,电池的充电机制涉及多个电压参数的协调控制,以下从原理到实际应用逐步分析: 1. 充电基础原理 电动汽车电池(通常为锂离子电池组)的充电本质是通过外部电源向电池注入电能,使锂离子…...
基于HTML的Word风格编辑器实现:从零打造功能完备的富文本编辑器
引言 在Web开发中,实现一个功能完备的富文本编辑器是一个常见需求。本文将基于HTML5和JavaScript,结合第三方库,打造一个具有Word风格界面的富文本编辑器,支持格式设置、图片插入、表格创建、文件导入导出等核心功能。 完整代码…...
亚远景-汽车软件开发的“升级之路”:ASPICE各等级说明
ASPICE(Automotive SPICE)将汽车软件开发过程的成熟度划分为六个等级,从0级到5级,每个等级代表了组织在软件开发过程中的不同能力水平。以下是各等级的详细说明: 等级0:不完整(Incomplete&#…...
Unity Display 1 No cameras rendering
一个相机不能同时输出到屏幕和RenderTexture。 Output Texture,要么是 None (屏幕),要么是RenderTexture。 如果此时相机已经输出到RenderTexture,场景中又没有别的相机在渲染,屏幕将变黑并显示No cam…...
Python Selenium 使用指南
Selenium 是一个用于自动化 Web 浏览器交互的强大工具,常用于网页测试、数据抓取和自动化任务。以下是 Python 中 Selenium 的详细使用说明。 安装 Selenium 首先需要安装 Selenium 库和浏览器驱动: pip install selenium 然后下载对应浏览器的驱动&…...
Cribl 对数据源进行过滤-01
先说一个项目中实际的例子: Cribl 利用filter expression 来过滤 data, 举个例子: source1: sourcerouter=A, source 2: sourcerouter=B, 这个时候,可以要把他们合并起来: sourcerouter=A || sourcerouter=B 来进行过滤想要的数据。 最后可以使用一个pipeline 来对数据进行…...
python 通过 pymysql 获取 select count(*) xxx 的数量
在使用 pymysql 库来获取 SELECT COUNT(*) 语句的结果时,你可以通过以下步骤实现: 安装 pymysql:如果你还没有安装 pymysql,可以通过 pip 安装它。 pip install pymysql连接到数据库:使用 pymysql.connect() 方法连接…...
定时任务延迟任务
二者的区别: 定时任务:有固定周期的,有明确的触发时间。 延迟任务:没有固定的开始时间,它常常是由一个事件触发的,而在这个事件触发之后的一段时间内触发另一个事件,任务可以立即执行࿰…...
【动手学深度学习】1.1~1.2 机器学习及其关键组件
目录 一、引言1.1. 日常生活中的机器学习1.2. 机器学习中的关键组件1)数据2)模型3)目标函数4)优化算法 一、引言 1.1. 日常生活中的机器学习 应用场景: 以智能语音助手(如Siri、Alexa)的唤醒…...
LLaVA-MoD:基于MoE结构和蒸馏训练方法,训练轻量化多模态大模型!!
摘要:我们介绍了LLaVA-MoD,这是一个旨在高效训练小型多模态语言模型(s-MLLM)的创新框架,通过从大规模多模态语言模型(l-MLLM)中提取知识来实现。我们的方法解决了多模态语言模型(MLL…...
YOLOv8 的双 Backbone 架构:解锁目标检测新性能
一、开篇:为何踏上双 Backbone 探索之路 在目标检测的领域中,YOLOv8 凭借其高效与精准脱颖而出,成为众多开发者和研究者的得力工具。然而,传统的单 Backbone 架构,尽管已经在诸多场景中表现出色,但仍存在一…...
SSRF(服务器端请求伪造)基本原理靶场实现
1、漏洞原理 攻击者通过构造恶意请求,诱使服务器向内部系统或第三方服务发起非预期的网络请求。其核心在于 服务器信任了不可信的用户输入,并基于该输入发起网络操作。 2、攻击场景与利用方式 1. 基础利用 攻击类型示例Payload目标读取本地文件file://…...
自动化测试脚本点击运行后,打开Chrome很久??
亲爱的小伙伴们大家好。 小编最近刚换了电脑,这几天做自动化测试发现打开Chrome浏览器需要等待好长时间,起初还以为代码有问题,或者Chromedriver与Chrome不匹配造成的,但排查后发现并不是!! 在driver.py中…...
Oracle中如何解决FREE BUFFER WAITS
基于性能上的考虑,服务器进程在扫描LRU主列的同时,会将脏块移至LRU-W列,如果发现没有足够可用(可替换)的BUFFER CACHE,进程并不会无止尽地扫描整条LRU主列,而是在扫描到某个阀值(该阀…...
OpenHarmony开源鸿蒙兼容性测试常见问题解答分享
OpenHarmony 兼容性测评主要是验证合作伙伴的设备和业务应用满足 OpenHarmony 开源兼容性定义的技术要求,确保运行在 OpenHarmony 上的设备和业务应用能稳定、正常运行,同时使用 OpenHarmony 的设备和业务应用有一致性的接口和业务体验。 一、兼容性测评…...
Android trace presentFence屏幕显示的帧
Android trace presentFence屏幕显示的帧 presentFence :当帧成功显示到屏幕时,present fence就会signal。 FrameMissed/GpuFrameMissed/HwcFrameMissed表示上一次合成的结果,当SurfaceFlinger合成后显示到屏幕上,present fence就…...
【520特辑】情人节脑影像绘图
祝大家520快乐! 永远爱自己! 1.Brain Net基于节点画爱心 clear all; clc;t linspace(0, 2*pi, 30); x 16*sin(t).^3; y 13*cos(t)-5*cos(2*t)-2*cos(3*t)-cos(4*t); z zeros(size(t));[X,Y] meshgrid(linspace(-10,10,5), linspace(-10,10,5)); X …...
Linux服务器配置深度学习环境(Pytorch+Anaconda极简版)
前言: 最近做横向需要使用实验室服务器跑模型,之前用师兄的账号登录服务器跑yolo,3张3090一轮14秒,我本地一张4080laptop要40秒,效率还是快很多,(这么算一张4080桌面版居然算力能比肩3090&#…...
如何理解大模型的幻觉输出及RAG技术的应用与实战案例
导读:大语言模型(LLM)在当今技术领域中扮演着越来越重要的角色,但其“幻觉输出”问题却成为实际应用中的痛点。本文将带你深入剖析这一现象的定义、表现形式及成因,并探讨如何通过RAG(检索增强生成…...
std::vector<>.emplace_back
emplace_back() 详解:C 就地构造的效率革命 emplace_back() 是 C11 引入的容器成员函数,用于在容器尾部就地构造(而非拷贝或移动)元素。这一特性显著提升了复杂对象的插入效率,尤其适用于构造代价较高的类型。 一、核…...
卷积神经网络(CNN)学习率调整完全指南:从理论到PyTorch实践
引言 学习率是训练卷积神经网络(CNN)最重要的超参数之一,合理调整学习率可以显著提高模型性能、加速收敛并避免训练失败。本文将全面解析CNN学习率调整的技术与方法,涵盖基础概念、常用策略、PyTorch实现以及实用技巧。 一、学习率为什么如此重要&…...
KLEC--基于知识学习的演化计算算法
KLEC–基于知识学习的演化计算算法 title: Knowledge Learning for Evolutionary Computation author: Yi Jiang, Zhi-Hui Zhan, Kay Chen Tan, Jun Zhang. journal: IEEE TRANSACTIONS ON EVOLUTIONARY COMPUTATION (TEVC) DOIÿ…...
Git查看指定作者提交命令
要查看 Git 仓库中某个作者的提交记录,可以使用 git log 命令结合 --author 选项。以下是具体用法和示例: 基础命令 git log --author"作者名"作用:列出指定作者的所有提交记录。示例:查找作者名为 John Doe 的提交&am…...
隐形安全感
凌晨两点,手机突然震动。合作三年的化工原料供应商发来紧急消息:“一批次环氧树脂需要连夜从南京调往广州,但合作多年的物流公司临时爽约,能帮忙想想办法吗?” 我盯着屏幕愣了几秒。这类危险品运输从来不是简单的“拉…...
代码随想录算法训练营 Day52 图论Ⅲ 岛屿问题Ⅱ 面积 孤岛 水流 造岛
图论 题目 101. 孤岛的总面积 计算孤岛总面积,一个想法是将相邻的陆地的位置置为 0,最后计算孤岛面积中最小的一个 #include <iostream> #include <vector> #include <queue>using namespace std;int sum 0; int dir[4][2] {0,-1…...
实用 Git 学习工具推荐:Learn Git Branching
https://learngitbranching.js.org/?localezh_CN 网站概述 Learn Git Branching 是一个面向开发者的交互式 Git 学习平台,专为那些希望通过实践掌握 Git 高级用法的用户设计。网站采用游戏化的界面和渐进式挑战,让复杂的 Git 概念变得直观易懂。无论是…...
物流项目第三期(统一网关、工厂模式运用)
前两期: 物流项目第一期(登录业务)-CSDN博客 物流项目第二期(用户端登录与双token三验证)-CSDN博客 为什么要有网关? 通过前面的课程我们已经完成了四个端的登录,但是我们并没有对登录后的请…...
安卓settings单双屏显示
Settings/src/com/android/settings/homepage/SettingsHomepageActivity.java的onCreate方法中,创建布局之前会通过ActivityEmbeddingUtils.isEmbeddingActivityEnabled(this);去获取是否使用嵌入式显示。 mIsEmbeddingActivityEnabled ActivityEmbeddingUtils.is…...
SpringCloud+Vue实现大文件分片下载(支持开始、暂停、继续、取消)
1. 实现效果 http://localhost:8089/#/demo 所有代码已提交至 https://github.com/SJshenjian/cloud.git与 https://github.com/SJshenjian/cloud-web.git中,欢迎star 2. 后端核心代码 FeignClient(value "download", contextId "download"…...
RK3576 Android 14.0 SDK开发指南(第一集)
RK3576 Android 14.0 SDK代码编译 SDK下载到本地后大概70多个G 下载后要做个校验 解压后内核源码 kernel代码路径说明 Android14支持6.1 版本的kernel,kernel源码在工程中kernel-6.1目录下 Lunch项说明 一键编译命令 ./build.sh -UKAupSoc RK3576 SDK默认没有开…...
【C/C++】现代C++线程池:从入门到生产级实现
文章目录 现代C线程池:从入门到生产级实现🧠 What Is a Thread Pool?🧩 Why Use a Thread Pool?🔰 Part 1: Basic Thread Pool (Beginner)🔧 Minimal Working Code:✅ Usage: 🧑🔬 Part 2: …...
后期:daplink
问题描述: 问题一:总工程,USB插入能识别到dap,但有个黄色的感叹号!现在连感叹号都没有了。 重点跟踪了枚举的几个函数,差异点就是有个工厂描述符没有枚举到。 问题二: 下载后,目标板,没有自动复位。 问题三:未移植daplink的时候,虚拟串口是收发正常,貌似没有映射到…...
Android SharedPreferences:从零到一的全面解析与实战指南
简介 SharedPreferences是Android平台提供的一种轻量级键值对存储方案,虽然看似简单,但在实际开发中却蕴含着丰富的技术细节和最佳实践。本文将从基本概念出发,深入分析其源码实现原理,探讨企业级开发中的应用技巧,并提供完整的代码示例,帮助开发者全面掌握这一重要数据…...
推扫式高光谱相机VIX-N230重磅发布——开启精准成像新时代
随着各行业对高光谱成像技术需求的持续增长,市场对于高分辨率、高灵敏度以及快速成像的高光谱相机的需求愈发迫切。中达瑞和凭借多年的行业经验和技术积累,敏锐捕捉到这一市场趋势,正式推出全新一代推扫式可见光近红外高光谱相机——VIX-N230…...
实现rpc通信机制(待定)
一、概述 (1)rpc(remote procedure call, 远程接口调用),就像在本地调用函数一样,是应用组成服务内部分布式的基础功能。应用场景是在内网中的计算,比如:(a) 为上传的一张图片加水印、…...
STM32--串口函数
USART_GetFlagStatus() 用于获取某个串口的寄存器中的某个标志位的状态,和中断无关。 USART_ClearFlag() 用于清楚串口寄存器中的标志位的状态,和中断无关。 USART_ITConfig() 使能或禁用指定的 USART 中断。 USART_ITConfig(USART1, USART_IT_TXE, …...
Linux跨网络通信中IP与MAC的作用
是的,MAC地址和IP地址分别属于OSI模型的不同层次,并在数据封装过程中被添加到不同的位置: 1. MAC地址(数据链路层) 作用层级:数据链路层(第二层)。封装位置:添加到数据链…...
Facebook隐私保护的成与败:一场对用户信任的考验
引言 在这个信息爆炸的时代,Facebook作为全球最大的社交网络平台之一,其隐私保护政策和实践一直是公众关注的焦点。随着数据泄露事件的频发,Facebook在隐私保护方面的成与败,不仅关系到其自身的声誉,更是对用户信任的…...
面试算法刷题3(核心+acm)
102. 二叉树的层序遍历 递归法 核心代码模式 不断递归根节点,根据深度来判断加在哪一层上。 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(in…...
[Java] idea的调试介绍
1. 什么是调试? 调试就是帮助我们去寻找代码中的bug,优化代码的过程。调试对于程序员来说非常重要,能帮助我们更容易去找到代码中的错误,去修复。 2. idea集成开发环境的调试 下面我就介绍下idea集成开发环境下的调试ÿ…...