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

进程概念(三)----- fork 初识

目录

  • 前言
  • 1. pid && ppid
  • 2. fork
    • a. 为什么 fork 要给子进程返回 0, 给父进程返回子进程的 pid ?
    • b. 一个函数是如何做到两次的?
    • c. fork 函数在干什么?
    • d. 一个变量怎么做到拥有不同的内容的?
    • e. 拓展:fork()之后,父子进程谁先运行?

前言

该篇文章是继 添加链接描述 文章的后续,针对 linux 中的 task_struct 进程的 PID(也即标识符)介绍,和系统调用中的 fork 展开初步的认识。

task_ struct 内容分类:
标识符:  描述本进程的唯一标识符,用来区别其他进程。
状态:  任务状态,退出代码,退出信号等。
优先级:  相对于其他进程的优先级。
程序计数器:  程序中即将被执行的下一条指令的地址。(其作用就相当于进程运行了一段时间后,因为系统调度等原因,停止了对该进程的执行而后续回来继续执行的时候,需要知道上次执行到什么地方了。也好比我们看书,今天看完不想看了之后,会在此处做一下标记,方便后续继续向下观看)
内存指针:  包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针(比如记录了该进程所匹配的代码和数据的存储位置)
上下文数据:  进程执行时处理器的寄存器中的数据[休学例子,要加图CPU,寄存器]。
I/O状态信息:  包括显示的I/O请求,分配给进程的 I/O 设备和被进程使用的文件列表。
记账信息:  可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。(保证系统调度的公平等)
其他信息


1. pid && ppid

在前面的进程相关的文章,我们已经知道了,因为用户不擅长直接对操作系统进行访问,并且操作系统也不会相信用户,因此用户无法直接访问操作系统。而在上一篇文章的末尾,我们简单见过了进程的 PID,但是那是通过系统指令获取到的 PID,而作为用户在编程语言上,在无法访问操作系统拿到数据的前提下,如何获取进程的 PID 等进程信息呢?

// 测试demo
#include<iostream>
#include<unistd.h>
using namespace std;int main()
{while(1){cout << "I am a process, my pid is " << getpid() << ", my parentId is " << getppid() << '\n';sleep(1);}return 0;
}

在这里插入图片描述

左右对比,我们是可以得知,在我们通过 c / c++ 编写的程序,运行起来后,系统会自动会该进程创建一个 PID,并且在cpp 中预取这个 PID 和我们在系统中获取的 PID 是一致的。

所以,PID 有什么用呢?? ---- 既然 PID 是每个进程的唯一标识符,那么当我们对进程进行管理的时候,就可以通过其PID 对该进程进行操作,比如杀掉该进程 kill -9 20059 等操作。

在这里插入图片描述

而当我们结束上一次进程,重新运行我们的程序时,我们又会发现,它的 pid 不一样了,这也是正常的现象。但是我们可以发现,进程自己的 pid 会变,但是他的父进程的 pid 确不会变!一直是 2742,好奇心驱动我们去查看这个父进程,它到底是谁!

在这里插入图片描述

没错!2742 它就是我们的 bash,这个 bash 进程是由 xshell 为我们创建的一个命令行的进程!所以同理,当我们断开对 linux 的链接之后,再一次链接 linux,进程的 ppid 也会随之改变,即我们每一次通过xshell 远程连接我们的服务器时,xshell 都会为我们重新分配一个 bash 进程,用来给我们提供命令行服务!


2. fork

但是上述的这些进程,可都是操作系统给我们创建出来的。那么现在我要手动创建进程,该怎么做呢? ---- 调用 fork 系统函数。那么修改后的 demo 代码如下:

int main()
{cout << "before the fork!\n";fork();cout << "after the fork!\n";sleep(1)return 0;
}

在这里插入图片描述

很明显,在执行完 fork函数之后,fork 之后的代码,被执行了 两次!为什么?最简单的回答就是,因为 fork 是创建进程的系统函数,因此在执行完 fork 之后,会有两个进程,同时执行这一份代码,所以代码一共被执行了两次!

但是上述仅仅是我们的猜测,为了更清楚的了解 fork 函数干了什么,我们需要通过 man 手册进一步了解 fork 函数!

在这里插入图片描述

以上是 fork 函数介绍中的一段信息,但是有一点奇怪的是!这个函数怎么可以返回两个值呢??据 man 手册的介绍,如果进程创建成功,返回这个进程的 pid 给它的父进程,返回 0 给自己;创建失败,则返回 -1 给父进程。这显然是我们无非理解的,在 C/C++ 语言当中,函数的返回值一直都只能有一个啊!而现在,这个 fork 函数,它告诉我有两个返回值!

多的不说,我们再来做一个 demo 测试,到底是不是真的这样,这个函数有两个返回值。

int main()
{cout << "I am a process, pid: " << getpid() << ", ppid: " << getppid() << '\n';pid_t pid = fork();if(pid == 0){// 子进程部分while(1){cout << "I am a child process, pid: " << getpid() << ", ppid: " << getppid() << "\n";sleep(1);}}else if(pid > 0){// 父进程部分while(1){cout << "I am a parent process, pid: " << getpid() << ", ppid: " << getppid() << "\n";sleep(1);}}else{cout << "error\n";}return 0;
}

在这里插入图片描述

没错!就是这么神奇,如果站在语言上的认知,这是根本无法理解的现象,每个 if 分支里面都是一个死循环,但是,运行起来确出现了两个 if 分支里的内容!所以这可以进一步的说明了,fork 之后,会多一个进程,而这个进程是由原来的进程所创建出来的,它的 ppid (即父进程)就是创建它的进程的 pid !而 fork 作为系统调用接口,也会为创建出来的进程进行属性初始化(分配 pid 等操作)。所以站在系统的角度看待这一段代码的话,那么就能说明原本的进程,作为父进程,在执行完 fork 函数之后,接收到的是创建出来的子进程的 pid,因此会执行第一个 if 分支,而子进程自己接收到 0 的返回值,所以执行第二个 if 分支的内容。

一般而言,fork 之后的代码,是父进程与子进程共享的!所以返回值的不同,恰恰是为了区分,让不同的执行流执行不同的代码块!

接下来,我们要回答几个关于 fork 的问题。

a. 为什么 fork 要给子进程返回 0, 给父进程返回子进程的 pid ?

你知道的,父亲永远只有一个,而孩子可以有很多个,一个孩子也不可能同时有两个父亲。因此在操作系统中同理,一个父进程可以有多个子进程,但是不可能存在一个子进程有多个父进程!所以把子进程的 pid 给父进程,是为了让父进程可以明确的找到它的子进程,而子进程永远只有一个父进程,就不用谈找不到这件事了。假设今天父进程有10个子进程,但是它并不知道这个进程跟那个进程的 pid,也就无法明确指定操作其中某一个子进程了!再者,父进程在创建时,父进程有自己的内核 pcb 数据结构,也有自己的代码和数据,那现在父进程创建出一个子进程之后,系统会为子进程其分配一个 pcb,这没问题,但是子进程应该执行什么样的代码和访问什么样的数据呢? 而开始创建子进程是时候,子进程是没有自己的代码和数据的,所以子进程只能与父进程共享一样的代码(数据另谈)!那问题又来了,当 cpu 在调度的时候,父进程在执行这一份代码,子进程也是执行的这一份代码,这也是上面实验时,fork 之后的代码会重复执行两遍的原因。那这有什么意义呢?或者说,同样的代码为什么要执行两遍呢?所以问题就回归到了 我们为什么要创建这个子进程?! 所以一定是为了让父进程和子进程执行不同的代码,完成不同的工作!所以就需要让 fork 具有不同的返回值,才能达到区别不同的执行流!

b. 一个函数是如何做到两次的?

既然 fork 是用于创建进程的一个系统调用函数,而站在系统层面上,创建进程就要为其创建一个 pcb,并且每个进程需要有与其匹配的代码和数据,这是系统在创建进程时需要做的工作。那么我们就不难猜测,fork 在干什么。

pid_t fork(void)
{创建子进程填充 PCB 对应的内容让父子进程共享同一份代码到这一步,父子进程都用拥有了自己独立的 task_struct(即 PCB),可以被 cpu 调度运行了......return ret;
}

我们知道的是,子进程被创建出来之后,父子进程会共享代码,因此 fork 之后的代码才会被执行两次。现在的问题就是那么 return ret 是不是一条代码? ---- 它是代码是不争的事实!又因为在 return 之前子进程就已经被创建了,并且也完成了其 pcb 的各种初始化工作,同父进程一样拥有独立的 task_struct,所以既然在 return 语句的时候,子进程就已经完全存在了,那么 return 语句就自然是会被父子进程都执行!所以父进程返回一次,子进程返回一次,这个函数一共就返回了两次!

c. fork 函数在干什么?

其实这个问题在上面的介绍中,就已经不难得知了。fork 就是在创建一个进程,并且用其父进程对应的字段来初始化子进程,而因为子进程刚创建出来,没有自己的代码和数据,所以就需要和父进程共享同一份代码(数据另谈)。我们都知道,之所以可以共享代码,是因为代码存储在系统的常量区,它是不能够被修改的,因此父进程并不会因为与子进程进行代码共享而受到影响。但是数据就不一定,数据是可以被修改的!所以假如父进程和子进程共享同一份数据,然后子进程需要对其中的数据进行修改,这个数据又恰恰是父进程的某一个条件判断所需的数据,这就势必会影响到父进程的正常运行!那怎么办呢??所以子进程可以将父进程的数据拷贝一份给自己独立使用,自己怎么修改都不会影响到父进程。但是问题又来了,假设父进程当中有100个全局变量数据,而将来子进程只需要用到其中一个,其它的 99 个甚至更多都不需要修改,这样就会导致系统资源变少,利用率也变低。而实际上,被创建出来的子进程,需要修改到的数据其实是不大的,基本不可能有子进程需要修改父进程的全部数据。因此在面对数据方面,子进程则是采用了 写时拷贝 的策略,当子进程与父进程进行数据共享之后,子进程需要修改数据,系统就会为子进程开辟一块属于子进程自己的空间,并且将要修改的数据拷贝一份,供子进程修改和使用,子进程需要多少空间,系统就开辟多少,而后续子进程访问的也是自己的数据,这样父子进程就不会互相影响(因为我们需要保证让进程之间相互独立,互不影响。总不能是今天我csdn网页的进程奔溃了,连同我的音乐进程也奔溃了吧)。

d. 一个变量怎么做到拥有不同的内容的?

这个问题对 b 问题的一个延续,在上面的问答中,我们已经能够得知,一个函数之所以可以返回两个值,是因为在 return 的时候,子进程就已经被创建出来了,并且开始与父进程共享代码;在数据层面上,子进程并不是完全与父进程进行数据共享,而是采用了 写时拷贝 的策略。所以现在需要确定的是,return 是不是一种对数据的修改,或者是算不算数据的写入? ---- return 将数据进行返回,所以有数据,就必须要接收,也即数据的写入,而写入就是修改的范畴,所以当系统检测到子进程要对父进程的数据进行修改的时候,就会为其开辟一块自己的空间供子进程使用。所以站在系统层面上,这个变量数据在内存中存在两份,一份是父进程的,一份是子进程的,所以当我们站在语言的角度上,才看到了一个变量拥有两个不一样的值。

e. 拓展:fork()之后,父子进程谁先运行?

如果大家有这方面的疑惑的话,就需要深入了解在系统调度器方面的知识,因为谁先运行,这是调度器决定的!在系统层面上,谁先运行,取决于调度器决定先将哪个进程提携给 cpu 执行。而每个系统的调度原理都不太一样,所以这方面又是一门足以压死人的学问,小篇也是无能为力。


进程介绍到这里的时候,还远远没有结束,我们现在只是弄清楚进程是什么,以及与进程相关的系统调用 fork,但是进程还会有所谓的状态,比如进程等待,堵塞等等。但是由于篇幅问题,关于进程的状态等方面的信息,小篇会在后续文章中一一介绍。

如果感觉该篇文章给你带来了收获,可以 点赞👍 + 收藏⭐️ + 关注➕ 支持一下!

感谢各位观看!

相关文章:

进程概念(三)----- fork 初识

目录 前言1. pid && ppid2. forka. 为什么 fork 要给子进程返回 0&#xff0c; 给父进程返回子进程的 pid &#xff1f;b. 一个函数是如何做到两次的&#xff1f;c. fork 函数在干什么&#xff1f;d. 一个变量怎么做到拥有不同的内容的&#xff1f;e. 拓展&#xff1a;…...

huawei 路由 RIP 协议中三种定时器的工作原理

RFC2453 定义的三种 RIP 协议定时器 更新定时器&#xff08;Update Timer&#xff09;&#xff1a;用于触发更新报文的发送&#xff0c;超时时间为 30 秒。老化定时器&#xff08;Age Timer&#xff09;&#xff1a;如果在老化时间内没有收到邻居发送的响应报文&#xff0c;则…...

HTML常见标签——超链接a标签

一、a标签简介 二、a标签属性 href属性 target属性 三、a标签的作用 利用a标签进行页面跳转 利用a标签返回页面顶部以及跳转页面指定区域 利用a标签实现文件下载 一、a标签简介 <a>标签用于做跳转、导航&#xff0c;是双标签&#xff0c;记作<a></a>&#…...

Python 爬虫入门(一):从零开始学爬虫 「详细介绍」

Python 爬虫入门&#xff08;一&#xff09;&#xff1a;从零开始学爬虫 「详细介绍」 前言1.爬虫概念1.1 什么是爬虫&#xff1f;1.2 爬虫的工作原理 2. HTTP 简述2.1 什么是 HTTP&#xff1f;2.2 HTTP 请求2.3 HTTP 响应2.4 常见的 HTTP 方法 3. 网页的组成3.1 HTML3.2 CSS3.…...

Linux嵌入式学习——数据结构——概念和Seqlist

数据结构 相互之间存在一种或多种特定关系的数据元素的集合。 逻辑结构 集合&#xff0c;所有数据在同一个集合中&#xff0c;关系平等。 线性&#xff0c;数据和数据之间是一对一的关系。数组就是线性表的一种。 树&#xff0c; 一对多 图&#xff0c;多对多 …...

iOS ------ Block的相关问题

Block的定义 Block可以截获局部变量的匿名函数&#xff0c; 是将函数及其执行上下文封装起来的对象。 Block的实现 通过Clang将以下的OC代码转化为C代码 // Clang xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m//main.m #import <Foundation/Foundation.…...

conda issue

Conda 是一个跨平台、通用的二进制包管理器。它是 Anaconda 安装使用的包管理器&#xff0c;但它也可能用于其他系统。Conda 完全用 Python 编写&#xff0c;并且是 BSD 许可的开源。通用意味着大部分的包都可以用它进行管理&#xff0c;很像一个跨平台版本的apt或者yum&#x…...

为了解决地图引入鉴权失败的解决方案

在以下文件中需要添加相应代码 app/controller/CollageProduct.php app/view/designer_page/designer_editor.html app/view/designer_page/designer.html app/controller/Freight.php app\controller\Business.php app\controller\DesignerPage.php 只有这样才能保证htt…...

[ptrade交易实战] 第十八篇 期货查询类函数和期货设置类函数

前言 今天主要和大家分享的是期货查询类的函数和期货设置类的函数&#xff01; 具体的开通渠道可以看文章末尾&#xff01; 一、get_margin_rate—— 获取用户设置的保证金比例 保证金是期货交易中的一个重点&#xff0c;这个函数就是用来获取我们设置的保证金比例的&#…...

STM32智能家居控制系统教程

目录 引言环境准备智能家居控制系统基础代码实现&#xff1a;实现智能家居控制系统 4.1 数据采集模块 4.2 数据处理与分析模块 4.3 通信与网络系统实现 4.4 用户界面与数据可视化应用场景&#xff1a;家居监测与优化问题解决方案与优化收尾与总结 1. 引言 智能家居控制系统通…...

FPGA 中的 IOE与IO BANK

IO bank&#xff08;输入/输出bank&#xff09; 定义&#xff1a;IO bank 是 FPGA 中一组 IOE 的集合&#xff0c;通常共享相同的电源电压、时钟域和时序管理。每个 IO bank 包含多个 IOE&#xff0c;它们可以根据需要分配给不同的信号处理任务。作用&#xff1a;IO bank 的存…...

ADetailer模型+Stable Diffusion的inpainting功能是如何对遮罩区域进行修复生成的ADetailer

模型选则&#xff1a; face_yolov8n.pt 和 face_yolov8s.pt&#xff1a; 用途&#xff1a;用于人脸检测。特点&#xff1a;YOLOv8n 是轻量级版本&#xff0c;适合资源有限的设备&#xff1b;YOLOv8s 是标准版本&#xff0c;检测精度更高。 hand_yolov8n.pt&#xff1a; 用途&am…...

【博士每天一篇文献-综述】2024机器遗忘最新综述之一:An overview of machine unlearning

1 介绍 年份&#xff1a;2024 作者&#xff1a; 期刊&#xff1a; High-Confidence Computing&#xff08;2区&#xff09; 引用量&#xff1a;0 Li C, Jiang H, Chen J, et al. An overview of machine unlearning[J]. High-Confidence Computing, 2024: 100254 本文详细提供…...

【机器学习】Jupyter Notebook如何使用之基本步骤和进阶操作

引言 Jupyter Notebook 是一个交互式计算环境&#xff0c;它允许创建包含代码、文本和可视化内容的文档 文章目录 引言一、基本步骤1.1 启动 Jupyter Notebook1.2 使用 Jupyter Notebook 仪表板1.3 在笔记本中工作1.4 常用快捷键1.5 导出和分享笔记本 二、进阶用法2.1 组织笔…...

C++ | Leetcode C++题解之第279题完全平方数

题目&#xff1a; 题解&#xff1a; class Solution { public:// 判断是否为完全平方数bool isPerfectSquare(int x) {int y sqrt(x);return y * y x;}// 判断是否能表示为 4^k*(8m7)bool checkAnswer4(int x) {while (x % 4 0) {x / 4;}return x % 8 7;}int numSquares(i…...

Vue 3 响应式高阶用法之 `shallowRef()` 详解

Vue 3 响应式高阶用法之 shallowRef() 详解 文章目录 Vue 3 响应式高阶用法之 shallowRef() 详解简介一、使用场景1.1 深层嵌套对象的性能优化1.2 需要部分响应式的场景 二、基本使用2.1 引入 shallowRef2.2 定义 shallowRef 三、功能详解3.1 浅层响应式3.2 与 ref 的对比 四、…...

流量录制与回放:jvm-sandbox-repeater工具详解

在软件开发和测试过程中&#xff0c;流量录制与回放是一个非常重要的环节&#xff0c;它可以帮助开发者验证系统在特定条件下的行为是否符合预期。本文将详细介绍一款强大的流量录制回放工具——jvm-sandbox-repeater&#xff0c;以及如何利用它来提高软件测试的效率和质量。 …...

内网渗透—内网穿透工具NgrokFRPNPSSPP

前言 主要介绍一下常见的隧道搭建工具&#xff0c;以此来达到一个内网穿透的目的。简单说一下实验滴环境吧&#xff0c;kali作为攻击机&#xff0c;winserver2016作为目标靶机。 kali 192.168.145.171 winserver2016 10.236.44.127 显然它们处于两个不同的局域网&#xff0c…...

嵌入式中传感器数据处理方法

大家好,在传感器使用中,我们常常需要对传感器数据进行各种整理,让应用获得更好的效果,以下介绍几种常用的简单处理方法: 加权平滑:平滑和均衡传感器数据,减小偶然数据突变的影响。 抽取突变:去除静态和缓慢变化的数据背景,强调瞬间变化。 简单移动平均线:保留数据流最…...

生成式 AI 的发展方向,是 Chat 还是 Agent?

据《福布斯》报道&#xff0c;商业的未来是自动化。他们报告说&#xff0c;自动化的应用是不可避免的&#xff0c;“工人们即将被一个圈子和一套规则包围&#xff0c;要严格遵守&#xff0c;不能偏离。得益于聊天机器人ChatGPT于2022年11月推出所带来的强劲加持&#xff0c;202…...

金字塔监督在人脸反欺骗中的应用

介绍 论文地址&#xff1a;https://arxiv.org/pdf/2011.12032.pdf 近年来&#xff0c;人脸识别技术越来越普及。在智能手机解锁和进出机场时&#xff0c;理所当然地会用到它。人脸识别也有望被用于管理今年奥运会的相关人员。但与此同时&#xff0c;人们对人脸欺骗的关注度也…...

vue3——两种利用自定义指令实现防止按钮重复点击的方法

方法一&#xff1a;利用定时器设置时间&#xff0c;下方代码设置时间为1秒 但是有个缺点&#xff1a;请求如果很慢&#xff0c;1秒钟还没有好&#xff0c;那么该方法就没用了 // 利用定时器&#xff1a;1秒之后才能再次点击app.directive(preventReClick, {mounted: (el, bind…...

Chrome谷歌浏览器Console(控制台)显示文件名及行数

有没有这样的困扰&#xff1f;Chrome谷歌浏览器console(控制台)不显示编译文件名及行数? 设置&#xff08;Settings&#xff09;- > 忽略列表&#xff08;lgnore List&#xff09;-> 自定义排除规则&#xff08;Custom exclusion rules&#xff09; 将自定义排除规则…...

Vue3+Element Plus 实现table表格中input的验证

实现效果 html部分 <template><div class"table"><el-form ref"tableFormRef" :model"form"><el-table :data"form.detailList"><el-table-column type"selection" width"55" align&…...

安宝特方案|解放双手,解决死角,AR带来质量监督新体验

AR质量监督 解放双手&#xff0c;解决死角 在当今制造业快速发展的背景下&#xff0c;质量监督成为确保产品高质量和完善的管理制度的关键环节。然而&#xff0c;传统的质量监督方式存在诸多挑战&#xff0c;如人工操作带来的效率低下、查岗不及时、摄像头死角等问题。 为了解…...

Django教程(005):基于ORM操作数据库的部门管理系统

文章目录 1、功能介绍2、新建项目3、创建app4、 表结构创建6、生成表7、静态文件管理8、部门管理8.1、部门列表8.2、添加部门8.3、删除部门8.4、编辑部门9、员工管理9.1、员工列表9.2、使用ModelForm添加员工9.3、编辑员工9.4、删除员工10、完整代码下载地址1、功能介绍 部门添…...

git等常用工具以及cmake

一、将git中的代码克隆进电脑以及常用工具介绍 1.安装git 首先需要安装git sudo apt install git 注意一定要加--recursive&#xff0c;因为文件中有很多“引用文件“&#xff0c;即第三方文件&#xff08;库&#xff09;&#xff0c;加入该选项会将文件中包含的子模…...

Mybatis(四)特殊SQL的查询:模糊查询、批量删除、动态设置表明、添加功能获取自增的主键

实体类&#xff1a; 数据库&#xff1a; 1、模糊查询 方案一&#xff1a; 不适用#{ }&#xff0c;’%?%‘ 问号是属于字符串的一部分 不会被解析成占位符&#xff0c;会被当作是我们字符串的一部分来解析&#xff0c;所以我们执行的语句中找不到占位符&#xff0c;但是我们却…...

JS原型与原型链

JS原型与原型链 JavaScript中一切引用类型都是对象&#xff0c;对象就是属性的集合。 Array类型、Function类型、Object类型、Date类型、RegExp类型等都是引用类型。 原型是什么 总计一句话就是&#xff08;继承里的父亲&#xff0c;你可以使用你的原型里的函数&#xff09;…...

Python编程学习第一篇——Python零基础快速入门(六)(4)异常处理

我们已经了解了Python的基本数据类型、变量和基本的逻辑控制语句&#xff0c;基于这些基础知识可以编写一些小程序了&#xff0c;但是在写程序的时候我们会发现&#xff0c;有时候程序并不是按我们预期的方向执行&#xff0c;有的直接报错&#xff0c;有的没有报错&#xff0c;…...

GraphHopper-map-navi_路径规划、导航(web前端页面版)

文章目录 一、项目地址二、踩坑环境三、问题记录3.1、graphhopper中地图问题3.1.1. getOpacity不存在的问题3.1.2. dispatchEvent不存在的问题3.1.3. vectorLayer.set(background-maplibre-layer, true)不存在set方法3.1.4. maplibre-gl.js.map不存在的问题3.1.5. Uncaught Ref…...

2-46 基于matlab的声音信号的短时能量、短时过零率、端点检测

基于matlab的声音信号的短时能量、短时过零率、端点检测。通过计算计算短时能量、调整能量门限&#xff0c;然后开始端点检测。输出可视化结果。程序已调通&#xff0c;可直接运行。 2-46 短时能量 短时过零率 端点检测 - 小红书 (xiaohongshu.com)...

力扣630.课程表 II

力扣630.课程表 II 反悔堆 将课程按照结束时间从大到小排序每次取一个判断当前是否能学完该课程如果能学完就将持续时间加入堆 更新答案如果学不完就判断该课程持续时间是否比之前学过的最大的还大 用时更短的话就将旧的弹出 class Solution {public:int scheduleCourse(ve…...

数字IC后端流程简述

1. 设计输入 目标:接收前端设计(如RTL代码和约束文件)的输出。 工具:前端设计工具(如Synopsys Design Compiler或Cadence Genus)。 步骤: 确保前端设计的RTL代码经过综合并生成了门级网表(Netlist)。 收集约束文件(Constraints),如时序约束(SDC文件)、功率约束等…...

数学建模--整数规划和非线性规划

目录 整数规划 非线性规划 总结 整数规划中分支定界法的具体步骤和实现细节是什么&#xff1f; 初始化&#xff1a; 分支&#xff1a; 定界&#xff1a; 剪枝&#xff1a; 终止条件&#xff1a; 非线性规划中的梯度法、牛顿法和拟牛顿法的比较分析有哪些&#xff1f;…...

Linux-查看dd命令进度

查看dd命令进度 一、概述1. 在一个终端执行拷贝任务2. 在另一终端执行进度命令 一、概述 系统&#xff1a;Ubuntu 22.04 在使用 dd 命令做拷贝大量数据的时候&#xff0c;因为并没有输出&#xff0c;所以比较难判断当前进度&#xff0c;因此可以使用下面的命令作为进度查看 …...

高效微调 100 多种大语言模型:先计算法,急速推理!

hiyouga/LLaMA-Factoryhttps://github.com/hiyouga/LLaMA-Factory Stars: 26.9k License: Apache-2.0 LLaMA-Factory 是一个用于高效微调 100 多个大型语言模型&#xff08;ACL 2024&#xff09;的 WebUI。 多种模型&#xff1a;LLaMA、LLaVA、Mistral、Mixtral-MoE、Qwen、Y…...

opencv grabCut前景后景分割去除背景

参考&#xff1a; https://zhuanlan.zhihu.com/p/523954762 https://docs.opencv.org/3.4/d8/d83/tutorial_py_grabcut.html 环境本次&#xff1a; python 3.10 提取前景&#xff1a; 1、需要先把前景物体框出来 需要坐标信息&#xff0c;可以用windows自带的画图简单提取像素…...

qt--电子相册

一、项目要求 设计一个电子相册&#xff0c;点击上一张&#xff0c;切换到上一张图片&#xff0c;点击下一张&#xff0c;切换到下一张图片。 要求&#xff1a;图片的展示可以循环&#xff08;QList<QString>&#xff09; 要求&#xff1a;界面美观 二、项目代码 本质是通…...

【MSP430】MSP430F5529几个定时器

MSP430F5529共有四个定时器&#xff0c;其中三个是Timer_A定时器&#xff0c;一个是Timer_B定时器。 这些定时器在MSP430F5529微控制器中发挥着重要的作用&#xff0c;不仅支持多重捕获/比较、PWM输出和内部定时功能&#xff0c;还具有丰富的中断处理能力。这些特性使得MSP430…...

苍穹外卖(一)之环境搭建篇

Ngnix启动一闪而退 启动之前需要确保ngnix.exe的目录中没有中文字体&#xff0c;在conf目录下的nginx.conf文件查看ngnix的端口号&#xff0c;一般默认为80&#xff0c;若80端口被占用就会出现闪退现象。我们可以通过logs/error.log查看错误信息&#xff0c;错误信息如下&…...

【限免】16PAM、16PSK、16QAM、16CQAM星座图及误码率【附MATLAB代码】

​微信公众号&#xff1a;智能电磁频谱算法 QQ交流群&#xff1a;949444104 主要内容 MATLAB代码 % Parameters M 16; N 4; % Number of circles for CQAM SNR_dB 0:2:25; % Extended SNR range to reach higher values num_symbols 1e5; % Total number of symbols for s…...

09-软件易用性

易用性是用户体验的一个重要方面&#xff0c;网站建设者一般会沉溺于自己的思维习惯&#xff0c;而造成用户使用的不畅。易用性不仅是专业UI/UE人员需要研究&#xff0c;对于网站建设其他岗位的人也应该了解一定的方法去检验和提升网站的易用性。通常对易用性有如下定义: 易理解…...

FPGA开发——独立仿真和联合仿真

一、概述 我们在进行FPGA开发的过程之中&#xff0c;大部分情况下都是在进行仿真&#xff0c;从而验证代码实现结果的正确与否&#xff0c;这里我们引入了独立仿真和联合仿真进行一个简单介绍。 联合仿真&#xff1a;一般我们在进行仿真之前需要在相应的软件中建立相应的工程…...

基于STM32瑞士军刀--【FreeRTOS开发】学习笔记(二)|| 堆 / 栈

堆和栈 1. 堆 堆就是空闲的一块内存&#xff0c;可以通过malloc申请一小块内存&#xff0c;用完之后使用再free释放回去。管理堆需要用到链表操作。 比如需要分配100字节&#xff0c;实际所占108字节&#xff0c;因为为了方便后期的free&#xff0c;这一小块需要有个头部记录…...

ABAP+从SAP发出去的PDF文件在第三方系统出现乱码

这是一个 ABAP转换PDF调用函数CALL FUNCTION CONVERT_OTF的问题记录&#xff0c;关乎字体STSong-Light-ldentity-H 和 STSong-Light的区别 背景&#xff1a; 做了一个增强&#xff0c;是采购订单审批后自动发送采购订单PDF1到企业微信&#xff0c;用户再将企业微信收到的P…...

基于springsecurity的会话并发处理功能(附代码)

1. 需求 在项目中往往需要实现一个限制不同设备同时登录的功能&#xff0c;比如我只允许同一时间只有一个客户端能登录&#xff0c;而其他的已登陆的客户端会被挤出来 而springsecurity中恰好就帮我们实现好了对应的接口功能&#xff0c;我们只需要自定义配置就好 2. 结合sp…...

Redis底层数据结构的实现

文章目录 1、Redis数据结构1.1 动态字符串1.2 intset1.3 Dict1.4 ZipList1.5 ZipList的连锁更新问题1.6 QuickList1.7 SkipList1.8 RedisObject 2、五种数据类型2.1 String2.2 List2.3 Set2.4 ZSET2.5 Hash 1、Redis数据结构 1.1 动态字符串 Redis中保存的Key是字符串&#xf…...

制作excel模板,用于管理后台批量导入船舶数据

文章目录 引言I 数据有效性:基于WPS在Excel中设置下拉框选择序列内容II 数据处理:基于easyexcel工具实现导入数据的持久化2.1 自定义枚举转换器2.2 ExcelDataConvertExceptionIII 序列格式化: 基于Sublime Text 文本编辑器进行批量字符操作引言 需求: excel数据导入模板制…...

领略诗词之妙,发觉生活之美。

文章目录 引言落霞与孤鹜齐飞,秋水共长天一色。野渡无人舟自横。吹灭读书灯,一身都是月。我醉欲眠卿且去,明朝有意抱琴来。赌书消得泼茶香,当时只道是寻常。月上柳梢头,人约黄昏后。最是人间留不住,朱颜辞镜花辞树。山中何事?松花酿酒,春水煎茶。似此星辰非昨夜,为谁风…...