Minio 是一个基于Apache License v2.0开源协议的对象存储服务。它可以运行在多种操作系统上,包括 Linux 和 Windows 等。

它兼容亚马逊S3云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从几kb到最大5TB不等。

Minio官网:https://min.io/

中文地址:https://www.minio.org.cn

中文文档:https://www.minio.org.cn/docs/minio/linux/index.html

演示:https://play.minio.org.cn 用户名:minioadmin、密码minioadmin

MinIO Linux 安装

单节点部署

Download: https://www.minio.org.cn/download.shtml#/linux

使用以下命令下载安装最新版本的稳定 MinIO二进制包, 并设置 $PATH :

[root@localhost ~]# wget https://dl.minio.org.cn/server/minio/release/linux-amd64/minio
[root@localhost ~]# chmod +x minio
[root@localhost ~]# sudo mv minio /usr/local/bin/

创建 systemd 系统启动服务文件

创建 minio.service 启动文件,确保文件在 /usr/lib/systemd/system/minio.service

[root@localhost ~]# vi /usr/lib/systemd/system/minio.service

minio.service

[Unit]
Description=MinIO
Documentation=https://min.io/docs/minio/linux/index.html
Wants=network-online.target
After=network-online.target
AssertFileIsExecutable=/usr/local/bin/minio [Service]
WorkingDirectory=/usr/local User=minio-user
Group=minio-user
ProtectProc=invisible EnvironmentFile=-/etc/default/minio
ExecStartPre=/bin/bash -c "if [ -z \"${MINIO_VOLUMES}\" ]; then echo \"Variable MINIO_VOLUMES not set in /etc/default/minio\"; exit 1; fi"
ExecStart=/usr/local/bin/minio server $MINIO_OPTS $MINIO_VOLUMES # MinIO RELEASE.2023-05-04T21-44-30Z adds support for Type=notify (https://www.freedesktop.org/software/systemd/man/systemd.service.html#Type=)
# This may improve systemctl setups where other services use `After=minio.server`
# Uncomment the line to enable the functionality
# Type=notify # Let systemd restart this service always
Restart=always # Specifies the maximum file descriptor number that can be opened by this process
LimitNOFILE=65536 # Specifies the maximum number of threads this process can create
TasksMax=infinity # Disable timeout logic and wait until process is stopped
TimeoutStopSec=infinity
SendSIGKILL=no [Install]
WantedBy=multi-user.target # Built for ${project.name}-${project.version} (${project.name})

默认情况下, minio.service 文件以 minio-user 用户和组的身份运行。 您可以使用 groupadduseradd 创建用户和组。 命令。下面的示例创建了用户和组,并设置了权限 来访问供 MinIO 使用的文件夹路径。这些命令通常 需要 root ( sudo ) 权限。

[root@localhost ~]# groupadd -r minio-user
[root@localhost ~]# useradd -M -r -g minio-user minio-user
# 存储路径
[root@localhost ~]# chown minio-user:minio-user /mnt/data
chown: 无法访问"/mnt/data": 没有那个文件或目录
[root@localhost ~]# mkdir /mnt/data
[root@localhost ~]# chown minio-user:minio-user /mnt/data

本例中的驱动器路径由 MINIO_VOLUMES 环境变量指定。更改此处和环境变量文件中的值,使其与 MinIO 打算使用的驱动器路径相匹配。

创建环境变量文件

/etc/default/minio 创建环境变量文件。 MinIO 服务器容器可以将此文件作为所有 environment variables

下面的示例提供了一个起始环境文件:

密码不能小于8个字符, 否则无法启动

[root@localhost ~]# vi /etc/default/minio
# MINIO_ROOT_USER and MINIO_ROOT_PASSWORD sets the root account for the MinIO server.
# This user has unrestricted permissions to perform S3 and administrative API operations on any resource in the deployment.
# Omit to use the default values 'minioadmin:minioadmin'.
# MinIO recommends setting non-default values as a best practice, regardless of environment
# 用户名长度不能小于3个字符
MINIO_ROOT_USER=admin
# 密码不能小于8个字符, 否则无法启动
MINIO_ROOT_PASSWORD=minioadmin # MINIO_VOLUMES sets the storage volume or path to use for the MinIO server. MINIO_VOLUMES="/mnt/data" # MINIO_OPTS sets any additional commandline options to pass to the MinIO server.
# For example, `--console-address :9001` sets the MinIO Console listen port
MINIO_OPTS="--console-address :9001"

启动MinIO服务

启动 MinIO SNSD 部署即服务:

[root@localhost ~]# sudo systemctl start minio.service

使用以下命令确认服务是否在线和功能正常:

[root@localhost ~]# sudo systemctl status minio.service
[root@localhost ~]# journalctl -f -u minio.service

自启动,将进程作为主机引导的一部分,在服务器重启的过程中该进程会自动重启,而不用再进行手动管理。

[root@localhost ~]# sudo systemctl enable minio.service

连接到MinIO服务

浏览器中输入:http://localhost:9001

登录MinIO的用户名和密码配置参数为 MINIO_ROOT_USERMINIO_ROOT_PASSWORD 这些配置可以在在容器指定的环境文件中进行修改。





您可以使用MinIO控制台进行一般管理任务,如身份和访问管理、指标和日志监控或服务器配置。每个MinIO服务器都包含其自己的嵌入式MinIO控制台。 如果您的本地主机防火墙允许外部访问控制台端口,则同一网络上的其他主机可以使用您的本地主机的IP地址或主机名访问控制台。

SpringBoot项目整合MinIO

https://mvnrepository.com/artifact/io.minio/minio

配置项

添加依赖

<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.5.10</version>
</dependency>

application.yml 配置 minio


spring:
mvc:
hiddenmethod:
filter:
enabled: true
#设置文件上传大小限制
servlet:
multipart:
max-file-size: -1 #设置单个文件的大小 -1表示不限制
max-request-size: -1 #单次请求的文件的总大小 -1表示不限制 minio:
endpoint: http://172.16.3.195:9000
accessKey: admin
secretKey: minioadmin
bucketName: vipsoft-devminioadmin

MinioConfig.java

package com.vipsoft.oss.config;

import io.minio.MinioClient;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; @Configuration
@ConfigurationProperties(prefix = "minio")
public class MinioConfig {
/**
* 服务地址:http://172.16.3.195:9000
*/
private String endpoint; /**
* 用户名
*/
private String accessKey; /**
* 密码
*/
private String secretKey; /**
* 存储桶名称
*/
private String bucketName; @Bean
public MinioClient getMinioClient() {
MinioClient minioClient = MinioClient.builder().endpoint(endpoint)
.credentials(accessKey, secretKey)
.build();
return minioClient;
} //todo 省去 getter & setter
}

工具类

MinioUtil.java

package com.vipsoft.oss.util;

import cn.hutool.core.io.IoUtil;
import com.cuwor.oss.config.MinioConfig;
import io.minio.*;
import io.minio.MinioClient;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import io.minio.messages.DeleteError;
import io.minio.messages.DeleteObject;
import io.minio.messages.Item;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile; import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit; @Component
public class MinioUtil { @Autowired
private MinioClient minioClient; @Autowired
private MinioConfig minioConfig; private static final int DEFAULT_EXPIRY_TIME = 7 * 24 * 3600; /**
* 判断bucket是否存在
*/
public boolean bucketExists(String bucketName) {
boolean exists;
try {
exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
} catch (Exception e) {
e.printStackTrace();
exists = false;
}
return exists;
} /**
* 创建存储桶,存在则不创建
*/
public boolean makeBucket(String bucketName) {
boolean exists;
try {
exists = bucketExists(bucketName);
if (!exists) {
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
exists = true;
}
} catch (Exception e) {
e.printStackTrace();
exists = false;
}
return exists;
} /**
* 删除存储桶 -- 有文件,不让删除
*
* @param bucketName 存储桶名称
* @return boolean
*/
public boolean removeBucket(String bucketName) {
try {
boolean flag = bucketExists(bucketName);
if (flag) {
Iterable<Result<Item>> myObjects = listObjects(bucketName);
for (Result<Item> result : myObjects) {
Item item = result.get();
// 有对象文件,则删除失败
if (item.size() > 0) {
return false;
}
}
// 删除存储桶,注意,只有存储桶为空时才能删除成功。
minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
flag = bucketExists(bucketName);
if (!flag) {
return true;
}
}
return false;
} catch (Exception e) {
e.printStackTrace();
return false;
}
} /**
* 列出存储桶中的所有对象
*
* @param bucketName 存储桶名称
* @return Iterable<Result < Item>>
*/
public Iterable<Result<Item>> listObjects(String bucketName) {
boolean flag = bucketExists(bucketName);
if (flag) {
return minioClient.listObjects(ListObjectsArgs.builder().bucket(bucketName).build());
}
return null;
} /**
* 列出所有存储桶名称
*
* @return List<String>
*/
public List<String> listBucketNames() {
List<String> bucketListName = new ArrayList<>();
try {
List<Bucket> bucketList = minioClient.listBuckets();
for (Bucket bucket : bucketList) {
bucketListName.add(bucket.name());
}
} catch (Exception e) {
e.printStackTrace();
}
return bucketListName;
} /**
* 列出存储桶中的所有对象名称
*
* @param bucketName 存储桶名称
* @return List<String>
*/
public List<String> listObjectNames(String bucketName) {
List<String> listObjectNames = new ArrayList<>();
try {
boolean flag = bucketExists(bucketName);
if (flag) {
Iterable<Result<Item>> myObjects = listObjects(bucketName);
for (Result<Item> result : myObjects) {
Item item = result.get();
listObjectNames.add(item.objectName());
}
}
} catch (Exception e) {
e.printStackTrace();
}
return listObjectNames;
} /**
* 获取对象的元数据
*
* @param objectName 存储桶里的对象名称
* @return
*/
public StatObjectResponse statObject(String objectName) {
StatObjectResponse statObject = null;
try {
statObject = minioClient.statObject(StatObjectArgs.builder().bucket(minioConfig.getBucketName()).object(objectName).build());
} catch (Exception e) {
e.printStackTrace();
}
return statObject;
} //region 上传文件 /**
* 上传文件
*
* @param file 文件
* @param objectName 文件名称
*/
public boolean uploadObject(MultipartFile file, String objectName) {
// 使用putObject上传一个文件到存储桶中。
try {
InputStream inputStream = file.getInputStream();
minioClient.putObject(PutObjectArgs.builder()
.bucket(minioConfig.getBucketName())
.object(objectName)
.stream(inputStream, file.getSize(), -1)
.contentType(file.getContentType())
.build());
IoUtil.close(inputStream);
// return StrUtil.format("{}/{}/{}", minioConfig.getEndpoint(), minioConfig.getBucketName(), objectName);
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
} /**
* 通过InputStream上传对象
*
* @param objectName 存储桶里的对象名称
* @param inputStream 要上传的流
* @param contentType 上传的文件类型 例如 video/mp4 image/jpg
* @return boolean
*/
public boolean uploadObject(InputStream inputStream, String objectName, String contentType) {
try {
minioClient.putObject(PutObjectArgs.builder().bucket(minioConfig.getBucketName()).object(objectName).stream(
//不清楚文件的大小时,可以传-1,10485760。如果知道大小也可以传入size,partsize。
inputStream, -1, 10485760)
.contentType(contentType)
.build());
IoUtil.close(inputStream);
StatObjectResponse statObject = statObject(objectName);
if (statObject != null && statObject.size() > 0) {
return true;
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
} /**
* 通过文件上传到对象
*
* @param objectName 存储桶里的对象名称
* @param fileName File name
* @return boolean
*/
public boolean uploadObject(String objectName, String fileName) {
try {
minioClient.uploadObject(UploadObjectArgs.builder()
.bucket(minioConfig.getBucketName())
.object(objectName)
.filename(fileName)
.build());
StatObjectResponse statObject = statObject(objectName);
if (statObject != null && statObject.size() > 0) {
return true;
}
} catch (Exception e) {
e.printStackTrace();
} return false;
} //endregion /**
* 获取文件访问地址
*
* @param fileName 文件名称
*/
public String getPresignedObjectUrl(String fileName) {
try {
return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket(minioConfig.getBucketName())
.object(fileName)
.build()
);
} catch (Exception e) {
e.printStackTrace();
}
return null;
} public String getObjectUrl(String objectName) {
String url = "";
try {
url = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket(minioConfig.getBucketName())
.object(objectName)
.build()); } catch (Exception e) {
e.printStackTrace();
}
return url;
} /**
* 生成一个给HTTP GET请求用的presigned URL。
* 浏览器/移动端的客户端可以用这个URL进行下载,即使其所在的存储桶是私有的。这个presigned URL可以设置一个失效时间,默认值是7天。
*
* @param objectName 存储桶里的对象名称
* @param expires 失效时间(以小时单位),默认是7天,不得大于七天
* @return
*/
public String getObjectUrl(String objectName, Integer expires) {
String url = "";
try {
if (expires < 1 || expires > DEFAULT_EXPIRY_TIME) {
throw new Exception("Expires must be in range of 1 to " + DEFAULT_EXPIRY_TIME);
}
url = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket(minioConfig.getBucketName())
.object(objectName)
.expiry(expires, TimeUnit.HOURS)//动态参数
// .expiry(24 * 60 * 60)//用秒来计算一天时间有效期
// .expiry(1, TimeUnit.DAYS)//按天传参
// .expiry(1, TimeUnit.HOURS)//按小时传参数
.build()); } catch (Exception e) {
e.printStackTrace();
}
return url;
} /**
* 下载文件,通过 HttpServletResponse 返回
*
* @param objectName 存储桶里的对象名称
*/
public void downloadObject(HttpServletResponse response, String objectName) {
try {
InputStream file = minioClient.getObject(GetObjectArgs.builder()
.bucket(minioConfig.getBucketName())
.object(objectName)
.build());
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(objectName, "UTF-8"));
ServletOutputStream servletOutputStream = response.getOutputStream();
int len;
byte[] buffer = new byte[1024];
while ((len = file.read(buffer)) > 0) {
servletOutputStream.write(buffer, 0, len);
}
servletOutputStream.flush();
file.close();
servletOutputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
} /**
* 下载并将文件保存到本地
*
* @param objectName 存储桶里的对象名称
* @param fileName 下载保存的文件名
* @return boolean
*/
public boolean downloadObject(String objectName, String fileName) {
try {
StatObjectResponse statObject = statObject(objectName);
if (statObject != null && statObject.size() > 0) {
minioClient.downloadObject(DownloadObjectArgs.builder()
.bucket(minioConfig.getBucketName())
.object(objectName)
.filename(fileName)
.build());
return true;
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
} /**
* 以流的形式获取一个文件对象
*
* @param bucketName 存储桶名称
* @param objectName 存储桶里的对象名称
* @return InputStream
*/
public InputStream getObject(String bucketName, String objectName) {
try {
StatObjectResponse statObject = statObject(objectName);
if (statObject != null && statObject.size() > 0) {
InputStream stream = minioClient.getObject(GetObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.build());
return stream;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
} /**
* 以流的形式获取一个文件对象(断点下载)
*
* @param bucketName 存储桶名称
* @param objectName 存储桶里的对象名称
* @param offset 起始字节的位置
* @param length 要读取的长度 (可选,如果无值则代表读到文件结尾)
* @return InputStream
*/
public InputStream getObject(String bucketName, String objectName, long offset, Long length) {
try {
StatObjectResponse statObject = statObject(objectName);
if (statObject != null && statObject.size() > 0) {
InputStream stream = minioClient.getObject(GetObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.offset(1024L)
.length(4096L)
.build());
return stream;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
} /**
* 删除一个对象
*
* @param objectName 存储桶里的对象名称
*/
public boolean removeObject(String objectName) {
try {
minioClient.removeObject(RemoveObjectArgs.builder().bucket(minioConfig.getBucketName()).object(objectName).build());
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
} /**
* 删除指定桶的多个文件对象,返回删除错误的对象列表,全部删除成功,返回空列表
*
* @param bucketName 存储桶名称
* @param objectNames 含有要删除的多个object名称的迭代器对象 eg:
* List<DeleteObject> objects = new LinkedList<>();
* objects.add(new DeleteObject("my-objectname1"));
* objects.add(new DeleteObject("my-objectname2"));
* objects.add(new DeleteObject("my-objectname3"));
* @return 如果有值,说明当前文件删除失败
*/
public List<String> removeObjects(String bucketName, List<DeleteObject> objectNames) {
List<String> deleteErrorNames = new ArrayList<>();
try {
Iterable<Result<DeleteError>> results = minioClient.removeObjects(RemoveObjectsArgs.builder().bucket(bucketName).objects(objectNames).build());
for (Result<DeleteError> result : results) {
DeleteError error = result.get();
deleteErrorNames.add(error.objectName());
}
} catch (Exception e) {
e.printStackTrace();
}
return deleteErrorNames;
}
}

测试

package com.vipsoft.admin;

import cn.hutool.core.util.StrUtil;
import com.cuwor.oss.util.MinioUtil;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.util.Assert; @SpringBootTest
public class MinioTest { Logger logger = LoggerFactory.getLogger(this.getClass()); @Autowired
private MinioUtil minioUtil; @Test
void makeBucketTest() {
boolean flag = minioUtil.makeBucket("public");
Assert.isTrue(flag, "查询异常");
} @Test
void uploadObjectTest() {
boolean flag = minioUtil.uploadObject("/avatar/123.png", "D:\\Users\\Pictures\\R-C.png");
Assert.isTrue(flag, "上传异常");
} @Test
void getObjectUrlTest() {
String objectName="/avatar/123.png";
String url = minioUtil.getObjectUrl(objectName);
logger.info("url:{}", url);
url = minioUtil.getObjectUrl(objectName, 3);
logger.info("expires url:{}", url);
Assert.isTrue(StrUtil.isNotEmpty(url), "上传异常");
}
}

MinIO Linux 安装使用 & SpringBoot整合MinIO的更多相关文章

  1. SpringBoot整合MinIO

    今天因为公司的需求接触到这个东西,我们先来看下MinIO的官网简介 MinIO 是一个基于Apache License v2.0开源协议的对象存储服务.它兼容亚马逊S3云存储服务接口,非常适合于存储大 ...

  2. SpringBoot 整合MinIO

    引入依赖 <dependency> <groupId>io.minio</groupId> <artifactId>minio</artifact ...

  3. 第2-1-5章 docker安装MinIO实现文件存储服务-springboot整合minio-minio全网最全的资料

    目录 1. MinIO介绍 2. MinIO应用场景 2.1 单主机单硬盘模式 2.2 单主机多硬盘模式 2.3 多主机多硬盘分布式 3. MinIO特点 4. 存储机制 5. docker安装Min ...

  4. Linux安装Minio

    Linux安装Minio 一.安装包方式安装 1.下载minio 1.1 手动下载:https://docs.min.io/docs/minio-quickstart-guide.html ​ 访问上 ...

  5. SpringBoot整合RabbitMQ-服务安装

    本系列是学习SpringBoot整合RabbitMQ的练手,包含服务安装,RabbitMQ整合SpringBoot2.x,消息可靠性投递实现等三篇博客. 学习路径:https://www.imooc. ...

  6. SpringBoot2 整合MinIO中间件,实现文件便捷管理

    本文源码:GitHub·点这里 || GitEE·点这里 一.MinIO简介 1.基础描述 MinIO是一个开源的对象存储服务.适合于存储大容量非结构化的数据,例如图片.视频.日志文件.备份数据和容器 ...

  7. 二、Windows安装与简单使用MinIO

    MinIO的官方网站非常详细,以下只是本人学习过程的整理 一.MinIO的基本概念 二.Windows安装与简单使用MinIO 三.Linux部署MinIO分布式集群 四.C#简单操作MinIO 一. ...

  8. RabbitMQ从概念到使用、从Docker安装到RabbitMQ整合Springboot【1.5w字保姆级教学】

    @ 目录 一.前言 二.RabbitMQ作用 1. 异步处理 2. 应用解耦 3. 流量控制 三.RabbitMQ概念 1. RabbitMQ简介 2. 核心概念 四.JMS与AMQP比较 五.Rab ...

  9. RocketMQ安装部署及整合Springboot

    消息中间件的功能: 通过学习ActiveMq,kafka,rabbitMq这些消息中间件,我们大致能为消息中间件的功能做一下以下定义:可以先从基本的需求开始思考 最基本的是要能支持消息的发送和接收,需 ...

  10. Spring Boot 整合 minio(一步到位)

    按照这个步骤来,宝贝保你一步到位 一.minio版本安装:这里我安装的新版本 新版本安装 # docker 下载镜像 docker pull minio/minio # 安装镜像 docker run ...

随机推荐

  1. PPT或Visio比较舒适的RGB配色参数

    1.187 204 235 2.222 156 83 3.117 156 83 4.64 116 52 5.117 121 74 6.69 137 148 7.182 194 154 8.207 19 ...

  2. armbian挂载sd卡记录

    mkdir -p /mnt/mmctouch  /etc/init.d/mount.shvim /etc/init.d/mount.sh内容见图mount /dev/mmcblk1p1 /mnt/mm ...

  3. C 语言多文件编译

    C 语言中的多文件编程通常涉及将代码分散在几个不同的源文件(.c 文件)和头文件(.h 文件)中.这么做可以帮助你组织大型项目,提高代码的重用性,便于团队合作,分离接口和实现,以及加快编译时间.下面是 ...

  4. Windos操作系统下的Zookeeper安装图文教程

    凯哥已经准备好最新版本3.9.1且已经配置好了.既获取到配置好的. 获取到凯哥准备的安装后,只需要修改一下配置.将解压包解压后,找到conf文件,里面有个zoo.cfg配置文件.如下图: 下载后con ...

  5. Docker网络上篇-网络介绍

    通过前面的学习,我们已经可以把自己写的微服务项目通过dockerfile文件方式部署到docker上面了.那么微服务之间通信,怎么通信的?是在同一个网络还是在不同的网络环境下?docker中怎么配置网 ...

  6. ansible部署jdk source /etc/profile 不起作用?

    问题: ansible调用playbook远程mvn执行打包时发现执行出错,找不到JAVA_HOME.我们的exporter JAVA_HOME=/usr/java/jdk1.8.0写在/etc/pr ...

  7. 如何用VMWARE创建一个Linux虚拟机

    序言 各位好啊,我是会编程的蜗牛,作为java开发者,我们都是需要接触Linux服务器的,一般部署应用都是部署在Linux服务器上的~ 但一般的服务器要么需要购买,要么只是公司里的,那么有没有免费的L ...

  8. [namespace hdk] ordered_vector

    功能: 已重载[]运算符 已重载+运算符(合并) 已重载+=运算符 已重载构造函数 clear() it() 以std::vector形式返回自身 print(char=' ',char='\n') ...

  9. 使用MessagePipe实现进程间通信

    1.MessagePipe介绍 可以用于.NET和Unity上面的高性能的内存/分布式消息传递管道.适用于发布/订阅模式.CQRS的中介模式.Prism中的EventAggregator.IPC(进程 ...

  10. USB LPM状态

    USB的u0.u1.u2和u3代表不同的电源状态或低功耗状态,主要用于USB 3.0及其更高版本,目的是在不活动时减少功耗,同时保证设备能够迅速恢复到工作状态.这些状态的具体作用如下: U0(Acti ...