【Linux】解锁文件描述符奥秘,高效缓存区的实战技巧
fd和缓冲区
- 1. 文件描述符fd
- 1.1. 概念与本质
- 1.2. 打开文件的管理
- 1.3. 一切皆文件的理解
- 1.4. 分配规则
- 1.5. 重定向的本质
- 1.5.1. dup2
- 2. FILE中的缓冲区
- 2.1. 概念
- 2.2. 存在的原因
- 2.3. 类型(刷新方案)
- 2.4. 存放的位置
- 2.4.1. 代码证明、现象解释
- 2.5. 模拟C标准库中的方法
1. 文件描述符fd
1.1. 概念与本质
-
定义:是用于标识打开文件的非负整数。
-
文件描述符的本质,就是数组下标。
1.2. 打开文件的管理
问:为什么访问文件的系统调用接口,都必需使用文件描述符fd?
- 当我们打开一个文件时,OS会在内存中创建一个file结构体,用来描述被打开的文件,这个结构体包含了文件的当前读写位置、文件描述符、文件路径等相关信息。
struct file {struct path f_path; // 文件路径struct file_operations *f_op; // 文件操作指针int _fileno; //文件描述符loff_t f_pos; // 当前文件读写位置...
};struct file_operations {int (*open)(struct inode *, struct file *);int (*release)(struct inode *, struct file *);ssize_t (*read)(struct file *, char __user *, size_t, loff_t *);ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *);loff_t (*llseek)(struct file *, loff_t, int);...
};
- 因为open函数是由进程来执行的,所以必须让进程和文件关联起来。在每一个task_struct结构体中都包含了一个struct file_struct*类型的指针,它指向了一个包含文件描述符表的file_struct结构体。
struct task_struct {...files_struct *files; // 文件描述符表...
};
- 文件描述符表是一个file*类型的指针数组,每个元素都指向一个打开的文件,而文件描述符就是此数组的下标,所以只要拿到了文件描述符表,就可以索引到对应的文件。
struct files_struct {...struct file *fd[FD_SETSIZE]; // 文件描述符数组...
};
打开文件本质:在内核中,把文件在磁盘上找到、内容和属性加载,在内存中创建file结构体,属性、方法、缓冲区都初始化,然后把结构体链入到系统管理文件的链表中,并且在指针数组中找到一个数据下标,再把它的地址填充进来,最后把数组下标(fd)返回给上层用户,应用层得到fd值。
a. 把数据写到文件中write:
-
因为write是由进程通过系统调用来执行的,而系统能够识别出是哪个进程在请求服务,即:OS可以找到进程(task_struct);
-
因为write需要访问文件,所以通过fd,直接在数组中进行索引,从而找到文件。再把用户空间中的缓冲区buf中的数据,拷贝到内核空间中的文件结构体对象的缓冲区中,最后让OS把缓冲区的刷新到磁盘文件中。
b. 从文件中读取数据read:
-
因为read是由进程通过系统调用来执行的,而系统能够识别出是哪个进程在请求服务,即:OS可以找到进程(task_struct);
-
因为read需要访问文件,所以通过fd,直接在数组中进行索引,从而找到文件。如果文件结构体对象的缓冲区中有内容,就直接读取到用户空间的缓冲区buf中,反之,就让OS把磁盘文件中的数据导入到内存中。
c. 关闭文件close:
-
因为close是由进程通过系统调用来执行的,而系统能够识别出是哪个进程在请求服务,即:OS可以找到进程(task_struct);
-
因为close需要访问文件,所以通过fd,直接在数组中进行索引,从而找到文件。OS再将文件结构体对象进行释放。
1.3. 一切皆文件的理解
一、文件系统的抽象和VFS
- VFS(Virtual File System):虚拟文件系统,是Linux内核的一个软件层,它提供了一套统一的接口来访问各种类型的文件系统和硬件设备。
这种设计使得用户和应用程序能够通过调用相同的系统调用(如open、write、read等)来操作不同的文件系统,而无需关心底层文件系统的具体实现细节。
- 文件操作结构体file_operations:在linux内核中,每个打开的文件都有一个指向file_operations结构体的指针,它包含一系列函数指针,即:它定义了文件的各种操作(如:读、写、打开、关闭),其内包含的函数指针指向具体的实现方法。
不同的文件系统或硬件的驱动程序会提供这些函数的具体实现,但这些函数的参数类、返回值类型、函数名,必须与定义在file_operations结构体中的函数指针相匹配。
struct file {struct inode *f_inode; // 文件的inodestruct file_operations *f_op; // 文件操作函数指针unsigned long f_flags; // 文件标志loff_t f_pos; // 当前文件位置// 其他信息...
};struct file_operations { //文件操作函数int (*open)(struct inode *, struct file *);int (*release)(struct inode *, struct file *);ssize_t (*read)(struct file *, char __user *, size_t, loff_t *);ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *);loff_t (*llseek)(struct file *, loff_t, int);// 其他操作...
};
- VFS的核心思想是通过抽象和封装来屏蔽底层硬件的差异。
二、面向对象编程的类比
-
多态性:在面向对象编程中,多态性允许我们使用统一的接口来调用不同的实现。在VFS中,是通过函数指针来实现多态性,不同的文件系统的具体实现方法不同,但上层应用程序只使用统一的函数指针接口。
-
封装:VFS屏蔽了文件系统和硬件设备的差异,即:隐藏了底层的细节;使得上层应用程序可以使用统一的函数指针接口来访问文件。
上层代码无需关心底层操作的实现,只需按照统一接口的规范进行操作。
不能从显示器读数据,平时在显示器输入的东西,显示器也显示了,不是通过显示器把数据交给了你的程序,而是从键盘中输入数据,你的程序先从键盘中读到的,为了让用户看到你输入的数据,程序就把数据同步的给显示器拷贝了一份。
1.4. 分配规则
- fd分配规则:最小未被使用的数组下标,会被分配给最新打开的文件。
#include<stdio.h>
#include<sys/types.h>
#include<fcntl.h>
#include<unistd.h>
#include<sys/stat.h>
#include<string.h>int main()
{close(1);//关闭标准输出流int fd1 = open("log.txt", O_WRONLY|O_CREAT|O_TRUNC, 0666);printf("fd1: %d\n", fd1); //printf默认向stdin—>fd = 1打印printf("hello world\n"); //输出重定向:本来应该把内容向显示器文件进行写入,更改为向磁盘文件进行写入return 0;
}
#include<stdio.h>
#include<sys/types.h>
#include<fcntl.h>
#include<unistd.h>
#include<sys/stat.h>
#include<string.h>int main()
{close(0); //关闭标入输出流 int fd2 = open("data.txt", O_RDWR);printf("fd2: %d\n", fd2); char buff[64]; fgets(buff, 64, stdin); //输入重定向:本来应该从键盘文件中读取的内容,更改为从磁盘文件中读取printf("%s\n", buff); return 0;}
1.5. 重定向的本质
- 重定向的本质:更改文件描述符表的内容,即:更改文件描述符(stdin、stdou、stderr)的指向,使得原本要写入到标准输出的数据,被重定向到其他文件、或者原本要从标准输入中读取的数据,重定向到来自于其他文件。
1.5.1. dup2
int dup2(int oldfd,int newfd);
-
功能:将stdin、stdout、stderr重定向到文件或其他设备。
-
参数:oldfd:要被复制的文件描述符;newfd:目标文件的描述符。
-
返回值:成功,返回新的文件描述符(即:newfd)。出错时,返回 -1,并设置 errno以指示错误。
#include<stdio.h>
#include<sys/types.h>
#include<fcntl.h>
#include<unistd.h>
#include<sys/stat.h>int main()
{int fd = open("log.txt", O_WRONLY|O_CREAT|O_TRUNC, 0666);dup2(fd, 1);printf("hello zzx\n");return 0;
}
2. FILE中的缓冲区
2.1. 概念
- 概念:本质是一块内存区域,用于暂时存放数据,以便更高效地处理输入、输出操作。
💡此处的缓冲区(如:进度条中的缓冲区等),不是内存中的缓冲区,它是语言层面的缓冲区,即:C语言自带的缓冲区,由C语言标准库提供。
- 缓冲区也会为格式化输入、输出操作提高场所。
printf函数工作原理:它会将其他类型的数据(如整数、浮点数等)转换为字符数据(即字符串),转化后的数据会被写入到FILE结构体维护的缓冲区中,根据条件刷新缓冲区。
scanf函数工作原理:scanf会从输入流中读取字符数据,将读取的数据转化为相应的格式化数据,格式化的数据会被存放到FILE结构体维护的缓冲区中,最终被存放到变量中。
2.2. 存在的原因
- 提高使用者的效率
减少了C接口的使用时间,从而减少了用户的等待时间,提高了使用者的效率:调用C接口时,只要将数据交给了缓冲区,就可立即返回,无需等待实际的写入操作完成,意味这用户可以更快地继续执行其他任务。
- 提高计算机整体的拷贝效率。
调用系统调用接口,都是有成本的,有时间和空间的开销。
减少调用系统调用的次数,提高了计算机整体的拷贝效率:缓冲区可以聚集大量数据,直到缓冲区满了,再调用一次系统调用进行实际的数据写入,即:进行一次拷贝。
故事理解:张三给李四送生日礼物,只需要将礼物交给附近的菜鸟驿站,就可立即其他活动,无需亲自送到的李四那,即:提高了使用者的效率。菜鸟驿站不是每次只处理一个包裹,而是收集多个包裹,直到它们填满整个运输车辆,然后再一次性运送到目的地,即:聚集数据,一次拷贝,提高了计算机的整体效率。—— 菜鸟驿站就相当于缓冲区。
2.3. 类型(刷新方案)
一、无缓冲、无刷新
-
无缓冲:无刷新,意味着数据不会暂存在缓冲区中,而是立即被写入到目标设备中。
-
适用场景:需要立即看到结果、实时性要求很高的场景,如:实时系统、设备驱动程序。
-
优点:保证了数据的即时可见性。
-
缺点:性能下降,频繁的使用系统调用会增加开销。
二、全缓冲、全刷新
-
全缓冲:全刷新,缓冲区满了或者关闭文件时,缓冲区的数据才会被刷新到目的设备中。
-
适用场景:文件的读写操作,尤其是大文件。
-
优点:减少了系统调用的次数,提高了性能。
-
缺点:可能会丢失数据,如:在缓冲区的数据未被刷新前,发生崩溃,则这部分的数据就会丢失。
三、行缓冲、行刷新
-
行缓冲:行刷新,意味着遇到换行符\n,缓冲区的数据就会被立即刷新到目的设备中。
-
适用场景:标准输入输出(显示器)。
💡当调用c语言接口fflush(),进行强制刷新; 进程退出时,或文件关闭时,自动刷新。
2.4. 存放的位置
-
缓冲区存放在FILE结构体中,即:缓冲区是被FILE结构来维护的。
-
每个通过标准C库函数打开的文件,都拥有自己的缓冲区。
fwrite等标准库函数,会先将数据拷贝到缓冲区中,然后根据一定的条件,调用系统调用接口进行刷新。
文件操作的系统调用接口,其实是个拷贝函数,它将数据从语言层的缓冲区拷贝到内存的缓冲区。
typedef struct _IO_FILE FILE;struct _IO_FILE {int _flags; /* High-order word is _IO_MAGIC; rest is flags. */
#define _IO_file_flags _flags//缓冲区相关/* The following pointers correspond to the C++ streambuf protocol. *//* Note: Tk uses the _IO_read_ptr and _IO_read_end fields directly. */char* _IO_read_ptr; /* Current read pointer */char* _IO_read_end; /* End of get area. */char* _IO_read_base; /* Start of putback+get area. */char* _IO_write_base; /* Start of put area. */char* _IO_write_ptr; /* Current put pointer. */char* _IO_write_end; /* End of put area. */char* _IO_buf_base; /* Start of reserve area. */char* _IO_buf_end; /* End of reserve area. *//* The following fields are used to support backing up and undo. */char *_IO_save_base; /* Pointer to start of non-current get area. */char *_IO_backup_base; /* Pointer to first valid character of backup area */char *_IO_save_end; /* Pointer to end of non-current get area. */struct _IO_marker *_markers;struct _IO_FILE *_chain;int _fileno; //封装的文件描述符
#if 0int _blksize;
#elseint _flags2;
#endif_IO_off_t _old_offset; /* This used to be _offset but it's too small. */#define __HAVE_COLUMN /* temporary *//* 1+column number of pbase(); 0 is unknown. */unsigned short _cur_column;signed char _vtable_offset;char _shortbuf[1];/* char* _save_gptr; char* _save_egptr; */_IO_lock_t *_lock;
#ifdef _IO_USE_OLD_IO_FILE
};
2.4.1. 代码证明、现象解释
#include<stdio.h>
#include<unistd.h>
#include<string.h>int main()
{const char* s1 = "hello write\n";write(1, s1, strlen(s1)); //调用系统调用,直接将数据写入到内核中//fprintf、fwrite为库函数,向显示器进行写入,行刷新(遇到换行符)const char* s2 = "hello fprintf\n";fprintf(stdout, "%s", s2); const char* s3 = "hello fwrite\n";fwrite(s3, strlen(s3), 1, stdout); fork(); //在创建子进程之前,缓冲区中的数据全部被刷新到内核中了return 0;
}
现象1解释:write()为系统调用接口,直接将数据写入到内核中;fprintf、fwrite为库函数,先将数据写入到缓冲区中,因为它们都是向显示器进行写入,而写入显示器是行刷新(遇到换行符\n,进行刷新),所以fork创建子进程前缓冲区中的数据全部被刷新到内核中了。
Tips:刷新到内核的数据,不属于进程的数据;存放在缓冲区中的数据,属于进程的数据。
现象2解释:重定向到普通文件时,数据刷新缓冲区的方式,由行缓存变为全缓冲,C语言接口自带缓冲区,所以它会将数据写入到缓冲区中,就不会立即刷新。fork创建子进程,父子共享缓冲区的数据,但是进程退出后,统一进行刷新。刷新缓冲区,是清空缓冲区,是修改数据的一种方式,所以父子进程的数据会发生写时拷贝,父子进程分别刷新各自的缓冲区,随即产生两份数据。write是系统调用接口,直接将数据写入到内核中,不存在所谓的缓冲区。
-
一般C库函数写入文件时,是全缓冲; 写入到显示器时,是行缓冲。
-
重定向到普通文件时,数据刷新缓冲区的方式,由行缓存变为全缓冲。
-
刷新缓冲区,是清空缓冲区,是修改数据的一种方式。
2.5. 模拟C标准库中的方法
#pragma once //防止头文件重复包含#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<string.h>
#include<stdlib.h>#define SIZE 4094//定义缓冲区的类型
#define None_Flush 1
#define Full_Flush (1<<1)
#define Line_Flush (1<<2)//自定义file结构体
typedef struct myfile{int fileno; //文件描述符int pos; //当前读写位置int cap; //缓冲区容量int flush_mode; //缓冲区类型char buff[SIZE]; //输出缓冲区
}myfile;myfile* my_fopen(const char* path, const char* mode); //打开文件
void my_fclose(myfile* fp); //关闭文件
int my_fwrite(myfile* fp, const char* str, int size); //读文件
void my_fflush(myfile* fp); //刷新缓冲区
void print_buff(myfile* fp); //打印file结构体的内容,便于测试
#include"mystdio.h" const char* To_string(int flush_mode) //将整形转化为字符串
{if(flush_mode & None_Flush) return "Nono Flush";else if(flush_mode & Line_Flush)return "Line_Flush";else if(flush_mode & Full_Flush)return "Full_Flush";
}void print_buff(myfile* fp) //打印file结构体的内容
{printf("fd: %d\n", fp->fileno);printf("fd: %d\n", fp->pos);printf("buff: %s\n", fp->buff);printf("flush_mode: %s\n", To_string(fp->flush_mode));
}myfile* my_fopen(const char* path, const char* mode) //打开文件
{int flag = -1; //确认它是以何种方式打开文件if(strcmp(mode, "r") == 0)flag = O_RDONLY; else if(strcmp(mode, "w") == 0)flag = O_WRONLY|O_CREAT|O_TRUNC; else if(strcmp(mode, "a") == 0)flag = O_WRONLY|O_CREAT|O_APPEND;else return NULL;//底层调用系统调用接口open打开文件int fd = -1; if(flag & O_RDONLY) //读不需要创建新的文件fd = open(path, flag); else //写、追加,都需要创建新的文件,并且需要设置文件权限{ umask(0); fd = open(path, flag, 0666);}if(fd < 0) //调用open失败return NULL;//为打开的文件创建一个file类型的结构体,用来记录描述打开文件的信息myfile* fp = (myfile*)malloc(sizeof(myfile));if(fp == NULL) //malloc调用1失败return NULL;//file结构体对象构建成功,进行初始化fp->fileno = fd;fp->pos = 0;fp->cap = SIZE;fp->flush_mode = Line_Flush;return fp;
}void my_fflush(myfile* fp) //刷新缓冲区
{if(fp->pos == 0) return ;//底层调用系统调用接口writewrite(fp->fileno, fp->buff, fp->pos);//清空缓冲区的内容fp->pos = 0;
} void my_fclose(myfile* fp) //关闭文件
{my_fflush(fp); //文件关闭,自动刷新缓冲区close(fp->fileno);free(fp);
}int my_fwrite(myfile* fp, const char* str, int size) //向文件写内容
{//将数据先拷贝到用户层的缓冲区内memcpy(fp->buff + fp->pos, str, size); fp->pos += size; //判断是否需要刷新if(fp->flush_mode == Line_Flush && fp->buff[fp->pos - 1] == '\n') //行刷新my_fflush(fp);else if(fp->flush_mode == Full_Flush && fp->pos == fp->cap) //全刷新my_fflush(fp);return 0;
}
int main() { myfile* fp = my_fopen("data.txt", "w"); if(fp == NULL) return 1; char buf[SIZE]; int cnt = 5; while(cnt--) { snprintf(buf, SIZE, "helloworld: %d :", cnt); //字符串的拼接my_fwrite(fp, buf, strlen(buf)); print_buff(fp); sleep(1); } my_fclose(fp); return 0; }
相关文章:
【Linux】解锁文件描述符奥秘,高效缓存区的实战技巧
fd和缓冲区 1. 文件描述符fd1.1. 概念与本质1.2. 打开文件的管理1.3. 一切皆文件的理解1.4. 分配规则1.5. 重定向的本质1.5.1. dup2 2. FILE中的缓冲区2.1. 概念2.2. 存在的原因2.3. 类型(刷新方案)2.4. 存放的位置2.4.1. 代码证明、现象解释 2.5. 模拟C标准库中的方法 1. 文件…...
MySQL基础笔记(五)
在此特别感谢尚硅谷-康师傅的MySQL精品教程 获取更好的阅读体验请前往我的博客主站! 如果本文对你的学习有帮助,请多多点赞、评论、收藏,你们的反馈是我更新最大的动力! 约束 1. 约束(constraint)概述 1.1 为什么需要约束 数据完整性&…...
夯实数字技术,培育创新人才:数据科学与大数据技术专业人才培养实践
近年来,得益于全球各国家和地区对大数据产业的政策扶持以及数字经济的蓬勃发展,大数据市场在全球范围内展现出了迅猛的增长态势。国家层面相继出台了诸如《“数据要素 ” 三年行动计划(2024—2026 年)》《数字中国建设整体布局规划…...
Java爬虫大冒险:如何征服1688商品搜索之巅
在这个信息爆炸的时代,数据就是力量。对于电商平台而言,数据更是金矿。今天,我们要踏上一场Java爬虫的冒险之旅,目标是征服1688这个B2B电商巨头,获取按关键字搜索的商品信息。这不仅是技术的挑战,更是智慧的…...
IEC 101/104 中为什么我们需要单点和双点信号
REDISANT 提供互联网与物联网开发测试套件 # 互联网与中间件: Redis AssistantZooKeeper AssistantKafka AssistantRocketMQ AssistantRabbitMQ AssistantPulsar AssistantHBase AssistantNoSql AssistantEtcd AssistantGarnet Assistant 工业与物联网࿱…...
01、NodeJS学习笔记,第一节:Node.js初识与内置模块
一、初识Node.js与内置模块 ##网址 https://nodejs.org##npm包 https://www.npmjs.com/ (搜索)https://registry.npmjs.org/ (下载)1、初识Node.js ##思考:为什么JavaScript可以在浏览器中被执行因为浏览器…...
ElasticSearch 自动补全
1、前言 当用户在搜索框输入字符时,我们应该提示出与该字符有关的搜索项,根据用户输入的字母,提示完整词条的功能,就是自动补全。 2、安装拼音分词器 Github地址:https://github.com/infinilabs/analysis-pinyin 插件…...
整点(枚举)
Hello!大家好!我是学霸小羊,今天分享一道c枚举题: 题目描述 在二维坐标系, 有一个圆,圆心在(0,0),圆的半径是r。问圆内有多少个整点(所谓的整点就是横坐标和纵坐标都是整数的点)。若点P的横坐标是整数a&a…...
【WRF安装】WRF编译错误:problems building executables look for error in the build log
WRF编译错误 错误内容:problems building executables, look for error in the build log原因1:gcc版本过低安装高版本gcc 原因2:netcdf版本和配置有误原因3:库冲突原因4:export NETCDF_classic1终极手段:重…...
2024年12月陪玩系统-仿东郊到家约玩系统是一种新兴的线上预约线下社交、陪伴系统分享-优雅草央千澈-附带搭建教程
2024年12月陪玩系统-仿东郊到家约玩系统是一种新兴的线上预约线下社交、陪伴系统分享-优雅草央千澈-附带搭建教程 产品介绍 仿东郊到家约玩系统是一种新兴的线上预约,线下社交、陪伴、助娱、助攻、分享、解答、指导等服务模式,范围涉及电竞、运动、音乐…...
社区版 IDEA 开发webapp 配置tomcat
1.安装tomcat 参考Tomcat配置_tomcat怎么配置成功-CSDN博客 2.构建webapp项目结构 新建一个普通项目 然后添加webapp的目录结构: main目录下新建 webapp 文件夹 webapp文件夹下新建WEB_INF文件夹 *WEB_INF目录下新建web.xml wenapp文件夹下再新建index.html …...
IDEA中解决Edit Configurations中没有tomcat Server选项的问题
今天使用IDEA2024专业版的时候,发现Edit Configurations里面没有tomcat Server,最终找到解决方案。 一、解决办法 1、打开Settings 2、搜索tomcat插件 搜索tomcat插件之后,找到tomcat 发现tomcat插件处于未勾选状态,然后我们将其勾选保存即可。 二、结果展示 最后,再次编…...
【Python】主成分分析PCA - 算法、问题与Python实现
【Python】主成分分析PCA - 算法、问题与Python实现 一、PCA 算法简介(一)概念及作用(二)基本原理(三)算法步骤1.数据预处理2.计算协方差矩阵3.进行特征值分解4.选择主成分5.完成数据降维 二、PCA 常见问题…...
Go怎么做性能优化工具篇之pprof
工欲善其事、必先利其器。这次我们来看看Go的性能优化工具有哪些吧 Go性能优化的工具 一、pprof 工具 pprof 是 Go 语言自带的性能分析工具,可以帮助开发者分析程序的 CPU 使用情况、内存使用情况、goroutine 调度情况等,从而定位性能瓶颈。通过 pprof…...
DataOps驱动数据集成创新:Apache DolphinScheduler SeaTunnel on Amazon Web Services
引言 在数字化转型的浪潮中,数据已成为企业最宝贵的资产之一。DataOps作为一种文化、流程和实践的集合,旨在提高数据管道的质量和效率,从而加速数据从源头到消费的过程。白鲸开源科技,作为DataOps领域的领先开源原生公司…...
递归读取指定目录下的文件
序言 需要读取sftp服务器上符合指定的文件名正则的文件列表,目前想到的最好的办法就是递归。 我这里引入的依赖是: <!-- jsch-sftp连接 --><dependency><groupId>com.jcraft</groupId><artifactId>jsch</artif…...
代码随想录算法训练营day46|动态规划part12
今天就结束动态规划章节了,以后还要多加练习。 今天的两道题都很有难度,647回文子串的思路非常巧妙,因为用一维dp数组比较难表示子串的起点和终点,所以需要用二维dp数组表示,dp[i][j]表示以i为起点,j为终点…...
ubuntu 24.04.1安装FTP流程
1、安装vsftpd: sudo apt update sudo apt install vsftpd 2、安装后重启查看vsftpd状态 sudo systemctl status vsftpd 输出如下所示,表明vsftpd服务处于活动状态并正在运行: * vsftpd.service - vsftpd FTP server Loaded: loaded (/…...
【Linux】UDP通信
udp使用的是数据报传输。可以一对一,一对多进行传输,用于快速,实时性高的场景 服务器端: 使用步骤: 1.创建socket 2.bind绑定可接收的客户端 3.while{ recv接收数据 send发送数据 } #include <stdio.h> #inclu…...
日期格式、JSR303校验
日期格式 public class Monster() {DateTimeFormat(pattern "yyyy-MM-dd")private Date birthday; } 输入:2024-11-12, 输出:Monster{birthdaySun Nov 12 00:00:00 CST 2024} public class Monster {JsonFormat(pattern &…...
ELK系列-(六)Redis也能作为消息队列?(上)
一、前文回顾 🔍 在前面的ELK系列中,我们已经搭建了ELK的核心组件,包括: ELK系列-(一)Docker部署ELK核心组件ELK系列-(二)LogStash数据处理的瑞士军刀ELK系列-(三&…...
点击展示大图预览
原文链接在table表格里能够实现,点击里面的图片实现大图预览的效果; 一、先安装viewer — 使用npm安装 npm install v-viewer --save二、在main.js中引入 import Viewer from v-viewer //点击图片大图预览 import viewerjs/dist/viewer.css Vue.use(…...
游戏AI实现-寻路算法(BFS)
广度优先搜索算法(英语:Breadth-first search,缩写:BFS),又译作宽度优先搜索,或横向优先搜索,是一种图形搜索算法。 寻路地图搭建: 游戏AI实现-寻路地图搭建-CSDN博客 …...
tryhackme-Pre Security-HTTP in Detail(HTTP的详细内容)
任务一:What is HTTP(S)?(什么是http(s)) 1.What is HTTP? (HyperText Transfer Protocol)(什么是 HTTP?(超文本传输协议)) http是你查看网站的时候遵循的…...
CNN和Transfomer介绍
文章目录 CNN和Transfomer介绍CNN和Transfomer的区别1. **基本概念**2. **数据处理方式**3. **模型结构差异**4. **应用场景区别** 自注意力机制1. **自注意力机制的概念**2. **自注意力机制的实现步骤**3. **自注意力机制的优势** Transformer结构组成1. **多头注意力层&#…...
37. Three.js案例-绘制部分球体
37. Three.js案例-绘制部分球体 实现效果 知识点 WebGLRenderer WebGLRenderer 是Three.js中的一个渲染器类,用于将3D场景渲染到网页上。 构造器 WebGLRenderer( parameters : Object ) 参数类型描述parametersObject渲染器的配置参数,可选。 常用…...
Latex+VsCode+Win10搭建
最近在写论文,overleaf的免费使用次数受限,因此需要使用本地的形式进行编译。 安装TEXLive 下载地址:https://mirror-hk.koddos.net/CTAN/systems/texlive/Images/ 下载完成直接点击iso进行安装操作。 安装LATEX Workshop插件 设置VsCode文…...
【ETCD】【Linearizable Read OR Serializable Read】ETCD 数据读取:强一致性 vs 高性能,选择最适合的读取模式
ETCD 提供了两种不同类型的读取操作方式,分别是 Linearizable Read(线性化读取)和 Serializable Read(可串行化读取)。这两种方式主要区分在读取数据时对一致性的要求不同。 目录 1. Linearizable Read(线…...
windows下搭建本地sofa-registry
官方介绍: SOFARegistry 是蚂蚁金服开源的一个生产级、高时效、高可用的服务注册中心。SOFARegistry 最早源自于淘宝的 ConfigServer,十年来,随着蚂蚁金服的业务发展,注册中心架构已经演进至第五代。目前 SOFARegistry 不仅全面服…...
什么是MyBatis
MyBatis 简介 MyBatis 是一个流行的 Java 持久层框架(Persistence Framework),它主要用于简化数据库操作,提供了对数据库的映射支持,使得开发人员能够通过简单的配置和映射文件来执行数据库操作(如增、删、…...
Docker如何运行一个Java的jar包程序
Docker如何运行一个Java的jar包程序 1、jar包程序 2、start.sh运行jar包脚本 #!/bin/bash #进入目录 cd /app #1.下载SDK并安装 java -jar SDKDown1.4.jar #2.加载环境变量 export LD_LIBRARY_PATH/opt/casb/CipherSuiteSdk_linux/lib echo $LD_LIBRARY_PATH #3.执行SDK java …...
c语言----顺序结构
顺序结构的基本概念 定义:顺序结构是C语言程序中最基本的结构,它按照语句的先后顺序依次执行。就像我们日常做事一样,一步一步地按照顺序来完成任务。在C语言程序中,从程序的第一条语句开始,逐句向下执行,…...
BERT采用双向训练
BERT采用双向训练 定义 BERT(Bidirectional Encoder Representations from Transformers)是一种基于Transformer架构的预训练语言模型。它在自然语言处理(NLP)领域具有极其重要的地位,由谷歌在2018年提出,能够对文本进行深度的语义理解,从而广泛应用于各种语言相关的任务…...
流程引擎Activiti性能优化方案
流程引擎Activiti性能优化方案 Activiti工作流引擎架构概述 Activiti工作流引擎架构大致分为6层。从上到下依次为工作流引擎层、部署层、业务接口层、命令拦截层、命令层和行为层。 基于关系型数据库层面优化 MySQL建表语句优化 Activiti在MySQL中创建默认字符集为utf8&…...
安卓 文件管理相关功能记录
文件管理细分为图片、视频、音乐、文件四类 目录 权限 静态声明权限 动态检查和声明权限方法 如何开始上述动态申请的流程 提示 图片 获取图片文件的对象列表 展示 删除 视频 获取视频文件的对象列表 获取视频file列表 按日期装载视频文件列表 展示 播放 删除…...
监控视频汇聚融合云平台一站式解决视频资源管理痛点
随着5G技术的广泛应用,各领域都在通信技术加持下通过海量终端设备收集了大量视频、图像等物联网数据,并通过人工智能、大数据、视频监控等技术方式来让我们的世界更安全、更高效。然而,随着数字化建设和生产经营管理活动的长期开展࿰…...
【jvm】主要参数
Java 虚拟机(JVM)有许多参数用于控制其行为和性能,下面是一些 主要的 JVM 启动参数,这些参数通常分为以下几类: 内存管理相关参数 这些参数主要用来配置 JVM 的内存分配策略、堆内存、栈内存等。 -Xms 设置 JVM 启动…...
在Ubuntu中配置mysql,并允许外部访问数据库
在虚拟机中安装 MySQL 并允许外部访问,可以按照以下步骤操作: 1. 更新系统包 首先,确保你的系统是最新的,使用以下命令更新包列表: sudo apt update sudo apt upgrade2. 安装 MySQL Server 安装 MySQL 服务&#x…...
Golang的向前兼容性和toolchain规则,Go1.21.0
在 Go 1.21 中,在工具上新增了两个变化:增强了向前兼容性;工具链管理。 向前兼容性 在以前的版本中,Go 工具链尝试编译依赖于新版本的代码时,可能会遇到兼容性问题。例如,如果你的代码依赖于 Go 1.18 引入…...
如何有效修复ffmpeg.dll错误:一站式解决方案指南
当您遇到提示“ffmpeg.dll文件丢失”的错误时,这可能导致相关的应用程序无法启动或运行异常。本文将详细介绍如何有效地解决ffmpeg.dll文件丢失的问题,确保您的应用程序能够恢复正常运行。 ffmpeg.dll是什么?有哪些功能? ffmpeg.…...
更频繁的 Android SDK 发布:更快的创新、更高的质量和更完善
Android 一直致力于让创新更快地进入用户手中。除了每年的平台发布之外,我们还投资了Project Treble、Mainline、Google Play 服务、每月安全更新和季度发布,为 Pixel Drops 提供支持。 未来,Android 将更频繁地发布 SDK,计划于 …...
远程连接:构建智能家居舒适生活
远程连接技术让智能家居从梦想照进现实,为人们构建了舒适便捷的生活环境。通过家庭网络与各种智能设备的远程连接,用户可以在外出时,使用手机 APP 轻松控制家中的灯光、窗帘、空调、电视等设备。 例如,在炎热的夏天,下…...
Python 爬取网页文字并保存为 txt 文件教程
引言 在网络数据获取的过程中,我们常常需要从网页中提取有用的文字信息。Python 提供了强大的库来帮助我们实现这一目标。本教程将以https://theory.gmw.cn/2023 - 08/31/content_36801268.htm为例,介绍如何使用requests库和BeautifulSoup库爬取网页文字…...
多协议视频监控汇聚/视频安防系统Liveweb搭建智慧园区视频管理平台
智慧园区作为现代化城市发展的重要组成部分,不仅承载着产业升级的使命,更是智慧城市建设的重要体现。随着产业园区竞争的逐渐白热化,将项目打造成完善的智慧园区是越来越多用户关注的内容。 然而我们往往在规划前期就开始面临众多难题&#…...
InnoDB 查询成本
1. 单表查询成本 连接查询总成本 IO 成本 CPU 成本对于 InnoDB 存储引擎来说,页是磁盘和内存之间交互的基本单位,设计MySQL的大叔规定读取一个页面花费的成本默认是 1.0,读取以及检测一条记录是否符合搜索条件的成本默认是 0.2。1.0、0.2 …...
C++的高精度减法 分步详解
高精度减法计算原理 在读小学时,我们做减法都采用竖式方法,如图 1 所示。 这样,我们可以写出两个整数相减的算法。 我们就可以用 C 语言来模拟这个竖式减法的过程。我们可以考虑利用 C 的数组来存储对应数据,假设用数组 A 存储被…...
linux cpu 管理
视频教程:ubuntu cpu 管理_哔哩哔哩_bilibili 概述 平均负载,CPU 使用率,CPU上下文 1 平均负载 #查看命令: rootzyb:~# uptime 18:21:47 up 1:09, 2 users, load average: 0.00, 0.00, 0.00 依次则是过去 1 分钟、5 分钟、1…...
大批量URL去重的架构设计(redis-bitmap+redisson)
1. 引言 什么是数据去重? 在大数据处理中,去重是指消除重复数据,只保留唯一的数据记录。 去重的重要性 提高数据处理效率,节省存储空间,提升数据分析的准确性。 常见的去重技术 基于哈希函数、布隆过滤器、位图等方法…...
WebGPU跨平台应用开发
对于 Web 开发人员来说,WebGPU 是一个 Web 图形 API,可提供对 GPU 的统一和快速访问。WebGPU 公开了现代硬件功能,并允许在 GPU 上进行渲染和计算操作,类似于 Direct3D 12、Metal 和 Vulkan。 虽然这是真的,但这个故事…...
Proteus(8.15)仿真下载安装过程(附详细安装过程图)
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 前言 一、Proteus是什么? 二、下载链接 三、下安装步骤 1.解压,有键管理员运行 2.点击Next,进行下一步 3.勾选I accept…&#…...