(万字长文)Linux——IO之重定向+缓冲区 +重定向 +缓冲区原理实现 +带重定向的简易版shell+标准输出标准错误
索引
- 文件描述符分配规则
- 重定向
- 缓冲区
- 1.什么是缓冲区
- 2.缓冲区在哪里
- 重定向
- 源码模拟实现缓冲区原理
- 带重定向的简易版Xshell
- 标准输入和标准错误
文件描述符分配规则
文件描述符的分配规则
从头遍历数组fd_array[],找到一个最小的,没有被使用的下标,分配给新的文件。
int main()7 {8 close(0);9 int fd = open("log.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666);10 if(fd < 0) {11 perror("open");12 return 1;13 }14 15 16 17 fprintf(stdout, "打开文件成功, fd : %d\n", fd);//将特定的字符串格式化写到特定的流中18 close(fd);19 return 0;20 }
如上所示,如果我们一开始将文件描述符0关掉,那么此时我们打开"log.txt’系统会为其分配的文件描述符为0
再看一个例子
如果此时我们将fd = 1 关闭,此时1这个文件描述符就会给新的文件log.txt
正常情况下如果我们cat log.txt的时候会打印出内容,因为我们在一开始关闭了显示器的标准stdout,然后再打开log.txt的时候其文件描述符会被自动填充为stdout.
但是运行之后发现
显示不出来,此时如果在源码中加上fflush(stdout)
发现就可以cat log.txt
就可以打印出来了
这是为什么呢?
先看下面的重定向和缓冲区的理解
重定向
所以也就不难理解追加重定向了,追加重定向就是将打开文件的方式修改一下。
输入从定向,就是dup2(fd, 0)
缓冲区
1.什么是缓冲区
缓冲区的本质:就是一段内存
- 解放使用缓冲区的进程时间
- 缓冲区的存在集中处理数据刷新,减少IO的次数,从而达到提高整机效率的目的
2.缓冲区在哪里
先看一段代码
1 #include<stdio.h>2 #include<sys/types.h>3 #include<sys/stat.h>4 #include<fcntl.h>5 #include<unistd.h>6 #include<string.h>7 int main()8 {9 printf("hello printf");//printf默认输出时候的文件描述符是1
W> 10 const char *msg = "hello write";11 write(1, msg, strlen(msg));//将msg写到标准输入中12 13 sleep(5);
此时发现先输出hello write
五秒钟之后再输出hello printf
printf("hello printf");//printf默认输出时候的文件描述符是110 fprintf(stdout, "hello fprintf");11 fputs("hello fputs", stdout); 12 const char *msg = "hello write";13 14 write(1, msg, strlen(msg));//将msg写到标准输入中15 16 sleep(5);
将代码改成上述发现还是跟原来的现象一样,hello write
先打印出来,然后再打印出printf fprintf fputs 的内容
为什么会这样?
可以证明是有缓冲区的,printf和fprintf fputs都是封装了write系统调用接口的,所以缓冲区必然不在write中
发现三个C语言接口的函数都有一个共同点,都有stdout
,
stdout
是FILE类型,其是一个结构体,而在结构体中除了有文件描述符外,还有语言级别的缓冲区。
所以缓冲区是语言级别的缓冲区
什么时候刷新?
常规
无缓冲(立即刷新)
行缓冲(逐行刷新,显示器的文件)
全缓冲(缓冲区满刷新)这个对应的是磁盘文件
特殊
进程退出,C语言的强制刷新
用户强制刷新 fflush
重定向
提问:如果在刷新之前,关闭了fd会有什么影响
先看不关闭fd时候的重定向
19 int fd = open("log.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666);20 if(fd < 0) {21 perror("open");22 return 1;23 }24 dup2(fd, 1);25 26 printf("hello printf");//printf默认输出时候的文件描述符是127 fprintf(stdout, "hello fprintf");28 fputs("hello fputs", stdout);29 const char *msg = "hello write";30 write(1, msg, strlen(msg));
如果我们在刷新之前关闭的话
printf("hello printf");//printf默认输出时候的文件描述符是127 fprintf(stdout, "hello fprintf");28 fputs("hello fputs", stdout);29 const char *msg = "hello write";30 write(1, msg, strlen(msg));31 close(1);
此时发现log.txt中只有write写入的内容,再一次证明了上述我们的结论,调用C语言的文件接口,就是通过fd找到对应的write,如果fd关闭了,就无法再显示了。
现在就可以理解最开始的问题了,如果将标准输出重定向到log.txt,关闭了fd之后就无法刷新了
再看一段代码
const char *str1 = "hello printf\n";11 const char *str2 = "hello fprintf\n";12 const char *str3 = "hello fputs\n";13 const char *str4 = "hello write\n";
W> 14 printf(str1);
W> 15 fprintf(stdout, str2);16 fputs(str3, stdout);17 //系统接口18 write(1, str4, strlen(str4));19 //调用结束上面的代码,执行fork20 fork();
上述代码的话,运行后的结果是
发现添加了重定向之后,此时代码打印是7行,其中C语言接口的函数各打印两条,write无论何种情况都只打印一条,为什么呢?
**代码的最后fork创建了子进程,父子进程代码共享,数据起初也是共享的,因为我们将打印的结果重定向到log.txt
了,而log.txt是一个磁盘文件,其刷新的条件是当缓冲区满的时,或者是进程退出的时候,会清空缓冲区,而无论父子进程谁先发生清空,数据都要发生写实拷贝,所以父进程刷新一份数据,子进程刷新一份数据,就是两份数据了,所以才会出现上述情况。
源码模拟实现缓冲区原理
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<assert.h>#define NUM 1024#define NONE_FLUSH 0x0 //没有刷新
#define LINE_FLUSH 0x1 //行刷新
#define FULL_FLUSH 0x2 //全满才刷新typedef struct _MyFILE {int _fileno;char _buffer[NUM];int _end;int _flags; //刷新方式
}MyFILE;MyFILE *my_open(const char *filename, const char *method)
{assert(filename);assert(method);int flag = O_RDONLY;if(strcmp(method, "r") == 0){} else if(strcmp(method, "r+") == 0) {} else if(strcmp(method, "w") == 0) {flag = O_WRONLY | O_CREAT | O_TRUNC;} else if(strcmp(method, "w+") == 0) {} else if(strcmp(method, "a") == 0) {} else if(strcmp(method, "a+") == 0) {} else {perror("open error!\n");}int fileno = open(filename, flag, 0666);if(fileno < 0) {return NULL;}MyFILE *fp = (MyFILE*)malloc(sizeof(MyFILE));if(fp == NULL) {return fp;}memset(fp, 0, sizeof(MyFILE));fp->_fileno = fileno;fp->_flags |= LINE_FLUSH;fp->_end = 0;return fp;}
void my_fflush(MyFILE *fp)
{assert(fp);if(fp->_end > 0) {write(fp->_fileno, fp->_buffer, fp->_end);fp->_end = 0;syncfs(fp->_fileno);//将数据从内存刷新到磁盘}
}
void my_fwrite(MyFILE *fp, const char *start, int len)
{assert(fp);assert(start);assert(len);//写到缓冲区中strncpy(fp->_buffer+fp->_end, start, len);fp->_end += len;if(fp->_flags & NONE_FLUSH) {} else if(fp->_flags & LINE_FLUSH) {if(fp->_end > 0 && fp->_buffer[fp->_end-1] == '\n') {//仅仅是写到内核中write(fp->_fileno, fp->_buffer, fp->_end);fp->_end = 0;syncfs(fp->_fileno);}} else if (fp->_flags & FULL_FLUSH) {}}void my_fclose(MyFILE *fp)
{my_fflush(fp);close(fp->_fileno);free(fp);fp = NULL;
}int main()
{MyFILE *fp = my_open("log.txt", "w");if(fp == NULL){perror("my_open error\n");return 1;}// const char *s = "hello zjt\n";// my_fwrite(fp, s, strlen(s));// printf("消息立即刷新");// sleep(3);// // const char *ss = "hello zhang";// my_fwrite(fp, ss, strlen(ss));// printf("写入了一个不满足条件的字符串\n");// sleep(3);// const char *sss = "hello jun";// my_fwrite(fp, ss, strlen(sss));// printf("写入了一个不满足条件的字符串\n");// my_fflush(fp); const char *s = "bbbbb-";my_fwrite(fp, s, strlen(s));printf("写入了一个不满足刷新条件的字符串\n");//fork();my_fclose(fp);return 0;
}
最后几行代码如果不加fork()
将fork()注释解除之后
在fork()函数创建子进程之后,此时因为我们的字符串没有\n
所以其是不支持刷新的,fork()创建子进程之后,父子进程代码数据共享,无论父子进程哪个先调用my_fclose(),其都会清空缓冲区,另外一个进程都会发生写实拷贝,所以父进程刷新一份数据,子进程刷新一份数据
带重定向的简易版Xshell
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h>
#include <ctype.h>// #define BUG 1
#define SEP " "
#define NUM 1024
#define SIZE 128#define DROP_SPACE(s) \do \{ \while (isspace(*s)) \s++; \} while (0)char command_line[NUM];
char *command_args[SIZE];char env_buffer[NUM]; // 为了测试#define NONE_REDIR -1
#define INPUT_REDIR 0
#define OUTPUT_REDIR 1
#define APPEND_REDIR 2int g_redir_flag = NONE_REDIR;
char *g_redir_filename = NULL;extern char **environ;
void CheckDir(char *commands)
{assert(commands);char *start = commands;char *end = commands + strlen(commands);while (start < end){if (*start == '>'){// 有可能是重定向,也可能是追加重定向if (*(start + 1) == '>'){// 追加重定向// ls -a -l >> log.txt*start = '\0';start += 2;g_redir_flag = APPEND_REDIR;DROP_SPACE(start); // 防止用户加空格g_redir_filename = start;break;}else{// ls -a -l > log.txt输出重定向*start = '\0';start++;DROP_SPACE(start);g_redir_flag = OUTPUT_REDIR;g_redir_filename = start;break;}}else if (*start == '<'){// 输出重定向*start = '\0';start++;DROP_SPACE(start);g_redir_filename = start;g_redir_flag = INPUT_REDIR;break;}else{start++;}}
}
int ChangDir(char *newdir)
{chdir(newdir);return 0;
}
int PutEnvMyshell(char *newenv)
{putenv(newenv); // 导出环境变量
}
int main()
{// shell本质上是一个死循环while (1){g_redir_flag = NONE_REDIR; // 每一次循环都要重新定义g_redir_filename = NULL;// 1.显示提示符printf("[zjt@1270.0.1 当前目录]# ");fflush(stdout);// 获取用户输入memset(command_line, '\0', sizeof(command_line) * sizeof(char));fgets(command_line, NUM, stdin); // 键盘,标准输入stdin,获取到的字符串是c风格的字符串以'\0'结尾command_line[strlen(command_line) - 1] = '\0'; // 清空\nCheckDir(command_line); // 检查路径// 3.字符串切分command_args[0] = strtok(command_line, SEP);int index = 1;// 给ls命令添加颜色if (strcmp(command_args[0], "ls") == 0){command_args[index++] = (char *)"--color=auto";}// strtok截取成功,返回字符串起始地址// 截取失败,返回NULLwhile (command_args[index++] = strtok(NULL, SEP));#ifdef BUGfor (int i = 0; i < index; i++){printf("%d : %s\n", i, command_args[i]);}
#endif// 内建命令的编写if (strcmp(command_args[0], "cd") == 0 && command_args[1] != NULL){ChangDir(command_args[1]); // 让调用方进行路径切换,父进程continue;}if (strcmp(command_args[0], "export") == 0 && command_args[1] != NULL){// 目前环境变量信息在command_line,会被清空// 所以我们要自己保存一下环境变量的内容strcpy(env_buffer, command_args[1]);PutEnvMyshell(env_buffer);continue;}// 创建进程执行pid_t id = fork();if (id == 0){int fd = -1;switch (g_redir_flag){case NONE_REDIR:break;case INPUT_REDIR:fd = open(g_redir_filename, O_RDONLY);dup2(fd, 0);break;case OUTPUT_REDIR:fd = open(g_redir_filename, O_WRONLY | O_CREAT | O_TRUNC);dup2(fd, 1);break;case APPEND_REDIR:fd = open(g_redir_filename, O_WRONLY | O_CREAT | O_APPEND);dup2(fd, 1);break;default:perror("Bug\n?");break;}// child// 程序替换execvp(command_args[0], command_args);exit(1); // 执行到这里,子进程一定替换失败}int status = 0;pid_t ret = waitpid(id, &status, 0);if (ret > 0){printf("执行命令成功! sig: %d, code : %d\n", status & 0x7F, (status >> 8) & 0xFF);}}return 0;
}
标准输入和标准错误
#include <iostream>
int main()
{// stdoutprintf("hello printf 1\n");fprintf(stdout, "hello fprintf 1\n");fputs("hello fputs 1\n", stdout);// stderrfprintf(stderr, "hello fprintf 2\n");fputs("hello fputs 2\n", stderr);perror("hello perror 2");// coutstd::cout << "hello cout 1" << std::endl;// cerrstd::cerr << "hello cerr 2" << std::endl;return 0;
}
先看代码,代码运行后的结果如下所示:
这个没问题,但是当我们将显示结果重定向后
发现并不是所有的显示结果都会重定向到文件中
如果这样操作的话,此时显示结果被分别重定向到了不同的文件中
为什么呢?
因为默认重定向的话只是将fd = 1的stdout重定向到文本文件中,如果需要重定向标准错误的话需要显示的写
所以上述重定向的标准写法应该是这样的
./a.out 1 > stdout.txt 2>stderr.txt
这么做的意义何在呢?
可以区分哪些是程序的日常输出,哪些是错误!
那么能不能将标准输出和标准错误重定向到一个文件中呢?可以,如何做呢?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4TGdyG0N-1685098168077)(null)]
可以注意到上述的perror在输出之后还打印出了success 为什么呢?
perror也是一个库函数,这个函数内部会自己获取errno的值,调用这个函数会直接把错误提示符打印出来,此外,我们也可以在错误提示字符串前添加一些自己想要打印的信息
什么是errno?
errno是一个全局变量,记录最近一次C库函数调用失败原因
我们可以自己实现一下perror
void my_perror(const char *info)
{fprintf(stderr," %s: %s \n", info, strerror(errno));
}
int main()
{int fd = open("log.txt", O_RDONLY);//此时必定是失败的if(fd < 0){// perror("open");my_perror("open");return 1;}return 0;
**万字长文结束,我本身是c++ 和Linux的,欢迎互相交流 **
相关文章:

(万字长文)Linux——IO之重定向+缓冲区 +重定向 +缓冲区原理实现 +带重定向的简易版shell+标准输出标准错误
索引 文件描述符分配规则重定向 缓冲区1.什么是缓冲区2.缓冲区在哪里 重定向源码模拟实现缓冲区原理带重定向的简易版Xshell标准输入和标准错误 文件描述符分配规则 文件描述符的分配规则 从头遍历数组fd_array[],找到一个最小的,没有被使用的下标,分配…...
面试:js 延迟加载方式
相关知识点: js 延迟加载,也就是等页面加载完成之后再加载 JavaScript 文件。 js 延迟加载有助于提高页面加载速度 一般有以下几种方式: defer 属性 async 属性 动态创建 DOM 方式 使用 setTimeout 延迟方法 让 JS 最后加载 js 的加载…...
将Oracle数据文件导入SQL Server的方法
审计过程中,采集的业务数据有Oracle备份数据,备份文件的后缀名为.dmp。如何将*.dmp文件导入审计人员熟悉的SQL Server中呢?以下是现场审计数据导入方法介绍。 一、将*.dmp文件导入oracle数据库 *.dmp文件为Oracle数据库备份文件,因…...

《汇编语言》- 读书笔记 - 实验5 编写、调试具有多个段的程序
《汇编语言》- 读书笔记 - 实验5 编写、调试具有多个段的程序 题目1题目2题目3题目4题目5题目6总结 题目1 将下面的程序编译、连接,用 Debug 加载、跟踪,然后回答问题 assume cs:code, ds:data, ss:stack data segmentdw 0123h,0456h,0789h,0abch,0def…...

剑指offer -- 二维数组中的查找
二维数组中的查找_牛客题霸_牛客网 (nowcoder.com) 暴力查找法: 是一种简单直接的解决方法,可以用于在二维数组中查找目标值。该方法的思路是遍历数组的每个元素,逐个与目标值进行比较。 具体步骤如下: 从数组的第一行第一列开始,…...

3. 自然语言处理NLP:具体用途(近义词类比词;情感分类;机器翻译)
一、求近义词和类比词 1. 近义词 方法一:在嵌入模型后,可以根据两个词向量的余弦相似度表示词与词之间在语义上的相似度。 方法二:KNN(K近邻) 2. 类比词 使用预训练词向量求词与词之间的类比关系。eg:man&a…...
Hibernate的FlushMode
一、Session中FlushMode的设置: 在事务开启前设置FlushMode属性,方法: // session.setFlushMode(FlushMode.Always|AUTO|COMMIT|NEVER|MANUAL)。Service public class TestService {Logger log LoggerFactory.getLogger(getClass());AutowiredEntityM…...

二线程序员的出路
最近长沙不太平。去年被动离职一拨人之后,HR一直强调降本增效,人人自危,挤走一拨人,反正会有大量内卷失败的一线程序员进来填坑。当然留就有人走,前同事除了几个出去搞培训创业(后面解散了)的之…...

MKS SERVO4257D 闭环步进电机_系列2 菜单说明
第1部分 产品介绍 MKS SERVO 28D/35D/42D/57D 系列闭环步进电机是创客基地为满足市场需求而自主研发的一款产品。具备脉冲接口和RS485/CAN串行接口,支持MODBUS-RTU通讯协议,内置高效FOC矢量算法,采用高精度编码器,通过位置反馈&am…...

使用Actor-Critic的DDPG强化学习算法控制双关节机械臂
在本文中,我们将介绍在 Reacher 环境中训练智能代理控制双关节机械臂,这是一种使用 Unity ML-Agents 工具包开发的基于 Unity 的模拟程序。 我们的目标是高精度的到达目标位置,所以这里我们可以使用专为连续状态和动作空间设计的最先进的Deep…...

黑马学生入职B站1年,晒出21K月薪:我想跳槽华为
现在的Z时代,嘴上说着不要,身体却很诚实。 前两天,黑马发布了《2022年度互联网平均薪资出炉!高到离谱!》,信息传输、软件和信息技术服务业薪资遥遥领先!Z时代举头望着天花板,故作潇…...

一文看懂GPT风口,都有哪些创业机会?
新时代的淘金者,低附加价值的创业要谨慎,高附加价值、低技术门槛创业也要谨慎,主干道边上的创业也要谨慎。不少朋友看完不淡定了,干什么都谨慎,回家躺平好了,我有个朋友,靠ChatGPT,半…...

chatgpt赋能python:Python中的不确定尾数问题
Python中的不确定尾数问题 Python作为一种高级编程语言,被广泛应用于数据科学、机器学习、Web开发等众多领域。然而,Python在处理浮点数时会出现一些不确定尾数的问题,给程序员和数据分析员带来不少麻烦。本篇文章将介绍Python中不确定尾数的…...

杜绝开源依赖风险,许可证扫描让高效合规「两不误」
目录 开源许可证及其常见类型 开源许可证扫描是软件研发过程中,不可或缺的工具 极狐GitLab 开源许可证扫描的优势与应用 Step 1:启用及设置许可证策略 Step 2:自动创建策略文件存放项目 Step 3:查看许可证合规情况 Step 4&…...

【sop】含储能及sop的多时段配网优化模型
目录 1 主要内容 2 部分代码 3 程序结果 4 下载链接 1 主要内容 之前分享了含sop的配电网优化模型,链接含sop的配电网优化,很多同学在咨询如何增加储能约束,并进行多时段的优化,本次拓展该部分功能,在原代码的基础上增加储能模…...
nodjs使用阿里云镜像安装
要使用阿里云镜像来安装 npm 包,你需要按照以下步骤进行操作: 首先,确保你已经安装了 Node.js 和 npm。你可以在终端(或命令提示符)中输入以下命令来验证它们的安装: node -v npm -v如果显示了 Node.js 和…...

C++ Primer Plus 第二章习题
目录 复习题 1.C程序的模块叫什么? 2.#include 预处理器编译指令的用处? 3.using namespace std; 该语句是干什么用的? 4.什么语句可以打印一个语句"hello,world",然后重新换行? 5.什么语句可以用来创…...

两分钟学会 制作自己的浏览器 —— 并将 ChatGPT 接入
前期回顾 分享24个强大的HTML属性 —— 建议每位前端工程师都应该掌握_0.活在风浪里的博客-CSDN博客2分享4个HTML5 属性,开发必备https://blog.csdn.net/m0_57904695/article/details/130465836?spm1001.2014.3001.5501 👍 本文专栏:开发…...

HEVC中,mvd怎么写进码流的?
文章目录 Motion vector difference syntax 标准文档描述语义解释设计意义 Motion vector difference syntax 标准文档描述 语义解释 MvdL1[ x0 ][ y0 ][ compIdx ] L1列表的mvd x0,y0 表示亮度快左上角坐标 compIdx 0表示水平 compIdx 0表示垂直 mvd_l1_zero_flag:…...

隐形黑客潜入美国和关岛关键基础设施而未被发现
微软和“五眼联盟”国家周三表示,一个隐秘的组织成功地在美国和关岛的关键基础设施组织中建立了一个持久的立足点,而没有被发现。 这家科技巨头的威胁情报团队正在以伏特台风(Volt Typhoon)的名义跟踪这些活动,包括入侵后的凭证访问和网络系…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...

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

使用分级同态加密防御梯度泄漏
抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...

相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...
多模态图像修复系统:基于深度学习的图片修复实现
多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...
Kafka主题运维全指南:从基础配置到故障处理
#作者:张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1:主题删除失败。常见错误2:__consumer_offsets占用太多的磁盘。 主题日常管理 …...
云原生周刊:k0s 成为 CNCF 沙箱项目
开源项目推荐 HAMi HAMi(原名 k8s‑vGPU‑scheduler)是一款 CNCF Sandbox 级别的开源 K8s 中间件,通过虚拟化 GPU/NPU 等异构设备并支持内存、计算核心时间片隔离及共享调度,为容器提供统一接口,实现细粒度资源配额…...

沙箱虚拟化技术虚拟机容器之间的关系详解
问题 沙箱、虚拟化、容器三者分开一一介绍的话我知道他们各自都是什么东西,但是如果把三者放在一起,它们之间到底什么关系?又有什么联系呢?我不是很明白!!! 就比如说: 沙箱&#…...