《操作系统导论》第27章读书笔记:插叙:线程API

《操作系统导论》第27章读书笔记:插叙:线程API

效果图

效果图

—— 2024-04-21 杭州 上午

本章讲得比较啰嗦,问题是本章的二级标题后面都会作为一个章节来讲,所以本章属于概况介绍类章节,另外这几个并发的章节使用的都是是POSIX线程库…

文章目录

  • 《操作系统导论》第27章读书笔记:插叙:线程API
    • 0.补充笔记:POSIX详解,以及和windows、linux的关系
      • 什么是POSIX?
      • POSIX标准的主要组成部分
      • POSIX标准的优势
      • 如何与非POSIX系统兼容
      • 实际应用
      • 总结1
      • POSIX 与 Linux 的关系
      • POSIX 与 Windows 的关系
      • 总结2
    • 0.补充笔记:POSIX线程API列表
    • 1.线程创建:pthread_create,书里对返回值和参数研究很细
      • 图27.1 代码:创建线程
    • 2.线程完成
      • pthread_join的中文术语
      • "阻塞线程"术语
      • 图27.2 代码:等待线程完成,书里对返回值和参数研究很细
      • 图27.3 代码:较简单的向线程传递参数示例
      • pthread线程中错误地返回栈上分配的局部变量的地址
    • 3.锁
    • 4.条件变量
    • 5.编译和运行、小结
    • 6.补充笔记:pthread_create的第4个参数和pthread_join的第2个参数详解
      • pthread_create 的第四个参数
      • pthread_join 的第二个参数
      • 示例:说明如何从具有返回值的线程函数中获取返回值

0.补充笔记:POSIX详解,以及和windows、linux的关系

什么是POSIX?

POSIX(Portable Operating System Interface)是一个操作系统接口标准,其目的是促进应用程序的可移植性。这一标准由IEEE(电气和电子工程师协会)开发,并被ISO和IEC采纳。POSIX标准定义了应用程序与操作系统之间的一组接口,包括系统调用、命令行工具和实用程序。

POSIX标准的主要组成部分

POSIX标准包括多个部分,主要可以分为以下几个领域:

  1. 系统接口 - 包括文件系统、进程控制、线程、同步机制等。
  2. Shell 和实用工具 - 定义shell行为和常见命令行工具,如awkechosed等。
  3. 用户和组管理 - 包括对用户ID和组ID的管理。
  4. 程序编程接口(API) - 提供了一套标准的C库函数,用于实现系统服务和各种操作系统功能。

POSIX标准的优势

  • 可移植性:程序员可以开发出可在任何支持POSIX的操作系统上运行的应用程序,这包括大多数Unix系统、Linux、BSD变体和MacOS。
  • 兼容性:提供了一致的API,降低了从一个操作系统到另一个操作系统的迁移成本。
  • 标准化:为操作系统设计提供了一套广泛接受的规范,有助于减少开发者在不同系统间迁移和学习的难度。

如何与非POSIX系统兼容

虽然POSIX旨在增强不同操作系统之间的兼容性,但并非所有操作系统都完全符合POSIX标准。例如,Windows就提供了自己的API,与POSIX有所不同。为了在Windows上运行POSIX兼容软件,可以使用如Cygwin这类工具,它提供了一个兼容POSIX标准的环境。

实际应用

在编写跨平台软件时,开发者通常会遵循POSIX标准,以确保软件能在不同的系统上运行。此外,操作系统开发者在设计系统时会尽量遵守POSIX标凈,以确保新系统能够运行已有的大量软件。

总结1

POSIX标准是推动操作系统之间兼容性的重要工具,它通过定义一组广泛接受的API、shell行为和工具,帮助软件开发者在不同的操作系统之间进行更轻松的迁移和开发。尽管存在一些不兼容的情况,POSIX的存在无疑为操作系统的互操作性提供了坚实的基础。

POSIX 与 Linux 的关系

POSIX(Portable Operating System Interface)标准旨在提供一个跨多种操作系统的一致的应用程序接口(API),使软件开发者能够写出可以在多个系统上运行的程序。Linux,作为一个类Unix系统,广泛地支持 POSIX 标准。这包括但不限于系统调用、命令行工具、用户和组管理等。

Linux 的设计初衷之一就是兼容 Unix,因此它实现了大量的 POSIX 接口,使得从其他 Unix-like 系统(如 BSD、Solaris)迁移到 Linux 的过程更为平滑。Linux 的核心组件,如 GNU 工具(bash、gawk 等)和其他基本工具,都遵循 POSIX 标准。因此,绝大多数遵循 POSIX 标准的软件可以在 Linux 上无缝运行,也使得 Linux 成为了众多软件开发者和系统管理员的首选平台。

POSIX 与 Windows 的关系

Windows 操作系统与 POSIX 的关系则较为复杂。Windows 并非一个基于 Unix 的操作系统,因此它的核心架构和 API 与 POSIX 标准相差较远。尽管如此,Microsoft 为了支持需要跨平台兼容性的企业用户,曾经在某些版本的 Windows 中实现了部分 POSIX 接口。

  1. POSIX 子系统:在较旧的 Windows NT 和 Windows 2000 中,Microsoft 提供了一个称为 “POSIX 子系统” 的功能,这允许运行一些基于 POSIX 的应用程序。

  2. Services for UNIX (SFU)Subsystem for UNIX-based Applications (SUA):这些是 Microsoft 提供的更为完整的工具和子系统,旨在提高 Windows 与 UNIX 系统的兼容性。

  3. Windows 10 的 Bash Shell:最近的发展是,Windows 10 引入了一个名为 “Windows Subsystem for Linux (WSL)” 的特性,它允许用户在 Windows 上直接运行 Linux 二进制可执行文件。WSL 是一个兼容层,允许在 Windows 上运行一个完整的 Linux 环境,这提高了对 POSIX 标准的支持。

总结2

  • Linux 与 POSIX:Linux 是 POSIX 标准的忠实实现者之一,它通过支持这些标准,提供了高度的兼容性和可移植性,特别是与其他 Unix-like 系统间。

  • Windows 与 POSIX:虽然 Windows 本身并不是基于 POSIX 构建的,但 Microsoft 提供了多种工具和子系统来支持 POSIX API,以便于某些需要跨平台运行的应用程序能在 Windows 上工作。最近的 WSL 功能大大提高了 Windows 支持 POSIX 应用程序的能力,使其能更好地支持 Linux 应用和工具。

这样的关系揭示了操作系统设计者如何在保持自身系统特性的同时,也尽可能地向标准靠拢,以提高软件的可移植性和操作系统的可用性。

0.补充笔记:POSIX线程API列表

这个表格并不全面,但它涵盖了大部分常用的POSIX线程API的主要功能:

函数名类别描述
pthread_create线程管理创建一个新的线程
pthread_exit线程管理终止调用线程
pthread_join线程管理阻塞调用线程直到指定线程结束
pthread_detach线程管理将线程设置为可分离状态
pthread_self线程管理获取调用线程的线程ID
pthread_equal线程管理比较两个线程ID是否相同
pthread_once线程管理保证某个初始化代码只执行一次
pthread_cancel线程管理请求取消同一进程中的另一个线程
pthread_setcancelstate线程管理设置调用线程的取消状态
pthread_setcanceltype线程管理设置调用线程的取消类型
pthread_mutex_init互斥锁(Mutex)初始化互斥锁
pthread_mutex_destroy互斥锁(Mutex)销毁互斥锁
pthread_mutex_lock互斥锁(Mutex)加锁互斥锁
pthread_mutex_unlock互斥锁(Mutex)解锁互斥锁
pthread_mutex_trylock互斥锁(Mutex)尝试加锁互斥锁,如果锁已被占用则立即返回
pthread_cond_init条件变量初始化条件变量
pthread_cond_destroy条件变量销毁条件变量
pthread_cond_wait条件变量等待条件变量
pthread_cond_signal条件变量单个唤醒等待条件变量的线程
pthread_cond_broadcast条件变量唤醒所有等待条件变量的线程
pthread_rwlock_init读写锁(RW Lock)初始化读写锁
pthread_rwlock_destroy读写锁(RW Lock)销毁读写锁
pthread_rwlock_rdlock读写锁(RW Lock)获取读锁
pthread_rwlock_wrlock读写锁(RW Lock)获取写锁
pthread_rwlock_unlock读写锁(RW Lock)释放读或写锁
pthread_rwlock_tryrdlock读写锁(RW Lock)尝试获取读锁,如果锁已被占用则立即返回
pthread_rwlock_trywrlock读写锁(RW Lock)尝试获取写锁,如果锁已被占用则立即返回
pthread_key_create线程局部存储(TLS)创建一个线程特定数据键
pthread_key_delete线程局部存储(TLS)删除线程特定数据键
pthread_setspecific线程局部存储(TLS)设置与键相关的线程特定数据
pthread_getspecific线程局部存储(TLS)获取与键相关的线程特定数据

1.线程创建:pthread_create,书里对返回值和参数研究很细

图27.1 代码:创建线程

#include <pthread.h>typedef struct myarg_t {int a;int b;
} myarg_t;void *mythread(void *arg) {myarg_t *m = (myarg_t *) arg;printf("%d %d\n", m->a, m->b);return NULL;
}int main(int argc, char *argv[]) {pthread_t p;int rc;myarg_t args;args.a = 10;args.b = 20;rc = pthread_create(&p, NULL, mythread, &args);...
}

在这里插入图片描述

在这里插入图片描述

2.线程完成

pthread_join的中文术语

在中文中,pthread_join 函数通常被称为“线程等待”或“线程合并”。这个函数的作用是调用线程(即执行 pthread_join 的线程)等待指定的线程终止,如果那个线程已经终止,则 pthread_join 会立即返回。这是一个同步操作,确保线程资源的正确回收和线程结束状态的获取。

"阻塞线程"术语

,“阻塞线程”(Blocking Thread)是一个常用的术语。在多线程编程中,当一个线程因为某些条件未被满足(例如等待一个事件发生、等待I/O操作完成、或等待获取锁)而暂停执行,这种状态被称为“阻塞”。阻塞线程将不会消耗CPU资源,它会保持在等待状态直到其等待的条件被满足。

例如,在使用 pthread_join 函数时,如果被等待的线程尚未结束,那么调用 pthread_join的线程会进入阻塞状态,直到被等待的线程结束为止。这就是一个典型的阻塞线程的场景。

图27.2 代码:等待线程完成,书里对返回值和参数研究很细

#include <stdio.h>
#include <pthread.h>
#include <assert.h>
#include <stdlib.h>typedef struct myarg_t {int a;int b;
} myarg_t;typedef struct myret_t {int x;int y;
} myret_t;void *mythread(void *arg) {myarg_t *m = (myarg_t *) arg;printf("%d %d\n", m->a, m->b);myret_t *r = Malloc(sizeof(myret_t));r->x = 1;r->y = 2;return (void *) r;
}int main(int argc, char *argv[]) {int rc;pthread_t p;myret_t *m;myarg_t args;args.a = 10;args.b = 20;Pthread_create(&p, NULL, mythread, &args);Pthread_join(p, (void **) &m);printf("returned %d %d\n", m->x, m->y);return 0;
}

图27.3 代码:较简单的向线程传递参数示例

#include <stdio.h>      // 引入标准输入输出库
#include <pthread.h>    // 引入 POSIX 线程库// 线程函数定义
void *mythread(void *arg) {// 将传入的void*指针转换为int类型int m = (int)arg;// 打印传入的整数printf("%d\n", m);// 将传入的整数加一后,转换为void*指针返回return (void *)(arg + 1);
}// 主函数
int main(int argc, char *argv[]) {pthread_t p;  // 定义线程的IDint rc, m;    // 定义接收线程返回值的变量// 创建线程,传入数字100作为参数// 这里有一个错误,函数名应该是小写的pthread_createPthread_create(&p, NULL, mythread, (void *)100);// 等待线程结束,并获取线程返回值// 这里有一个错误,函数名应该是小写的pthread_joinPthread_join(p, (void **)&m);// 打印线程返回的值printf("returned %d\n", m);return 0; // 程序正常退出
}

pthread线程中错误地返回栈上分配的局部变量的地址

图片中的文本包含了一个C语言编写的多线程示例代码,它演示了如何在pthread线程中错误地返回栈上分配的局部变量的地址。这是一个常见的错误,因为栈上的数据在函数返回后可能会被覆盖,导致未定义行为。

代码中定义了一个线程函数mythread,它打印出传入结构体的两个成员变量的值,并试图返回一个在栈上分配的结构体变量的地址。注释中指出这样做是错误的(BAD!)。

下面是图片中代码的Markdown格式:

#include <stdio.h>
#include <pthread.h>typedef struct {int a;int b;
} myarg_t;typedef struct {int x;int y;
} myret_t;void *mythread(void *arg) {myarg_t *m = (myarg_t *) arg;printf("%d %d\n", m->a, m->b);myret_t r; // ALLOCATED ON STACK: BAD!r.x = 1;r.y = 2;return (void *) &r;
}// ... (其他代码可能在这里)int main(int argc, char *argv[]) {pthread_t p;myarg_t args = {10, 20};myret_t *result;pthread_create(&p, NULL, mythread, &args);pthread_join(p, (void **) &result);printf("%d %d\n", result->x, result->y);return 0;
}// ... (其他代码可能在这里)

这段代码试图创建一个线程,然后等待线程结束,并打印线程函数返回的结构体中的值。但是,由于返回的是栈上分配的局部变量的地址,这段代码在执行时会有问题。返回的指针可能指向不再有效的内存,因为当mythread函数返回时,r变量所占用的栈空间可能会被用于其他目的。

图片下方的文本警告说这是一个严重错误,并指出在这个函数返回后,r变量的内存可能会被其他线程或函数调用覆盖。它还提到了第27.3条,这可能是某个文档或书籍中的一条规则,但没有更多的上下文信息,无法确定其具体含义。

最后,图片下方的文本建议使用gcc编译器的-Wall选项来编译代码,以便发现潜在的问题。-Wall选项会启用编译器的大多数警告,帮助开发者找到可能的代码错误。

在这里插入图片描述

在这里插入图片描述

3.锁

在这里插入图片描述

在这里插入图片描述

4.条件变量

最后一点需要注意:等待线程在while循环中重新检查条件,而不是简单的if语句。在后续章节中研究条件变量时,我们会详细讨论这个问题,但是通常使用while循环是一件简单而安全的事情。虽然它重新检查了这种情况(可能会增加一点开销),但有一些pthread实现可能会错误地唤醒等待的线程。在这种情况下,没有重新检查,等待的线程会继续认为条件已经改变。因此,将唤醒视为某种事物可能已经发生变化的暗示,而不是绝对的事实,这样更安全。

在这里插入图片描述

5.编译和运行、小结

在这里插入图片描述

6.补充笔记:pthread_create的第4个参数和pthread_join的第2个参数详解

pthread_createpthread_join 是 POSIX 线程(pthread)库中的两个基本函数,用于在 C 或 C++ 程序中创建和管理线程。下面我们将详细解释这两个函数中的特定参数。

pthread_create 的第四个参数

pthread_create 函数用于创建一个新的线程。其函数原型如下:

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);
  • 第四个参数 (void *arg): 这是一个 void 指针,用于传递给线程启动函数(start_routine)的单个参数。这允许用户向线程函数传递数据。由于它是一个类型为 void * 的指针,它可以指向任何类型的数据,从而使得该函数可以接收各种类型的参数。

    例如,若要传递一个整数或结构体给线程,你可以传递指向这些数据的指针。在线程函数中,你需要将这个 void * 指针转换回原始类型的指针,以便正确处理数据。

pthread_join 的第二个参数

pthread_join 函数用于等待指定的线程终止。其函数原型如下:

int pthread_join(pthread_t thread, void **retval);
  • 第二个参数 (void **retval): 这是一个指向 void * 的指针,用于接收线程通过 pthread_exit 调用或从线程函数返回的退出状态。如果线程成功返回并且这个参数不是 NULL,则这个位置将被更新为指向线程的返回值。

    这个参数给调用者提供了一种方式来获取线程结束时返回的数据,这非常有用,例如,当线程执行完成一些计算并需要返回结果时。如果不关心返回值,可以将此参数设置为 NULL

在使用 pthread_create 创建线程时,你可以让线程函数返回一个值,这个值可以通过 pthread_join 的第二个参数来接收。这是一个非常常见的用法,用于从线程中获取计算结果或状态。

线程函数的返回值类型是 void *,这意味着它可以返回指向任何类型数据的指针。当线程函数退出时,它返回的指针可以通过 pthread_join 调用中的第二个参数获取。

示例:说明如何从具有返回值的线程函数中获取返回值

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>// 线程函数
void *thread_func(void *arg) {int *input = (int *)arg;int *result = malloc(sizeof(int));  // 分配内存以存储结果*result = (*input) * 2;  // 计算结果,这里简单地将输入值乘以2// 直接从函数返回result,相当于pthread_exit(result);return result;
}int main() {pthread_t thread;int value = 10;// 创建线程,传递value的地址pthread_create(&thread, NULL, thread_func, &value);// 等待线程结束,并接收返回值void *retval;pthread_join(thread, &retval);// 输出线程返回的结果printf("Thread returned: %d\n", *(int *)retval);// 释放由线程分配的内存free(retval);return 0;
}

在这个例子中,thread_func 函数计算传入值的两倍,并将结果存储在动态分配的内存中。它直接从函数返回这个内存地址,这与调用 pthread_exit 并传递这个地址是等同的。

在主函数中,我们使用 pthread_join 来等待线程结束并接收它的返回值。pthread_join 的第二个参数 &retval 接收线程函数返回的指针。然后我们可以使用这个指针访问线程计算的结果,并在最后负责释放这段内存。

这种方式非常灵活,可以通过线程返回指针来传递结构体、数组或任何其他类型的数据,只要确保调用线程(这里是 main 函数中的代码)负责适当地管理这些数据(例如释放内存)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/1489.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【python】启动一个公司级项目的完整报错和解决方案

启动一个项目对于新手都是不容易的事情 操作 打开项目 使用pyCharm打开python项目以后&#xff0c;先找main方法&#xff0c;一般在根目录有一个.py的文件 点进去以后会让你配置Python解释器 每个项目都有自己的一个虚拟环境&#xff0c;配置自己的解释器&#xff0c;可能…

windows驱动开发-设备栈

设备栈是windows内核中非常重要的部分&#xff0c;这部分理解可以让我们在调试中节省大量的时间&#xff0c; 在windows NT体系中&#xff0c;内核所有的设备被按照连接次序加载到设备树上&#xff0c;这棵树的根节点是ROOT节点&#xff0c;每一个设备可以从当前路径一直遍历到…

QMT和Ptrade有什么区别?该如何选择?

QMT&#xff08;Quantitative Model Trading&#xff09;和Ptrade&#xff08;Professional Trading&#xff09;是两种不同的交易策略和方法&#xff0c;它们在金融市场中被广泛应用。了解它们的区别有助于投资者根据自己的需求和目标做出选择&#xff1a; QMT&#xff08;量…

将记录从excel当中导出为.sql文件,再新增到数据库

一、背景 临时遇到了一个需求&#xff0c;比如根据人员的名字查询对应记录&#xff0c;看起来还是很简单的&#xff0c;直接用select查询就可以&#xff0c;然而如果此时存在以下情况&#xff1a; 数据库根本就没有人员信息表&#xff1b;------这个倒是好操作&#xff1b;现…

AlDente Pro for mac最新激活版:电池长续航软件

AlDente Pro是一款专为Mac用户设计的电池管理工具&#xff0c;旨在提供电池安全和健康管理的一站式解决方案。它具备实时监控电池状态的功能&#xff0c;让用户随时了解电池的电量、充电次数、健康状态等信息。 AlDente Pro for mac最新激活版下载 同时&#xff0c;AlDente Pro…

分类预测 | Matlab实现CNN-LSTM-SAM-Attention卷积长短期记忆神经网络融合空间注意力机制的数据分类预测

分类预测 | Matlab实现CNN-LSTM-SAM-Attention卷积长短期记忆神经网络融合空间注意力机制的数据分类预测 目录 分类预测 | Matlab实现CNN-LSTM-SAM-Attention卷积长短期记忆神经网络融合空间注意力机制的数据分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Mat…

Vue3 + Js + Element-Plus + VueX后台管理系统通用解决方案

前言 本文是作为学习总结而写的一篇文章&#xff0c;也是方便以后有相关需求&#xff0c;可以直接拿来用&#xff0c;也算是记录吧&#xff0c;文中有一些文件的引入&#xff0c;没给出来&#xff0c;完整项目地址&#xff08;后续代码仓库放这里&#xff09; 1、layout解决方…

【Python性能优化】list、array与set

list、array与set 详述测试代码 详述 本文对比 list 与 set 在插入和取值时的性能差异&#xff0c;以提供一条什么时候该选择什么数据类型的建议。先上结果&#xff1a; array 与 list 的不同&#xff1a; 内存方面 array 是 C array 的包装&#xff0c;它直接存储数据&#xf…

【002_音频开发_基础篇_Linux音频架构简介】

002_音频开发_基础篇_Linux音频架构简介 文章目录 002_音频开发_基础篇_Linux音频架构简介创作背景Linux 音频架构ALSA 简介ASoC 驱动硬件架构软件架构MachinePlatformCodec ASoC 驱动 PCMALSA设备文件结构 ALSA 使用常用概念alsa-libALSA Open 流程ALSA Write 流程2种写入方法…

Eclipse+Java+Swing实现学生信息管理系统-TXT存储信息

一、系统介绍 1.开发环境 操作系统&#xff1a;Win10 开发工具 &#xff1a;Eclipse2021 JDK版本&#xff1a;jdk1.8 存储方式&#xff1a;Txt文件存储 2.技术选型 JavaSwingTxt 3.功能模块 4.工程结构 5.系统功能 1.系统登录 管理员可以登录系统。 2.教师-查看学生…

打破国外垄断|暴雨发布纯血国产电脑

要说现在国产手机这边已然进入纯自研模式&#xff0c;但电脑这边却还是仍未打破国外技术垄断。但就在刚刚&#xff0c;暴雨发布自研架构台式机open Station X &#xff0c;这是纯血鸿蒙系统之后国产又一款纯血产品发布&#xff01;标志的我们已经彻底打破西方在硬件及软件方面的…

c++ - 空间申请和释放 new/delete

文章目录 一、c/c内存分布二、new/delete 的使用三、malloc/free 和 new/delete 的对比四、new/delete 的实现原理五、匹配问题 一、c/c内存分布 求下面各个变量的位置 // c/c内存分布int globalVar 1; static int staticGlobalVar 1; void Test() {static int staticVar …

PyTorch与深度学习:探索现代神经网络的魅力

在科技飞速发展的今天&#xff0c;深度学习作为人工智能领域的重要分支&#xff0c;已经在图像识别、自然语言处理、语音识别等多个领域取得了突破性的进展。而PyTorch&#xff0c;作为一款开源的深度学习框架&#xff0c;以其简洁易用、动态计算图等特性&#xff0c;赢得了广大…

Django中间件的源码解析流程(上)——中间件载入的前置

目录 1. ​前言​ 2. 请求的入口 3. 中间件加载的入口 4. 源码中的闭包实现 5. 最后 1. 前言 哈喽&#xff0c;大家好&#xff0c;我是小K,今天咋们分享的内容是&#xff1a;在学会Django中间件之后&#xff0c; 我们继续深入底层源码。 在执行中间件时请求到来总是从前往后…

ChatGPT研究论文提示词集合3-【数据收集】、【数据分析】和【解释与讨论】

点击下方▼▼▼▼链接直达AIPaperPass &#xff01; AIPaperPass - AI论文写作指导平台 目录 1.数据收集 2.数据分析 3.讨论与解释 4.书籍介绍 AIPaperPass智能论文写作平台 近期小编按照学术论文的流程&#xff0c;精心准备一套学术研究各个流程的提示词集合。总共14个步…

【IDEA】用idea导入eclipse的项目后,提示:The file was loaded in a wrong encoding ‘utf-8‘

前言 最近用IDEA导入一个exlipse项目后&#xff0c;窗口出现这个红色提示&#xff1a; 可以项目中的中文&#xff0c;包括注释都是乱码&#xff0c;要解决问题就跟我开始做吧。 一定要看仔细在操作&#xff01; 一定要看仔细在操作&#xff01; 一定要看仔细在操作&#xf…

rmallox勒索病毒威胁网络安全:如何避免数据被锁定

尊敬的读者&#xff1a; 随着信息技术的飞速发展&#xff0c;网络空间的安全问题日益凸显。近年来&#xff0c;一种名为.rmallox的勒索病毒频繁出没&#xff0c;给广大计算机用户带来了严重的困扰。本文将对该病毒进行深入剖析&#xff0c;并探讨相应的应对策略。在面对被勒索…

飞书API(5):查看多维表 28 种数据类型的数据结构

一、引入 前面我们用于测试的数据集其实都是比较常用的数据&#xff0c;比如说文本、数字、单选等&#xff0c;但飞书多维表并不仅仅只有这些数据&#xff0c;截止发文&#xff0c;飞书多维表应用上支持28种数据类型&#xff0c;在数据层面飞书官方只提供了23种数据类型&#…

微信小程序vue.js+uniapp服装商城销售管理系统nodejs-java

本技术是java平台的开源应用框架&#xff0c;其目的是简化Sping的初始搭建和开发过程。默认配置了很多框架的使用方式&#xff0c;自动加载Jar包&#xff0c;为了让用户尽可能快的跑起来spring应用程序。 SpinrgBoot的主要优点有&#xff1a; 1、为所有spring开发提供了一个更快…

AI 智能工具以及热门AI开源项目整理,包含国内中科院版GPT

AI 智能工具以及热门AI开源项目整理&#xff0c;包含国内中科院版GPT。 不用xx即可访问的镜像网站 https://chat1.yqcloud.top https://chat.bnu120.space https://chat.aidutu.cn https://hzdjs.cn/chatgpt https://chats.fenqubiao.com/zh 需要xx才能访问的网站 https://o…