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

《TCP/IP网络编程》学习笔记 | Chapter 19:Windows 平台下线程的使用

《TCP/IP网络编程》学习笔记 | Chapter 19:Windows 平台下线程的使用

  • 《TCP/IP网络编程》学习笔记 | Chapter 19:Windows 平台下线程的使用
    • 内核对象
      • 内核对象的定义
      • 内核对象归操作系统所有
    • 基于 Windows 的线程创建
      • 进程与线程的关系
      • Windows 中线程的创建方法
      • Windows 线程的销毁时间点
      • 编写多线程程序的环境设置
      • 创建“使用线程安全标准 C 函数”的线程
      • 句柄、内核对象和 ID 间的关系
    • 内核对象的 2 种状态
      • 内核对象状态及状态查看
      • 验证内核对象状态的 2 个函数
    • 习题
      • (1)下列关于内核对象的说法错误的是?
      • (2)现代操作系统大部分都在操作系统级别支持线程。根据该情况判断下列描述中错误的是?
      • (3)请比较从内存中完全销毁 Windows 线程和 Linux 线程的方法。
      • (4)通过线程创建过程解释内核对象、线程、句柄之间的关系。
      • (5)判断下列关于内核对象描述的正误。
      • (6)请解释“auto-reset模式”和manual-reset模式”的内核对象。区分二者的内核对象特征是什么?

《TCP/IP网络编程》学习笔记 | Chapter 19:Windows 平台下线程的使用

内核对象

要想掌握 Windows 平台下的线程,应首先理解内核对象(Kernel Objects)的概念。

内核对象的定义

操作系统创建的资源有很多种,如进程、线程、文件及即将介绍的信号量、互斥量等。其中大部分都是通过程序员的请求创建的,而且请求方式各不相同。虽然存在一些差异,但它们之间也有如下共同点:都是由 Windows 操作系统创建并管理的资源。

不同资源类型在管理方式也有差异。例如,文件管理中应注册并更新文件相关的数据I/O位置、文件的打开模式(rcad or write)等。如果是线程,则应注册并维护线程ID、线程所属进程等信息。操作系统为了以记录相关信息的方式管理各种资源,在其内部生成数据块(结构体变量)。当然,每种资源需要维护的信息不同,所以每种资源拥有的数据块格式也有差异。这类数据块称为“内核对象”。

假设在 Windows 下创建了 mydata.txt 文件,此时 Windows 操作系统将生成 1 个数据块以便管理,该数据块就是内核对象。同理,Windows 在创建进程、线程、线程同步信号量时也会生成相应的内核对象,用于管理操作系统资源。

内核对象归操作系统所有

线程、文件等资源的创建请求均在进程内部完成,因此,很容易产生“此时创建的内核对象所有者就是进程”的错觉。其实,内核对象所有者是内核(操作系统),内核对象的创建、管理、销毁时机的决定等工作均由操作系统完成。

基于 Windows 的线程创建

进程与线程的关系

现代操作系统都支持线程,因此,非显式创建线程的程序可描述为“单一线程模型的应用程序”,显式创建单独线程的程序可描述为“多线程模型的应用程序”。这就意味着 main 函数的运行同样基于线程完成,此时进程可以比喻为装有线程的篮子,实际的运行主体是线程。

Windows 中线程的创建方法

#include <windows.h>HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,SIZE_T dwStackSize,LPTHREAD_START_ROUTINE lpStartAddress,LPVOID lpParameter,DWORD dwCreationFlags,LPDWORD lpThreadId
);

参数:

  • IpThreadAttributes:线程安全相关信息,使用默认设置时传递 NULL。
  • dwStackSize:要分配给线程的栈大小,传递 0 时生成默认大小的栈。
  • IpStartAddress:传递线程的 main 函数信息。
  • lpParameter:调用 main 函数时传递的参数信息。
  • dwCreationFlags:用于指定线程创建后的行为,传递 0 时,线程创建后立即进入可执行状态。
  • IpThreadld:用于保存线程 ID 的变量地址值。

成功时返回线程句柄,失败时返回 NULL。

调用该函数将创建线程,操作系统为了管理这些资源也将同时创建内核对象。最后返回用于区分内核对象的整数型“句柄”(Handle)。

第 1 章已介绍过,句柄相当于 Linux的文件描述符。

上述定义看起来有些复杂,其实只需要考虑 IpStartAddress 和 lpParameter 这 2 个参数,剩下的只需传递 0 或 NULL 即可。

Windows 线程的销毁时间点

Windows 线程在首次调用的线程 main 函数返回时销毁(销毁时间点和销毁方法与 Linux 不同)。

还有其他方法可以终止线程,但最好的方法就是让线程main函数终止(返回)。

编写多线程程序的环境设置

旧的 VC++6.0版默认只包含支持单线程的库,需要自行配置。

在项目的属性-代码生成界面,可以检查运行库:

在这里插入图片描述

创建“使用线程安全标准 C 函数”的线程

通过 CreateThread 函数调用创建出的线程在使用 C/C++ 标准函数时并不稳定。

如果线程要调用 C/C++ 标准函数,需要通过如下方法创建线程:

#include <process.h>unitptr_t _beginthreadex(void *security,unsigned stack_size,unsigned (*start_address)(void *),void *arglist,unsigned initflag,unsigned *thrdaddr
);

上述函数与之前的 CreateThread 函数相比,参数个数及各参数的含义和顺序的相同,只是变量名和参数类型有所不同。因此,用上述函数替换 CreateThread 函数时,只需适当更改数据类型。上述函数的返回值类型 uintptr_t 是 64 位 unsigned 整数型。

程序示例:

在这里插入代码片

运行结果:

在这里插入图片描述

与 Linux 相同,Windows 同样在 main 函数返回后终止进程,也同时终止其中包含的所有线程。另外,如果对上述代码进行运行的话,最后输出的内容并非字符串"end of main",而是"running thread"。但这是在 main 函数返回后,完全销毁进程前输出的字符串。

句柄、内核对象和 ID 间的关系

线程属于操作系统管理资源,伴随内核对象的创建,为了引用内核对象而返回句柄。

可以通过句柄区分内核对象,通过内核对象可以区分线程,最终,线程句柄成为区分线程的工具。

句柄的整数值在不同进程中可能重复。通过 CreateThread/_beginthreadex 函数可以得到线程 ID,它用于区分操作系统创建的所有线程,在跨进程范围内不会重复。

内核对象的 2 种状态

应用程序实现过程中需要特别关注的信息被赋予某种“状态”。

线程终止状态又称 signaled 状态,未终止状态称为 non-signaled 状态。

内核对象状态及状态查看

进程或线程终止时,操作系统会把相应的内核对象改为 signaled 状态。

这也意味着,进程和线程的内核对象初始状态是 non-signaled 状态。

内核对象带有 1 个 boolean 变量,其初始值为 FALSE,此时的状态就是 non-signaled 状态。如果发生约定的情况,把该变量改为 TRUE,此时的状态就是 signaled 状态。内核对象类型不同,进入 signaled 状态的情况也有所区别(即对应事件也有区别)。

验证内核对象状态的 2 个函数

首先介绍 WaitForSingleObject 函数,该函数针对单个内核对象验证 signaled 状态。

#include<windows.h>DWORD WaitForSingleObject(HANDLE hHandle,DWORD dwMilliseconds
);

参数:

  • hHandle:查看状态的内核对象句柄。
  • dwMilliseconds:以 1ms 为单位指定超时,传递 INFINITE 时函数不会返回,直到内核对象变成 signaled状态。

进入 signaled 状态返回 WAIT_OBJECT_0,超时返回 WAIT_TIMEOUT,失败时返回 WAIT_FAILED。

该函数由于发生事件(变为 signaled 状态)返回时,有时会把相应内核对象再次改为 non-signaled 状态。这种可以再次进入 non-signaled 状态的内核对象称为“auto-reset模式”的内核对象,而不会自动跳转到 non-signaled 状态的内核对象称为“manual-reset模式”的内核对象。

WaitForMultipleObjects 函数与 WaitForSingleObject 函数不同,可以验证多个内核对象状态。

#include <windows.h>DWORD WaitForMultipleObjects(DWORD nCount,const HANDLE *lphHandles,BOOL bWaitAll,DWORD dwMilliseconds
);

参数:

  • nCount:需验证的内核对象数。
  • IpHandles:存有内核对象句柄的数组地址值。
  • bWaitAll:如果为 TRUE,则所有内核对象全部变为 signaled 时返回;如果为 FALSE,则只要有 1 个对象的状态变为 signaled 就会返回。
  • dwMilliseconds:以 1ms 为单指定超时,传递 INFINITE 时函数不会返回,直到内核对象变为 signaled 状态。

成功时返回事件信息,失败时返回 WAIT_FAILED。

下面利用 WaitForSingleObject 函数尝试解决示例的问题。

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <process.h>unsigned WINAPI ThreadFunc(void *arg); // WINAPI 是 Windows 固有的关键字,表示遵守 _beginthreadex 函数的调用规定int main(int argc, char *argv[])
{HANDLE hThread;DWORD wr;unsigned threadID;int param = 5;hThread = (HANDLE)_beginthreadex(NULL, 0, ThreadFunc, (void *)&param, 0, &threadID);if (hThread == 0){puts("_beginthreadex() error");return -1;}if ((wr = WaitForSingleObject(hThread, INFINITE)) == WAIT_FAILED){puts("thread wait error");return -1;}printf("wait result: %s \n", (wr == WAIT_OBJECT_0) ? "signaled" : "time-out");puts("end of main");system("pause");return 0;
}unsigned WINAPI ThreadFunc(void *arg)
{int cnt = *((int *)arg);for (int i = 0; i < cnt; i++){Sleep(1000);puts("runnning thread");}return 0;
}

运行结果:

在这里插入图片描述

可以看出,thread1_win.c 中的问题得到解决。

第 18 章在 Linux 平台下分析了临界区问题,本章最后的内容将留给 Windows 平台下的临界区问题。

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <process.h>#define NUM_THREAD 50
unsigned WINAPI threadInc(void *arg);
unsigned WINAPI threadDes(void *arg);
long long num = 0;int main(int argc, char *argv[])
{HANDLE tHandles[NUM_THREAD];int i;printf("sizeof long long: %d \n", sizeof(long long));for (i = 0; i < NUM_THREAD; i++){if (i % 2)tHandles[i] = (HANDLE)_beginthreadex(NULL, 0, threadInc, NULL, 0, NULL);elsetHandles[i] = (HANDLE)_beginthreadex(NULL, 0, threadDes, NULL, 0, NULL);}WaitForMultipleObjects(NUM_THREAD, tHandles, TRUE, INFINITE);printf("result: %lld \n", num);system("pause");return 0;
}unsigned WINAPI threadInc(void *arg)
{int i;for (i = 0; i < 50000000; i++)num += 1;return 0;
}unsigned WINAPI threadDes(void *arg)
{int i;for (i = 0; i < 50000000; i++)num -= 1;return 0;
}

运行结果:

在这里插入图片描述

即使多运行几次也无法得到正确结果,而且每次结果都不同。可以利用第 20 章的同步技术得到预想的结果。

习题

(1)下列关于内核对象的说法错误的是?

a. 内核对象是操作系统保存各种资源信息的数据块。
b. 内核对象的所有者是创建该内核对象的进程。
c. 由用户进程创建并管理内核对象。
d. 无论操作系统创建和管理的资源类型是什么,内核对象的数据块结构都完全相同。

答:

b、c、d。

(2)现代操作系统大部分都在操作系统级别支持线程。根据该情况判断下列描述中错误的是?

a. 调用 main 函数的也是线程。
b. 如果进程不创建线程,则进程内不存在任何线程。
c. 多线程模型是进程内可以创建额外线程的程序类型。
d. 单一线程模型是进程内只额外创建 1 个线程的程序模型。

答:

b、d。

(3)请比较从内存中完全销毁 Windows 线程和 Linux 线程的方法。

在这里插入图片描述

(4)通过线程创建过程解释内核对象、线程、句柄之间的关系。

线程创建过程:

  1. 用户程序通过系统调用请求创建线程。
  2. 内核创建线程对象。
  3. 内核将线程对象的引用封装为句柄,返回给用户程序。
  4. 线程开始执行用户定义的 main 函数,代码运行在用户态。
  5. 当线程函数结束且所有句柄关闭,内核销毁线程对象。

在这里插入图片描述

总结:

内核对象是操作系统的核心资源管理者,线程是用户程序与内核协作的执行单元,句柄是用户程序安全访问内核对象的桥梁。三者通过线程创建过程紧密协作,确保资源的隔离性、安全性和高效管理。

(5)判断下列关于内核对象描述的正误。

  • 内核对象只有 signaled 和 non- signaled 这 2 种状态。(×)
  • 内核对象需要转为 signaled 状态时,需要程序员亲自将内核对象的状态改为 signaled 状态。(×)
  • 线程的内核对象在线程运行时处于 sigaled 状态,线程终止则进入 non-signaled 状态。(×)

(6)请解释“auto-reset模式”和manual-reset模式”的内核对象。区分二者的内核对象特征是什么?

auto-reset 模式:当事件被触发,只有一个等待线程会被唤醒,随后事件自动重置为 non-signaled 状态。如果有多个线程在等待,只有一个线程能继续执行,其余线程继续等待。

manual-reset 模式:当事件被触发,所有等待线程都会被唤醒,事件保持 signaled 状态,直到手动重置为 non- signaled 状态。

选择哪种模式取决于具体需求:是唤醒单个线程还是多个线程。

相关文章:

《TCP/IP网络编程》学习笔记 | Chapter 19:Windows 平台下线程的使用

《TCP/IP网络编程》学习笔记 | Chapter 19&#xff1a;Windows 平台下线程的使用 《TCP/IP网络编程》学习笔记 | Chapter 19&#xff1a;Windows 平台下线程的使用内核对象内核对象的定义内核对象归操作系统所有 基于 Windows 的线程创建进程与线程的关系Windows 中线程的创建方…...

线性规划的基本解、基本可行解和可行解

在线性规划中&#xff0c;基本解、基本可行解和可行解是非常重要的概念&#xff0c;特别是在使用单纯形法求解时。下面详细解释这些概念&#xff0c;并说明如何计算它们。 1. 线性规划问题的标准形式 线性规划的标准形式为&#xff1a; 其中&#xff1a; A 是 mn 的矩阵&…...

【AVRCP】服务发现互操作性:CT 与 TG 的 SDP 协议契约解析

目录 一、服务发现的核心目标&#xff1a;能力画像对齐 二、控制器&#xff08;CT&#xff09;服务记录&#xff1a;控制能力的声明 2.1 必选字段&#xff1a;角色与协议的刚性契约 2.1.1 服务类标识&#xff08;Service Class ID List&#xff09; 2.1.2 协议描述列表&am…...

[从零开始学习JAVA] Stream流

前言&#xff1a; 本文我们将学习Stream流&#xff0c;他就像流水线一样&#xff0c;可以对我们要处理的对象进行逐步处理&#xff0c;最终达到我们想要的效果&#xff0c;是JAVA中的一大好帮手&#xff0c;值得我们了解和掌握。&#xff08;通常和lambda 匿名内部类 方法引用相…...

K8S学习之基础三十八:Kube-static-metrics监控

Kube-static-metrics监控 ​ kube-static-metrics组件可以通过监听apiserver生成有关资源对象的状态指标&#xff0c;比如Node、Pod&#xff0c;需要注意的是kube-state-metrics只是简单的提供一个metrics数据&#xff0c;并不会存储这些指标数据&#xff0c;所以可以使用Prom…...

JAVA-多线程join()等待一个线程

引言&#xff1a;更多线程的认识可以看一篇博客&#xff1a; JAVA-Thread类实现多线程-CSDN博客 一、join()的作用 我们知道线程是随机调度执行的&#xff0c;但是有时候我们需要另一个任务完成了&#xff0c;我们才能继续&#xff0c;这个时候我们就可以使用join去等待线程结束…...

HashMap 常用方法

HashMap 常用方法 方法作用示例put(K key, V value)添加键值对map.put("apple", 10);get(Object key)获取指定键的值map.get("apple"); → 10remove(Object key)删除指定键的键值对map.remove("orange");containsKey(Object key)检查是否包含指…...

LogicFlow介绍

LogicFlow介绍 LogicFlow是一款流程图编辑框架&#xff0c;提供了一系列流程图交互、编辑所必需的功能和灵活的节点自定义、插件等拓展机制。LogicFlow支持前端自定义开发各种逻辑编排场景&#xff0c;如流程图、ER图、BPMN流程等。在工作审批流配置、机器人逻辑编排、无代码平…...

Docker搭建MySQL主从服务器

一、在主机上创建MySQL配置文件——my.cnf master服务器配置文件路径&#xff1a;/data/docker/containers/mysql-cluster-master/conf.d/my.cnf slave服务器配置文件路径&#xff1a; /data/docker/containers/mysql-cluster-master/conf.d/my.cnf master服务配置文件内容 …...

计算机二级web易错点(4)-选择题

选项 A&#xff1a;<input type"radio"> 用于创建单选按钮&#xff0c;同一组单选按钮中只能选择一个选项&#xff0c;所以该选项不符合要求。选项 B&#xff1a;HTML 中没有 type"check" 这种类型&#xff0c;是错误的写法&#xff0c;不能产生复选…...

3.19学习总结

学习了Java中的面向对象的知识点 完成一道算法题&#xff0c;找树左下角的值&#xff0c;错误的以为左下角只能是最底层的左节点&#xff0c;但指的是最底层最左边的节点...

Swagger-告别手写文档

文章目录 1. 引言2. Swagger是什么&#xff1f;3. SpringBoot2.7.3集成Swagger4. 常见注解 1. 引言 在RESTful API开发中&#xff0c;维护准确、易读的接口文档是团队协作的核心挑战&#xff0c;通常接口文档分为离线的和实时的。离线的接口文档工具有 YAPI等&#xff0c;其中…...

LeetCode-回文数

原题链接&#xff1a;9. 回文数 - 力扣&#xff08;LeetCode&#xff09; 首先我会想到的是&#xff0c;将这个数字转成字符串&#xff0c;然后通过前后指针判断是否相等&#xff0c;最终返回结果是否为回文数&#xff0c;时间复杂度&#xff1a;O(n)&#xff0c;空间复杂度&am…...

数据结构之链表(双链表)

目录 一、双向带头循环链表 概念 二、哨兵位的头节点 优点&#xff1a; 头节点的初始化 三、带头双向链表的实现 1.双链表的销毁 2.双链表的打印 3.双链表的尾插和头插 尾插&#xff1a; 头插&#xff1a; 4.双链表的尾删和头删 尾删&#xff1a; 头删&#xff1a; …...

硬件基础(5):(2)二极管分类

文章目录 &#x1f4cc; 二极管的分类与详细介绍1. **整流二极管&#xff08;Rectifier Diode&#xff09;**特点&#xff1a;选型依据&#xff1a;补充说明&#xff1a; 2. **快恢复二极管&#xff08;Fast Recovery Diode&#xff09;**特点&#xff1a;选型依据&#xff1a;…...

MQTT 和 Modbus 的优缺点对比

MQTT和Modbus协议是物联网&#xff08;IoT&#xff09;躲不开的两种协议&#xff0c;市面上覆盖了百分之98的产品。 MQTT由IBM在1999年发布。2014年&#xff0c;MQTT成为OASIS&#xff08;结构化信息标准促进组织&#xff09;的标准&#xff0c;后来被ISO/IEC 20922正式采纳&a…...

Android14 系统左右声音通道设置代码

Android14 系统左右声音通道设置代码 文章目录 Android14 系统左右声音通道设置代码一、前言二、系统级设置左右声音通道分析1、各方案设置左右声音通道的主要代码&#xff08;1&#xff09;3588 Android13 方案的实现&#xff08;2&#xff09;9679 Android14 方案的实现&…...

【Golang】go如何通过atomic原子操作来确保数据一致性

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全…...

2025年汽车加气站操作工考试精选题库

汽车加气站操作工题库中题目及答案&#xff1a; 单项选择题 1、按压力容器的设计压力分为&#xff08; &#xff09;个压力等级。 A. 3 B. 4 C. 5 答案&#xff1a;B 2、缓冲罐的安装位置在天然气压缩机&#xff08; &#xff09;。 A. 前 B. 后 C. 中间 答案&#…...

LLVM学习--外部项目

不包含于核心LLVM和Clang存储库的项目需要单独下载。在本章中&#xff0c;我们将介绍各种其他官方LLVM项目&#xff0c;并介绍如何构建和安装它们。仅仅对核心LLVM工具感兴趣的读者可以跳过本章&#xff0c;或者在需要的时候翻阅。 在本章中&#xff0c;我们将介绍以下项目安装…...

AUTOSAR_DoIP_Detailed

AUTOSAR DoIP模块详解 基于AUTOSAR标准的诊断通信协议实现 目录 架构概述通信流程消息格式配置结构详细序列总结1. 架构概述 1.1 模块架构 DoIP模块是AUTOSAR基础软件中负责诊断通信的核心组件。它通过TCP/IP网络实现诊断工具与ECU之间的通信。主要功能包括: 基础功能 基于UD…...

C语言:(大数相加版)数字阶梯求和

题目&#xff1a; 给定a和n&#xff0c;计算aaaaaaa...a(n个a)的和。 输入 测试数据有多组&#xff0c;输入a&#xff0c;n&#xff08;1<a<9,1<n<100&#xff09;。 输出 对于每组输入,请输出结果。 分析&#xff1a; 1. 方式和规定&#xff1a;大数相加必然越界…...

Echarts 折线图

功能 每月记录值&#xff0c;当数据大于600画红线&#xff0c;小于300画蓝线&#xff0c;其他在中间值为黑线。鼠标移动上去后&#xff0c;现在数据值。 option {tooltip: {trigger: axis, // 触发类型&#xff1a;坐标轴触发show: true, // 显示提示框formatter: function …...

element-plus中Dropdown下拉菜单组件的使用

1、基本使用 复制下面的代码&#xff1a; <!-- 选择查询类型 --> <el-dropdown trigger"click"><span class"el-dropdown-link"><span style"width:60px;color:#404040">查询类型</span><el-icon class"e…...

Kafka详解——介绍与部署

1. 什么是 Kafka&#xff1f; Kafka 是一个分布式的消息队列系统&#xff0c;最初由 LinkedIn 开发&#xff0c;后来成为 Apache 开源项目。它的主要用途包括实时数据处理、日志收集、数据流管道构建等。Kafka 具备高吞吐量、可扩展性、持久性和容错性&#xff0c;广泛应用于大…...

ngx_http_core_srv_conf_t

定义在 src\http\ngx_http_core_module.h typedef struct {/* array of the ngx_http_server_name_t, "server_name" directive */ngx_array_t server_names;/* server ctx */ngx_http_conf_ctx_t *ctx;u_char *file_…...

4.angular 服务

服务是在controller里面引入的服务&#xff1a; 最好是内部服务在前面&#xff0c;自定义服务在后面 内部服务 $scope $scope.$watch(‘属性名’, function(newVal, oldVal) {}, true) true是深度监听,对象函数等$scope.$apply 触发页面更新,里面传入回调函数,比如说之前那个…...

[动手学习深度学习]26. 网络中的网络 NiN

前面的LeNet、AlexNet、VGG在设计上的共同之处在于&#xff1a;先以卷积层构成的模块充分抽取空间特征&#xff0c;再以全连接层构成的模块来输出分类结果 其中AlexNet和VGG对LeNet的改进主要在于如何对这两个模块价款&#xff08;增加通道数&#xff09;和加深 这一节的NiN提出…...

【设计模式】原型模式

三、原型模式 3.2 原型模式 同工厂模式一样&#xff0c;原型(Prototype) 模式也是一种创建型模式。原型模式通过一个对象 (原型对象)克隆出多个一模一样的对象。实际上&#xff0c;该模式与其说是一种设计模式&#xff0c;不如说是 一种创建对象的方法(对象克隆),尤其是创建给…...

力扣题目汇总 使用贪心算法解决问题

贪心算法是一种通过局部最优解来获得全局最优解的算法。它的核心思想是&#xff1a;在每一步中选择当前看起来最优的解&#xff0c;并希望通过一系列局部最优选择最终得到全局最优解。 121.买卖股票的最佳时机 分析&#xff1a; 在每一天求出当前最优的利润&#xff0c;也就…...

Mac下Ollama安装全攻略:开启本地大模型之旅

文章目录 Mac下Ollama安装全攻略&#xff1a;开启本地大模型之旅一、Ollama 是什么功能特点优势应用场景 二、安装前准备&#xff08;一&#xff09;系统要求&#xff08;二&#xff09;硬件要求 三、下载安装包&#xff08;一&#xff09;官网下载&#xff08;二&#xff09;其…...

[HelloCTF]PHPinclude-labs超详细WP-Level 1-FILE协议

源码分析 <?php include("get_flag.php");isset($_GET[wrappers]) ? include("file://".$_GET[wrappers]) : ;highlight_file(__FILE__); ?>第一句 include("get_flag.php");, 使代码包含了 get_flag.php 的内容 大概是生成 Flag 之类的…...

Skia 图形引擎介绍

文章目录 一、Skia 的基本概念1. 定位与作用2. 历史背景 二、Skia 的核心架构1. 模块化设计2. 渲染流程3. 跨平台适配 三、Skia 在 Flutter 中的角色1. 自绘 UI 的核心依赖2. 跨平台一致性3. 性能优化 四、Skia 的性能优势1. 高效的图形处理2. 与原生渲染的对比3. 性能瓶颈 五、…...

构建高可靠NFS存储:自动化挂载保障机制的设计与优势

一、背景与需求场景 在分布式系统或集群架构中&#xff0c;NFS&#xff08;Network File System&#xff09;是跨节点共享存储的经典方案。然而&#xff0c;传统/etc/fstab配置的静态挂载方式存在明显缺陷&#xff1a; 服务启动顺序不可控&#xff0c;网络未就绪时挂载失败临…...

Spring Boot对接twilio发送邮件信息

要在Spring Boot应用程序中对接Twilio发送邮件信息&#xff0c;您可以使用Twilio的SendGrid API。以下是一个简单的步骤指南&#xff0c;帮助您完成这一过程&#xff1a; 1. 创建Twilio账户并获取API密钥 注册一个Twilio账户&#xff08;如果您还没有的话&#xff09;。在Twi…...

如何创建并保存HTML文件?零基础入门教程

原文&#xff1a;如何创建并保存HTML文件&#xff1f;零基础入门教程 | w3cschool笔记 本文将以Windows系统为例&#xff0c;教你用最简单的记事本创建并保存第一个HTML网页。 &#x1f4dd; 第一步&#xff1a;准备工具 文本编辑器&#xff1a;使用系统自带的记事本&#xff…...

vue3 + css 列表无限循环滚动+鼠标移入停止滚动+移出继续滚动

1.动画文件.vue <template><div class"dashboard" click"setFullScreen"><div class"warp-box"><el-scrollbar ref"scrollRef" height"100%" scroll"handelScroll"><div class"…...

C#的简单工厂模式、工厂方法模式、抽象工厂模式

工厂模式是一种创建型设计模式&#xff0c;主要将对象的创建和使用分离&#xff0c;使得系统更加灵活和可维护。常见的工厂模式有简单工厂模式、工厂方法模式和抽象工厂模式&#xff0c;以下是 C# 实现的三个案例&#xff1a; 简单工厂模式 简单工厂模式通过一个工厂类来创建…...

Vue:Vue2和Vue3创建项目的几种常用方式以及区别

前言 Vue.js 和 Element UI 都是用 JavaScript 编写的。 1、Vue.js 是一个渐进式 JavaScript 框架。2、Element UI 是基于 Vue.js 的组件库。3、JavaScript 是这两个项目的主要编程语言。 而Element Plus是基于TypeScript开发的。 一、Vue2 1、基于vuecli工具创建 vue2 …...

C++ list类

C list类 目录 C list类引言1.list的使用1.1 list的构造1.2 list的iterator的使用1.3 list capacity1.4 list element acess1.5 list modifiers 2. list的迭代器失效3. list的模拟实现3.1 List.h文件3.2 List的反向迭代器 4.list与vector的对比 引言 在C标准库中&#xff0c;l…...

LeetCode 热题 100_跳跃游戏(78_55_中等_C++)(贪心算法)

LeetCode 热题 100_跳跃游戏&#xff08;78_55&#xff09; 题目描述&#xff1a;输入输出样例&#xff1a;题解&#xff1a;解题思路&#xff1a;思路一&#xff08;贪心算法&#xff09;&#xff1a; 代码实现代码实现&#xff08;思路一&#xff08;贪心算法&#xff09;&am…...

【Redis】Redis的数据删除(过期)策略,数据淘汰策略。

如果问到&#xff1a;假如Redis的key过期之后&#xff0c;会立即删除吗&#xff1f; 其实就是想问数据删除(过期)策略。 如果面试官问到&#xff1a;如果缓存过多&#xff0c;内存是有限的&#xff0c;内存被占满了怎么办&#xff1f; 其实就是问&#xff1a;数据的淘汰策略。…...

C++和标准库速成(八)——指针、动态数组、const、constexpr和consteval

目录 1. 指针和动态数组1.1 栈和自由存储区1.2 使用指针1.3 动态分配的数组1.4 空指针常量 2. const2.1 const修饰类型2.2 const与指针2.3 使用const保护参数2.4 const方法(建议&#xff09; 3. constexpr4. consteval参考 1. 指针和动态数组 动态内存允许所创建的程序具有在编…...

深入解析 Spring Boot 中的 FailureAnalyzer

深入解析 Spring Boot 中的 FailureAnalyzer 在 Spring Boot 应用中&#xff0c;我们难免会遇到启动失败的情况&#xff0c;而默认的异常信息往往过于复杂&#xff0c;导致排查问题变得困难。Spring Boot 提供了一套强大的 FailureAnalyzer 机制&#xff0c;能够捕获常见的异常…...

20. Excel 自动化:Excel 对象模型

一 Excel 对象模型是什么 Excel对象模型是Excel图形用户界面的层次结构表示&#xff0c;它允许开发者通过编程来操作Excel的各种组件&#xff0c;如工作簿、工作表、单元格等。 xlwings 是一个Python库&#xff0c;它允许Python脚本与Excel进行交互。与一些其他Python库&#x…...

【Matlab GUI】封装matlab GUI为exe文件

注&#xff1a;封装后的exe还是需要有matlab环境才能运行 &#xff08;1&#xff09;安装MCRinstaller.exe文件&#xff0c;在matlab安装目录下的toolbox/compiler/deploy/win64文件夹里 &#xff08;2&#xff09;安装完MCRinstaller.exe&#xff0c;字命令窗口输入&#x…...

ModBus TCP/RTU互转(主)(从)|| Modbus主动轮询下发的工业应用 || 基于智能网关的串口服务器进行Modbus数据收发的工业应用

目录 前言 一、ModBus TCP/RTU互转&#xff08;从&#xff09;及应用|| 1.1 举栗子 二、ModBus TCP/RTU互转&#xff08;主&#xff09; 2.1 举栗子 三、ModBus 主动轮询 3.1 Modbus主动轮询原理 3.2 Modbus格式上传与下发 3.2.1.设置Modbus主动轮询指令 3.2.2 设…...

Linux top 命令详解:从入门到高级用法

Linux top 命令详解&#xff1a;从入门到高级用法 在 Linux 系统中&#xff0c;top 是一个强大的实时监控工具&#xff0c;用于查看系统资源使用情况和进程状态。它可以帮助你快速了解 CPU、内存、负载等信息&#xff0c;是系统管理员和开发者的日常利器。本文将从基本用法开始…...

【网络协议】基于UDP的可靠协议:KCP

TCP是为流量设计的&#xff08;每秒内可以传输多少KB的数据&#xff09;&#xff0c;讲究的是充分利用带宽。而 KCP是为流速设计的&#xff08;单个数据包从一端发送到一端需要多少时间&#xff09;&#xff0c;以10%-20%带宽浪费的代价换取了比 TCP快30%-40%的传输速度。TCP信…...

【Docker入门】构建推送第一个Docker映像

【Docker入门】构建推送第一个Docker映像 Build and Push the First Docker Image By JacksonML Docker的容器(Container)映像是轻量级的可执行独立包&#xff0c;包含代码、运行时、库、环境变量以及配置文件&#xff0c;它对于运行软件至关重要。注册表可在团队间分享映像。…...