Linux之进程概念
作者主页: 作者主页
本篇博客专栏:Linux专栏
创作时间 :2024年9月28日
基本概念:
进程说白了其实就是一个程序的执行实例,正在执行的程序。
在内核层面来说,就是一个担当分配资源(CPU时间,内存)的实体
写过代码的都知道,当你的代码进行编译链接之后就会形成一个可执行的程序了,这个程序本质上是一个文件,是放在磁盘上的。当我们双击这个程序让他运行起来之后,本质上是让这个程序加载到内存当中去了,因为只有加载到内存当中去CPU才能对他进行逐语句执行,而一旦将这个程序加载到内存之后,我们就不应该叫他程序了,严格意义上应该称他为进程。
描述进程-PCB
系统中可以同时存在大量的进程,当我们使用ps aux命令时便可以看见此时存在的所有进程
当我们电脑开机时,打开的第一个程序其实就是操作系统(即操作系统是第一个加载到系统中的),我们都知道操作系统是管理工作的,其中一个就是进程管理,那么我们电脑上这么多的进程,操作系统是如何进行管理的呢?
这时我想首先告诉大家一个六字真言:就是先描述,再组织,操作系统管理也是如此,操作系统作为管理者是不需要直接和被管理者进行沟通的,当一个进程出现时,操作系统会直接对其进行描述,然后对他的管理其实就是对其描述信息的管理,进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合,这个就是PCB。
操作系统将每一个进程进行描述,形成一个个的进程控制块(PCB),并且通过双链表的形式将他们连接起来。
这样,操作系统只要拿到这个双链表的头指针就可以对这个双链表进行管理,这样操作系统对各个进程的管理就变成了对双链表的管理。
例如我们创建一个进程时首先就是将改进程的代码和数据加载到内存,然后操作系统对此进程进行描述形成对应的进程控制块(PCB),并将这个PCB插入到双链表中,想要退出这个进程时就直接从双链表当中删去这个节点(PCB)即可。这样一来,操作系统对于进程的管理就变成了对一个双链表的增删查改。
task_struct --PCB的一种
进程控制块(PCB)是描述进程的,再c++中我们称之为面向对象,而在c语言当中我们称之为结构体,因为Linux是用C语言写的,当然PCB也是用c语言写的了,也就是用结构体来实现的。
- PCB实际上是对进程控制块的统称,在Linux中描述进程的结构体叫做task_struct
- task_struct是Linux中的一种数据结构,他会被装载到RAM(内存)里并包含进程的信息
task_struct 内容分类
task_struct 就是Linux中的进程控制块,它包含着以下的一些信息。
- 标识符:描述本进程的唯一标识符,用来区别其他标识符
- 状态:任务状态,退出代码,推出信号等
- 优先级:相对于其他进程的优先级
- 程序计数器:程序中即将被执行的下一条指令的地址
- 内存地址:包含程序代码和进程相关的指针,还有和其他进程共享的内存块中的指针
- 上下文数据:进程执行时处理器的寄存器中的数据
- I/O状态信息:包含显示的I/O请求等
- 记账信息:可能包含处理器时间的总和等
- 其他信息
查看进程
通过系统目录来查看信息:
在根目录下有一个名为proc的系统文件夹,其中包含了大量进程信息,其中一些子目录的名字为数字
这些数字其实是一某一进程的PID,对应的文件夹中记录中对应进程的各种信息,想要查看直接输入ls /proc/对应的数字 即可
通过ps命令查看:
ps与对应的指令想叠加,便可以显示对应的进程的信息
ps aux | head -1 && ps aux | grep proc | grep -v grep
通过系统调用获得对应的进程的PID和PPID
通过系统调用函数,getpid和getppid两个函数分别可以获得对应进程的PID和PPID
当我们执行该程序之后,这个程序会不停的执行下去
我们通过ps命令得到对应进程的PID和PPID,就可以发现和getpid与getppid得到的值是一模一样的
通过系统调用创建进程-fork初始
fork函数创建子程序
加入fork函数之后,运行结果如下:
循环打印两行数据,这两行数据分别为:第一行是该进程的PID和PPID,第二行是fork创建的子进程的PID和PPID,我们可以发现fork创建的子进程的PPID是子进程的PID,说明这两个进程的关系为父子关系。
同样,操作系统也会为这个新建的进程创建PCB。
我们知道加载到内存中的数据和代码是属于父进程的,那么子进程的数据和代码又是从哪里来的呢?
我们可以看到,fork之前的代码是父进程自己执行的,之后的代码是父子进程都执行
需要注意的是,虽然父子进程共享代码了,但是其实是各自开辟空间(采用写时拷贝);
小贴士:使用fork函数创建子进程后就有了两个进程,这两个进程的调度顺序是不确定的,取决于操作系统调度算法具体的实现。
fork返回值:
1.如果fork函数创建子进程成功,那么在父进程中返回父进程的pid,子进程的返回0
2.如果创建失败,那么父进程的返回-1.
Linux运行状态:
一个进程都创建而产生到因撤销而销毁的整个生命期间,有时占有处理器执行,有时虽然可以运行但是分不到处理器。有时虽然有空闲处理器但是由于待某个时间的发生而无法执行,这一切就说明进程和程序有区别,进程是活动的且状态变化的,所以叫做进程
这里我们具体谈一下进程中的一些状态:
Linux源代码中对于一些状态的定义:
/*
* The task state array is a strange "bitmap" of
* reasons to sleep. Thus "running" is zero, and
* you can test for combinations of others with
* simple bit tests.
*/
static const char *task_state_array[] = {"R (running)", /* 0*/"S (sleeping)", /* 1*/"D (disk sleep)", /* 2*/"T (stopped)", /* 4*/"T (tracing stop)", /* 8*/"Z (zombie)", /* 16*/"X (dead)" /* 32*/
};
运行状态——R
一个程序处于运行状态,并不一定一定处于运行当中,一个进程处于R状态,表示处于运行当中或者处于运行队列(runqueue)当中,所有会存在多个进程同时处于R状态。
浅睡眠状态——S
一个进程处于浅睡眠状态,也叫可中断睡眠状态,意味着等待某件事情的完成,处于浅睡眠状态的进程随时可以被唤醒,也可以随时被杀掉
当我们在一个进程中加入sleep(100),意思就是在这里休息一百秒,此时编译运行之后就会出现浅睡眠状态。
深睡眠状态——D
一个进程处于深度睡眠状态,表示这个进程不可以被杀掉,即便是操作系统也是不可以的,只有这个进程自动唤醒才可以恢复,该进程也被称为不可中睡眠状态。
例如:某一进程对磁盘进行写入操作时,再写入期间,就会处于D状态,是无法被杀掉的,因为该进程必须磁盘回复是否写入成功,以做出相应的回应
暂停状态——T
在Linux中,我们可以通过向进程发送SIGSTOP信号使进程进入暂停状态(T),发送SIGCONT可以让处于暂停状态的进程继续运行。
僵尸状态——Z
当一个进程将要退出的时候,在系统层面,这个系统曾经申请的资源并不会被马上释放,而是暂时存储一段时间,以供操作系统或者其父进程进行读取,如果信息一直未被读取,则相关数据会一直存在,不会被释放掉的,如果一个进程等待着数据被读取,那么我们就说他正处在僵尸状态。
僵尸状态时应该存在的,因为我们调用一个程序时,调用方是应该知道这个完成情况的,所以僵尸状态必须是要存在的,以便后续的相关操作。
例如我们在编写程序时都会在最后写一个return 0,它的作用就是告诉操作系统这个程序顺利完成结束了。
在Linux中,我们可以通过echo $命令来获取最近的一次进程的退出码
死亡状态——X
死亡状态只是一个返回状态,当一个进程的信息被退出之后,该进程申请的资源会立即被释放,所以你不会在进程状态中看到死亡状态。
僵尸进程
前面我们已经说过僵尸状态的概念,相信大家也有了一个大致的了解,而处于僵尸状态的进程,就被称为僵尸进程。
例如,对于下面的代码,当程序执行五次之后,子进程便会退出,但是父进程不知道它退出了,那么此时子进程就处于僵尸状态。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{printf("I am running...\n");pid_t id = fork();if(id == 0){ //childint count = 5;while(count){printf("I am child...PID:%d, PPID:%d, count:%d\n", getpid(), getppid(), count);sleep(1);count--;}printf("child quit...\n");exit(1);}else if(id > 0){ //fatherwhile(1){printf("I am father...PID:%d, PPID:%d\n", getpid(), getppid());sleep(1);}}else{ //fork error}return 0;
}
运行该代码之后,我们可以通过下面这个简单的脚本进行监控
while :; do ps axj | head -1 && ps axj | grep proc | grep -v grep;echo "######################";sleep 1;done
运行之后我们发现:当子进程退出之后,子进程就会编程僵尸状态。
僵尸进程的危害:
- 僵尸进程的退出状态会一直维持下去,因为它需要告诉父进程执行的相应的结果信息。但是父进程一直在不停的执行,所以子进程就一直处于僵尸状态
- 僵尸进程的信息会一直存在与task_struct(PCB)中,所以PCB就需要一直去维护
- 若一个父进程创建了多个子进程,并且不对其进行回收,那么就会造成资源浪费,因为数据结构对象本身就要占据内存
- 僵尸进程越来越多,申请的资源无法进行回收,那么僵尸进程越多,实际可用的资源就越少,也就是说僵尸进程会造成内存泄漏
孤儿进程:
孤儿进程是指在操作系统中,其父进程已经结束(正常或异常终止),但该进程本身还在继续运行的进程。当一个进程创建子进程后,如果父进程在子进程结束之前就已经退出,那么子进程就会成为孤儿进程。例如,一个父进程启动了一个子进程,之后父进程由于某种原因(如完成了它的任务或者遇到了错误而终止)退出,此时子进程就变成了孤儿进程。
对于以下代码,父进程执行五次后退出,子进程就变成了孤儿进程:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{printf("I am running...\n");pid_t id = fork();if(id == 0){ //childint count = 5;while(1){printf("I am child...PID:%d, PPID:%d\n", getpid(), getppid(), count);sleep(1);}}else if(id > 0){ //fatherint count = 5;while(count){printf("I am father...PID:%d, PPID:%d, count:%d\n", getpid(), getppid(), count);sleep(1);count--;}printf("father quit...\n");exit(0);}else{ //fork error}return 0;
}
观察代码运行,会发现父进程退出后,子进程的PPID变成了1,这就说明他被一号进程领养了
进程优先级:
基本概念:
什么是进程优先级?优先级实际上就是进程获取某些资源的先后顺序,而进程优先级实际上就是进程获取CPU资源分配的先后顺序,就是指进程的优先权,优先权高的进程具有优先执行的权力
为什么要有进程优先级?
进程优先级存在的主要原因就是我们的资源是有限的,就像我们的电脑,一般都是单CPU的,一个CPU一次只能执行一个进程,而进程有多个,所以需要存在进程优先级,确定获取CPU资源的先后顺序。
查看系统进程
在Linux中输入ps -l可以看到以下的东西:
我列出其中重要的几个信息:
- UID:代表着执行者的身份
- PID:代表这个进程的代号
- PPID:代表着这个进程由哪一个进程发展而来,即父进程的代号
- PRI:代表这个进程的可被执行的优先级,值越小越早被执行
- NI:代表着这个进程的nice值
PRI和NI
- PRI代表着进程的优先级,这个值越小进程的优先级越高
- NI代表着nice值,其表示进程可被执行的优先级的修正数值
- PRI(new)=PRI(old)+NI;
- 若NI值为负值,那么PRI变小,优先级变高
- 调整进程的优先级,在Linux下就是调整NI,即nice值
- NI的范围是-20-19,也就是说进程优先级一共分为四十个级别
注意:在Linux系统中,PRI默认的值是80,也就是PRI=80+NI。
当我们创建一个进程之后,我们可以通过ps -al查看进程的优先级。
通过top命令修改进程优先级
这里的top命令其实就相当于Windows中的任务管理器,可以调整进程优先级。
使用top命令后按r,然后输入要调整的进程的PID,然后调整后的nice值即可
注意:要想将nice调整为负值,需要加上sudo提升权限
通过renice调整进程优先级
输入 renice +更改后的nice +PID即可
四个重要概念:
竞争性:由于只有一个CPU,所以资源有限,会出现资源竞争,为了高效完成任务,合理分配CPU资源,所以会出现进程优先级
独立性:多进程之间运行需要独享各种资源,运行期间互不打扰
并发:即多个进程在一个进程下采用进程切换的方式,在一段时间段内,让多个进程都得以共同推进,称之为并发
并行:多个进程在多个CPU下同时进行
环境变量:
基本概念
环境变量一般是指在操作系统中指定操作系统运行环境的一些参数
常见环境变量
- PATH:指定命令的搜索路径
- HOME:指定用户的主工作目录
- SHELL:当前shell,他的值一般是/bin/bash
查看当前环境变量的方法
使用echo来查看:
echo $NAME //NAME为待查看的环境的名称
测试PATH
大家有没有想过这样一个问题:为什么执行ls命令时不用带./,而在执行我们自己的可执行程序时就必须要带上?
容易理解的是,我们在执行一个程序的时候,必须要先找到他在哪里,既然不带ls就可以执行ls,说明操作系统可以找到他,而系统找不到我们的可执行程序,必须带上./来说明他在我们的当前目录下。
而系统就是通过环境变量PATH来找到ls的,查看环境变量PATH,可以看到下面内容:
可以看到很多路径,这些路径通过冒号隔开,然后执行ls命令时,系统会从左到右开始寻找ls命令
而ls命令确实存在与这些路径中的某个路径下面。
那我们可不可以让自己的可执行程序不带./就执行呢
两个方法:
- 一个就是在系统默认的路径下创建这个程序,然后生成可执行程序或者将这个可执行程序拷贝到PATH的某一个路径下面
- 将可执行程序所在的路径导入到PATH这个路径下面
部分环境变量说明:
set:显示本地定义的shell变量和环境变量
unset:清楚环境变量
通过代码来获取环境变量:
你知道main函数其实是由参数的嘛?
我们平常情况不会使用他,所以基本不会写出来。
在这里我们可以看到,调用main函数时向其传递了三个参数。
我们先来说说前两个参数
我们在Linux下写下这个程序并运行:
#include <stdio.h>
int main(int argc,char *argv[])
{
for(int i=0;i<argc;i++)
{
printf("argv[%d]:%s\n",i,argv[i]); } return 0; }
执行结果如下:
现在我们来说说main函数中的前两个参数,其中的第二个参数是一个字符指针数组,数组中第一个字符指针存储的是可执行程序的位置,其余字符指针存储的是所给的若干选项。最后一个指针为空,而前面那个第一个参数就代表着字符指针数组中有效元素的个数
下面我们来写一个简单的代码,这个代码运行起来之后会根据你所给的选项的不同给出不同的提示语句:
现在我们来说说main的第三个参数:
main的第三个参数实际上是接受的环境变量表
可通过他获得系统的环境变量:
通过系统调用获取环境变量:
程序地址空间:
下面我们来验证一下:
最后:
十分感谢你可以耐着性子把它读完和我可以坚持写到这里,送几句话,对你,也对我:
1.一个冷知识:
屏蔽力是一个人最顶级的能力,任何消耗你的人和事,多看一眼都是你的不对。
2.你不用变得很外向,内向挺好的,但需要你发言的时候,一定要勇敢。
正所谓:君子可内敛不可懦弱,面不公可起而论之。
3.成年人的世界,只筛选,不教育。
4.自律不是6点起床,7点准时学习,而是不管别人怎么说怎么看,你也会坚持去做,绝不打乱自己的节奏,是一种自我的恒心。
5.你开始炫耀自己,往往都是灾难的开始,就像老子在《道德经》里写到:光而不耀,静水流深。
最后如果觉得我写的还不错,请不要忘记点赞✌,收藏✌,加关注✌哦(。・ω・。)
愿我们一起加油,奔向更美好的未来,愿我们从懵懵懂懂的一枚菜鸟逐渐成为大佬。加油,为自己点赞!
相关文章:

Linux之进程概念
作者主页: 作者主页 本篇博客专栏:Linux专栏 创作时间 :2024年9月28日 基本概念: 进程说白了其实就是一个程序的执行实例,正在执行的程序。 在内核层面来说,就是一个担当分配资源(CPU时间…...

小程序-使用npm包
目录 Vant Weapp 安装 Vant 组件库 使用 Vant 组件 定制全局主题样式 API Promise化 1. 基于回调函数的异步 API 的缺点 2. 什么是 API Promise 化 3. 实现 API Promise 化 4.调用 Promise 化之后的异步 API 小程序对 npm 的支持与限制 目前,小程序中已经…...

【springboot】整合沙箱支付
目录 1. 配置沙箱应用环境2. 配置springboot项目1. 引入依赖2. 配置文件注册下载ngrok 3. 创建支付宝支付服务类4. 支付界面模板5. 控制类实现支付6. 测试 1. 配置沙箱应用环境 使用支付宝账号登录到开放平台控制台。 使用支付宝登录后,看到以下页面,下…...

技术速递|Python in Visual Studio Code 2024年9月发布
排版:Alan Wang 我们很高兴地宣布将于 2024 年 9 月发布适用于 Visual Studio Code 的 Python 和 Jupyter 扩展! 此版本包括以下公告: Django 单元测试支持使用 Pylance 从 inlay 提示转到定义 如果您有兴趣,可以在我们的 Pyth…...

数据结构-3.5.队列的顺序实现
一.队列的顺序实现,初始化操作以及判断队列是否为空: 1.图解: 2.代码: #include<stdio.h> #define MaxSize 10 //定义一个队列最多存储的元素个数 typedef struct {int data[MaxSize]; //用静态数组存放队列元素int f…...
preconnect 预解析
preconnect 是一种浏览器优化技术,用于告诉浏览器提前与指定的域名建立连接,包括DNS解析、TCP握手和TLS协商(如果适用)。这样做可以减少客户端在请求资源时所需的往返时间(RTT),从而提高页面加载…...

Leecode热题100-283.移动零
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。 请注意 ,必须在不复制数组的情况下原地对数组进行操作。 示例 1: 输入: nums [0,1,0,3,12] 输出: [1,3,12,0,0]示例 2: 输入: nums [0] 输出: […...

如何高效使用Prompt与AI大模型对话
一、如何与人工智能对话 在人工智能的世界里,提示词(Prompt)就像是一把钥匙,能够解锁AI智能助手的潜力,帮助你更高效地获取信息、解决问题。但如何正确使用这把钥匙,却是一门艺术。本文将带你了解提示词的…...

Java 之深入理解 String、StringBuilder、StringBuffer
前言 由于发现 String、StringBuilder、StringBuffer 面试的时候会经常问到,这里就顺便总结一下:本文重点会以这三个字符串类的性能、线程安全、存储结构这三个方面进行分析 ✨上期回顾:Java 哈希表 ✨目录 前言 String 介绍 String 的不可变…...

vue3项目执行pnpm update后还原package.json文件后运行报错
项目场景: vue官方版本已更新到vue3.5,项目中还在使用vue3.4,因此想要更新项目vue版本。 问题描述 执行了 pnpm update 命令,一键更新了所有包,更新完成后项目不能正常运行。为了还原项目代码,先删除 nod…...

蓝桥杯【物联网】零基础到国奖之路:十七. 扩展模块之单路ADC和NE555
蓝桥杯【物联网】零基础到国奖之路:十七. 扩展模块之单路ADC和NE555 第一节 硬件解读第二节 CubeMx配置第三节 代码1,脉冲部分代码2,ADC部分代码 第一节 …...
SolveigMM Video Splitter方便快捷视频分割合并软件 V3.6.1309.3-供大家学习研究参考
视频分割功能(Splitter)支持各种编码格式的AVI(DivX、DV、MJPEG、XVID、MPEG-4)、WMV、ASF(DivX、MJPEG、XVID、MPEG-4、WM Video 7/9)F、MPEG(*.mpg、*.mpeg、*.mpv、*.m2v、*.vob)文件、也支持受损的WMV、ASF格式的分割。视频合并功能(Joiner)则支持AVI、WMV/ASF、WMA、MP3、…...

Unity3D 创建一个人物,实现人物的移动
1,创建项目 首先打开我们的Unity Hub 在我们的编译器下面新建项目,选择3D模板,更改一下我们的项目名称,选择一下路径,然后点击创建项目 等待项目创建。。。。。。 我们在项目里先创建一个plane,这样有点视…...

【笔记】数据结构12
文章目录 2013年408应用题41方法一方法二 看到的社区的一个知识总结,这里记录一下。 知识点汇总 2013年408应用题41 解决方法: 方法一 (1)算法思想 算法的策略是从前向后扫描数组元素,标记出一个可能成为主元素的元…...

django的URL配置
1 django如何处理一个请求 首先Django要使用根URLconf模块,通过setting.py配置文件的ROOT_URLCONF来设置。 加载该模块后并查找变量 urlpatterns。这是一个Python的django.conf.urls.url()实例列表。 Django按顺序运行每个URL模式,并在匹配所请求的…...

精华帖分享 | 因子构建思考1
本文来源于量化小论坛股票量化板块精华帖,作者为z-coffee。 以下为精华帖正文: 一段时间没写帖子,其实一直在研究策略,只是从不同的角度去思考而已。熟悉我的老板其实清楚,我的炉子水平一般,基本不太依托…...
kubernetes笔记(四)
一、Pod调度策略 1.基于节点的调度 spec->nodeName [rootmaster ~]# vim myhttp.yaml --- kind: Pod apiVersion: v1 metadata:name: myhttp spec:nodeName: node-0001 # 基于节点名称进行调度containers:- name: apacheimage: myos:httpd[rootmaster ~]# kubectl a…...

通信工程学习:什么是SNMP简单网络管理协议
SNMP:简单网络管理协议 SNMP(Simple Network Management Protocol,简单网络管理协议)是一种用于在计算机网络中管理网络节点(如服务器、工作站、路由器、交换机等)的标准协议。它属于OSI模型的应用层&#…...

ubuntu20.04系统下,c++图形库Matplot++配置
linux下安装c图形库Matplot,使得c可以可视化编程;安装Matplot之前,需要先安装一个gnuplot,因为Matplot是依赖于此库 gnuplot下载链接: http://www.gnuplot.info/ 一、gnuplot下载与安装(可以跳过,下面源码…...

[激光原理与应用-126]:南京科耐激光-激光焊接 - 焊中无损检测技术 - 智能制程监测系统IPM介绍 - 26- 频域分析法
目录 一、什么是频域分析法 1、定义 2、基本原理 3、分析步骤 4、应用领域 5、优缺点 二、频域分析法在激光焊接故障监测中的应用 2.1 概述 1、应用背景 2、频域分析法的应用 3、应用优势 4、应用实例 2.2 激光焊接故障检测中光电信号的频谱特征 1、光电信号分类…...

简易版抽奖活动的设计技术方案
1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...

ardupilot 开发环境eclipse 中import 缺少C++
目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建
华为云FlexusDeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色,华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型,能助力我们轻松驾驭 DeepSeek-V3/R1,本文中将分享如何…...

Springboot社区养老保险系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,社区养老保险系统小程序被用户普遍使用,为方…...

ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...

C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...