【LInux】<基础IO> 文件操作 | 文件描述符 | 重定向
👦个人主页:Weraphael
✍🏻作者简介:目前正在学习c++和算法
✈️专栏:Linux
🐋 希望大家多多支持,咱一起进步!😁
如果文章有啥瑕疵,希望大佬指点一二
如果文章对你有帮助的话
欢迎 评论💬 点赞👍🏻 收藏 📂 加关注😍
目录
- 一、C语言文件操作
- 1.1 打开文件 --- fopen
- 1.2 关闭文件 --- fclose
- 1.3 文件写入 --- fwrite
- 二、文件系统调用
- 2.1 文件系统调用和函数的关系
- 2.2 打开文件 --- open
- 2.3 文件关闭 --- close
- 2.4 文件写入 --- write
- 三、文件描述符
- 3.1 什么是文件描述符
- 3.2 三个标准流
- 3.3 文件描述符的分配规则
- 3.4 引用计数
- 四、再谈重定向
- 4.1 输出重定向
- 4.2 追加重定向
- 4.3 输入重定向
- 4.4 系统调用接口 --- dup2
- 五、补充知识
- 5.1 stdout和stderr的区别
- 5.2 为什么Linux下一切皆文件(以源码的角度剖析)
- 六、相关代码
一、C语言文件操作
1.1 打开文件 — fopen
#include <stdio.h>
FILE* fopen(const char* path, const char* mode);
-
path
:要打开文件的相对路径或绝对路径。注意:如果不带路径默认会在当前进程所在路径下创建/打开文件。 -
mode
:打开文件的模式常用的模式包括:"r"
:只读模式。打开文件用于读取。注意:文件不存在表示打开文件失败。"w"
:写入模式。文件内容截断为零长度,即清空文件内容,再写入内容。(如果文件不存在,系统会新建对应的文件)"a"
:追加模式。不会清空原有文件内容,而在文件内容末尾追加。(如果文件不存在,系统会新建对应的文件)- 还有很多模式请查看手册:
man fopen
-
返回值
-
打开文件后,将返回一个指向
FILE
类型的文件指针,指向打开的文件流。 -
如果打开失败,则返回
NULL
。
-
为什么不带路径默认会在当前进程所在路径下创建文件?为什么不在其他路径创建文件?
首先大家需要明白一个道理:文件一定是由进程通过调用函数(如fopen()
)打开的,因此,文件与进程有关。所以,默认情况下,如果你不带路径,新建文件所处的路径将取决于进程当前的工作目录。
当然了,如果你的程序在运行时改变了当前工作目录,那么新建文件所处的路径也会相应地改变。
1.2 关闭文件 — fclose
在C
语言中,当你完成了对文件的读写操作后,最后应该使用fclose
函数关闭文件。这是一个很重要的步骤,因为它确保了操作系统释放文件资源,并且在某些情况下,确保了写入的数据被刷新到磁盘上。不关闭文件可能会导致资源泄露或数据丢失。
int fclose(FILE* stream);
-
如果成功关闭文件,
fclose
函数返回0
。 -
如果关闭失败,返回
EOF
(-1
),表示出现了错误。
1.3 文件写入 — fwrite
C
语言对于文件写入有这几种方式:fputc
、fputs
、fwrite
、fprintf
和 snprintf
(大家可以去man
手册查看用法)
int fputc (int character, FILE* stream);
int fputs (const char* str, FILE* stream);
int snprintf ( char* s, size_t n, const char* format, ...);
这里以fwrite
函数为例
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
这个函数将 nmemb
个元素,每个元素大小为 size
字节,从指针 ptr
所指向的内存块写入到给定的文件流 stream
中。
-
ptr
:指向待写入数据的指针。 -
size
:数据写入的字节数。 -
nmemb
:以size
为单位,待写入数据的数量。 -
stream
:指向FILE
对象的指针。 -
返回值:如果返回值与
nmemb
不相等,说明写入时发生错误。
这里有一个细节问题:strlen
需要+ 1
将’\0‘
写入到log.txt
文件中吗?
我们执行以上代码看看log.txt
里的内容(不+ 1
)
然后我们再+ 1
看看效果
后面多了一个类似于乱码的字符^@
,这其实就是'\0'
的二进制。因为vim
是一个文本编辑器,对于二进制来说当然显示的是乱码啦。 这也说明了我们在向文件写入字符串的时候不需要处理'\0'
(只需将字符串的内容写入即可),因为字符串以'\0'
结尾是编程语言的规定,和文件没半毛钱关系 ~
接下来我们再连续执行程序,再看看log.txt
的内容
我们不是向文件中写入了多个字符串hello file
吗?为什么只写入了一个?
这是因为我们设置打开文件的模式是w
,即在向文件写入之前会先对文件进行清空处理,然后再写入。
这不由得让我们联想到输出重定向>
因此输出重定向>
的底层一定要以w
的方式打开一个文件,即fopen("文件/文件路径", "w")
,即将文件内容清空,最后再用写入函数进行向文件写入。
接下来我们再以a
的方式打开一个文件并写入
我们发现:以a
的方式打开一个文件并写入,不会清空文件,而是在文件内容末尾追加。
这不由得让我们联想到追加重定向>>
因此追加重定向>>
的底层一定要以a
的方式打开一个文件,即fopen("文件/文件路径", "a")
,即不将文件内容清空,最后再用任意一个写入函数向文件内容进行追加。
综上所述,输出重定向>
和追加重定向>>
主要区别就是在于打开文件的方式不同,一个以w
,一个以a
。
二、文件系统调用
2.1 文件系统调用和函数的关系
我们知道,文件是在磁盘上存储的,磁盘作为外设(外部设备),所以访问文件其实也是在访问磁盘(硬件)!而我们计算机体系结构是分层的,如下所示:
而我们知道底层硬件一定要被操作系统管理的,作为普通用户无法直接访问底层硬件的相关信息,那么就只能通过管理者,也就是操作系统来获取,而操作系统根本不相信用户,因此提供了系统调用接口来访问,以此来保护操作系统。因此,几乎所有的库函数只要访问硬件设备,必定要封装系统调用接口。因此,以上文件操作的函数底层必定封装了文件系统调用接口!
2.2 打开文件 — open
在Linux
中,open
函数是一个系统调用,用于打开或创建文件。
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>// 通常用于打开已存在文件
int open(const char *pathname, int flags); // 通常用于打开不存在文件
int open(const char *pathname, int flags, mode_t mode);
-
pathname
:要打开或创建的文件的路径。不指定路径默认是当前进程的工作路径。 -
flags
:控制文件打开方式。以下是常见的打开方式。(还有很多打开方式,可以通过man 2 open
来查看)O_WRONLY
:以只写模式打开文件。O_CREAT
:如果文件不存在,则创建文件。O_APPEND
:在写入时将数据追加到文件的末尾。O_TRUNC
:清空文件内容。
实际上,以上的选项是在
<fcntl.h>
头文件中定义的宏。我们可以在路径/usr/include/bits
查看,此路径通常包含了与体系结构相关的宏定义和声明。
-
mode
:用于指定新创建文件的权限,只有在O_CREAT
标志位被设置时才有效。一般采用八进制表示的文件权限值,例如0666
。 -
返回值:
-
如果成功,返回一个文件描述符(非负整数),该描述符可以在后续的读写操作中传参。
-
如果失败,返回
-1
。
-
当我们将程序运行起来,发现open
打开文件失败,原因是:O_WRONLY
只会读文件,而不会新建文件。那就非常简单了,再加一个宏O_CREAT
,让文件不存在时自动创建即可。可是,open
的第二个参数flag
是整型,如何传两个参数?
这就要涉及到比特位方式的标志位传递方式。
还记得诸如O_WRONLY
这些宏吗?它们的共同特点:二进制序列中最多只有一个比特位上是1
,并且1
所处的比特位是不同的。而一个整型是4
个字节,也就是32
个比特位(标志位),那么我们可以使用按位或|
运算符来组合多个标志位。比如0001 | 0010 = 0011
。然后open
函数内部实现可以使用按位与操作符&
来检查是否设置了某个标志位,比如
因此,我们可以对一开始的代码进行修改,使用按位或|
增加O_CREAT
选项
如上,我们确实把一个不存在的文件log.txt
创建好了,可是此文件的权限都是乱码,原因在于你新建一个文件,此文件要受Linux
权限约束,你新建文件的权限必须得告诉操作系统。因此,只有在 O_CREAT
标志位被设置时,需要指定新文件的权限。
在往期博客讲过,文件默认的权限是0666
,即rw-rw-rw-
文件创建出来了,并且权限也不是乱码了,但是,权限并不是我们一开说的rw-rw-rw-
。实际上创建出来的文件会收到文件默认权限掩码umask
的影响,实际创建出来文件的权限值为:mode & (~umask)
;而在Linux中,umask
的默认权限值为0002
,当我们设置mode
值为0666
时实际创建出来的文件权限为0666 & ~(0002) = 0664
,即rw-rw-r--
。
若想创建出文件的权限值不受umask
的影响,即如上想让权限为rw-rw-rw-
,那么系统专门提供了 umask
系统调用接口,可以让你修改默认的权限掩码。
即在创建文件前使用umask
函数将文件掩码umask
设置为0
。
2.3 文件关闭 — close
#include <unistd.h>
int close(int fd);
-
fd
是要关闭的文件描述符,即open
函数的返回值。 -
函数返回值为
0
表示成功关闭文件,返回-1
表示出现错误
关闭文件描述符后,相关的系统资源将被释放,包括文件表项和文件描述符本身。这通常是在不再需要使用文件描述符时执行的操作,以释放系统资源并防止资源泄漏。
2.4 文件写入 — write
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
fd
是文件描述符(open
函数返回值),表示要写入的文件。buf
是一个指向要写入数据的缓冲区的指针。count
是要写入的字节数。- 返回值是写入的字节数,如果出现错误,则返回
-1
,
如果想要实现输出重定向的功能,不仅需要读O_WRONLY
、创建文件O_CREAT
,在写之前还需要将文件清空O_CREAT
如果想实现追加重定向也非常简单,由于清空和追加两个是冲突的,因此你只需要将清空O_CREAT
替换成追加O_APPEND
【总结】
因此,只要是在 Linux
平台中编写的程序,无论是什么编程语言,在进行文件相关操作时,其文件操作函数都有封装系统调用接口。也就是说,要想与硬件(磁盘)打交道,必须经过 系统调用 -> 操作系统 -> 硬件 这条路线,否则无法直接与硬件进行交互。
三、文件描述符
3.1 什么是文件描述符
到目前为止,我们所知道的文件描述符就是open
函数的返回值(非负整数),这个描述符可以在后续的读写操作中用作文件标识符,即找到对应的文件。
那不知道大家有没有思考过一个问题:为什么操作系统可以单单通过一个整数(文件描述符)就能找到对应的文件?
文件分为打开的文件和没打开的文件(这里先讨论打开的文件,等到文件系统再谈没打开的文件)。打开的文件是由进程使用函数(如fopen()
)打开的。根据冯诺依曼体系结构,被打开的文件一定会被加载到内存。而一个进程可以打开多个文件(1:n
),那么被打开的文件也一定要受操作系统的管理,那就要请出管理的六字真言:先描述,后组织。
-
描述:一个被打开的文件一定要有自己的文件结构体对象
file
,包含文件的信息,即struct file { 文件信息; struct file* next; struct file* prev;};
-
组织:通过双链表方式。
-
往后对被打开文件的管理,就转换成为了对链表的增删改查!
所以,当进程打开文件时,操作系统会在内核中创建数据结构来描述这个已打开的文件对象(和PCB
类似)。这个数据结构通常被称为 file
或其他类似的名字,它包含了文件的各种信息,如文件位置、权限、状态等。
而进程可以打开多个文件,那进程PCB
结构体对象就要存储哪些文件是由哪一个进程打开的。因此,每个进程PCB
对象都要和打开的文件建立关系!所以进程PCB
对象其实有一个指针struct files_struct* files
,这个指针指向结构体files_struct
,而这个结构体包含一个指针数组struct file* fd_array[]
,这个数组我们可以称之为文件描述符表。数组中的每个元素都是指向当前进程所打开文件的指针(地址)!
所以,本质上文件描述符就是指针数组的下标(索引)。所以,只要拿着文件描述符,就可以找到对应的文件。
【源码】
我们可以打印出文件描述符来看看
3.2 三个标准流
如上,文件描述符即指针数组的下标是从3
开始连续递增的。那这里我有一个问题:为何不从0
开始递增呢?难道下标0
、1、``2
存储了其他被打开文件的地址吗?你的猜测是正确的!
在C语言中,默认情况下,当一个进程启动时,操作系统会打开三个标准流(本质上就是文件,不同的编程语言都会打开它的三个标准流)
-
stdin
:标准输入,文件描述符0
。通常用来接收用户的输入,主要是键盘设备。 -
stdout
:标准输出,文件描述符1
。通常用来输出程序的正常运行信息,主要是显示器设备。 -
stderr
标准错误,文件描述符3
。通常用来输出程序的错误信息,stderr
默认也将错误信息显示在终端上。主要也是显示器。
我们可以来验证:
FILE
是C
语言封装文件操作的结构体,当你使用 C 标准库中的函数来操作文件时,这些库函数底层必定会封装系统调用接口,那么FILE
结构体内部一定要有对应的文件描述符来与操作系统进行通信,即需要有文件描述符来调用底层封装的系统调用接口,因此FILE
结构体里一定会包含文件描述符成员_fileno
(其他编程语言的文件操作也是如此)
3.3 文件描述符的分配规则
如果是直接打开文件某个文件,由于系统默认会打开三个标准流,因此新分配的文件描述符从3
开始依次递增。
如果我在打开log.txt
文件之前,把标准输入stdin
关闭,其文件描述符还会是3
吗?
我们发现:新文件的文件描述符占据了标准输入stdin
的文件描述符。因此,文件描述符的分配规则是:从头遍历文件描述符表fd_array[]
,找到一个最小的且没有被使用的下标,它的下标就是新文件的文件描述符(保证数组空间不会被浪费)。
3.4 引用计数
如果我这里故意将文件标识符1
给关掉,即显示器文件被关闭,那么打印结果就无法显示到屏幕上
那如果我在文件标识符1
关掉的基础上,再向stderr
流写入,即向显示器写入,还能写入成功吗?有的人想,肯定不成功,文件标识符1关掉,等同将显示器文件关掉,而stderr
也是将结果显示在显示器,肯定打印不出来
我们发现:结果可以打印出来。
其实每个文件对象都包含一个引用计数字段count
,记录了有多少个文件描述符指向该文件对象。当一个进程打开一个文件时,内核会增加该文件对象的引用计数count++
。当进程关闭文件描述符时,内核会减少相应文件对象的引用计数count--
,并且将文件描述符表对应下标的位置置空NULL
。只有当引用计数减少到零时,内核才会释放该文件对象及其相关资源。
四、再谈重定向
重定向实际上是改变了进程的文件描述符表中指针数组对应下标内容的指向。这样,进程在进行I/O
操作时,就会按照新的文件描述符表中的指向来进行,从而实现了重定向的效果。
常见的重定向操作包括
-
将一个文件描述符指向另一个文件描述符
-
或者将一个文件描述符关闭。
4.1 输出重定向
输出重定向是指将程序本来输出到标准输出
stdout
设备的内容,重定向到其他文件
此时,我们发现,本来应该输出到显示器上的内容,输出到了文件log.txt
当中,这不就是典型的输出重定向!
接下来我们来分析,为什么会出现这种情况
代码中,首先将stdout
文件关闭,而后打开log.txt
文件。根据文件描述符的分配规则是:从头遍历文件描述符表fd_array[]
,找到一个最小的且没有被使用的下标,它的下标就是新文件的文件描述符(保证数组空间不会被浪费)。那么log.txt的的文件描述符就是1
,而后面写入文件是向文件描述符1
中写入,即就是向log.txt
文件写入。这就是重定向的原理。
4.2 追加重定向
追加重定向是指将程序本来输出到标准输出
stdout
设备的内容,追加到指定文件的末尾,而不是覆盖原文件内容。
那我们只需将以上代码的打开方式O_TRUNC
修改成O_APPEND
就有追加重定向的效果
4.3 输入重定向
输入重定向是指将程序从标准输入
stdin
中读取数据的方式改变为从其他文件读取数据
例如,让本应该从“键盘文件”读取数据,改从log.txt
文件中读取数据,那么我们可以打开log.txt
文件之前将stdin
文件关闭,这样一来,根据文件描述符的分配规则,当我们后续打开log.txt
文件时所分配到的文件描述符就是0
。
4.4 系统调用接口 — dup2
以上操作都需要先关闭再打开一个文件来实现重定向,操作过于繁琐,而且每次你写这样的代码都要向别人解释,因此操作系统提供了系统调用接口来实现重定向操作
#include <unistd.h>
int dup2(int oldfd, int newfd);
-
oldfd
:是要复制的文件描述符。 -
newfd
:是要被覆盖的文件描述符。 -
如果
newfd
已经打开,则操作系统首先会关闭newfd
,即释放文件对象。然后,dup2()
会使newfd
指向oldfd
所指向的文件对象。
下面是演示了如何使用 dup2()
函数将标准输出重定向到一个文件中:
下面是演示了如何使用 dup2()
函数将标准输出追加重定向到一个文件中:
下面是演示了如何使用 dup2()
函数将标准输入重定向到一个文件中:
为往期模拟实现bash
添加重定向功能:点击跳转
五、补充知识
5.1 stdout和stderr的区别
我们至今所认知的标准输出流和标准错误流并没有区别,都是将数据向显示器打印。
但若是将程序运行结果重定向输出到文件hello.txt
当中,我们会发现hello.txt
文件当中只将标准输出的打印语句重定向到hello.txt
文件中,而向标准错误流输出的两行数据并没有重定向到文件当中,而是仍然输出到了显示器上。
实际上我们使用重定向时,默认重定向的是文件描述符是1
的标准输出流,而并不会对文件描述符是2
的标准错误流进行重定向。
此外,我们也可以将标准错误流进程重定向,通常使用 2>
或 2>>
来重定向 stderr
。详细命令如下:
./proc 1> hello.txt 2>stderr.txt
//不要在重定向操作符和文件描述符之间添加空格。
// 1可以被省略,因为它是默认的输出流。
上述指令做了两次重定向,第一次把标准输出重定向到了文件描述符为1的显示器,第二次是把标准错误重定向到了文件描述符为2的显示器,,通过重定向可以分别将它们发送到不同的目的地,使得对程序输出和错误信息的处理更加灵活和有效。
前面已经提到,重定向只会默认把标准输出的进行处理,并不会重定向标准错误,如果我想让标准输出和标准错误一同混合起来到一个文件显示,如下命令:
./myfile 1>all.txt 2>&1
这个命令将 myfile
的标准输出重定向到 all.txt
文件,2>&1
是将标准错误重定向到与标准输出相同的地方,也就是all.txt
文件中。
5.2 为什么Linux下一切皆文件(以源码的角度剖析)
一切皆文件其实是在Linux
系统中一致访问资源的方式,即将所有资源抽象为文件。这包括了硬件设备等各种资源。(文件很容易理解,这里主要谈为什么硬件也要当做文件来看待)
当一个进程在Linux
系统中运行时,操作系统会为每个文件创建一个文件对象struct file
,这个文件对象跟踪了该文件的状态和相关信息。
因此,当一个进程打开硬件,那么操作系统就会管理这个硬件,即为该硬件创建文件对象struct file
,而此文件对象其实提供了对设备的操作接口。
f_op
指向对文件操作的各种函数指针。这些函数指针对应了文件的不同操作,例如读取、写入、定位等。
所以所谓的一切皆文件,就是相当于在文件这一层封装了一个文件对象,让文件对象中的函数指针结构体 file_operations
指向不同设备的操作方法。在这种情况下,不同类型的文件对象(比如普通文件、设备文件等)都具有相同的接口,即结构体file_operations
。当应用程序调用文件操作函数时,操作系统根据文件对象的实际类型来调用相应的方法,这种行为类似于多态的表现,即同一个接口可以根据不同的对象类型展现出不同的行为。
因此,一切皆文件可以被视为在操作系统级别实现的一种多态思想,使得不同类型的资源都能够以统一的方式进行访问和管理。
六、相关代码
本篇博客相关代码:点击跳转
相关文章:

【LInux】<基础IO> 文件操作 | 文件描述符 | 重定向
👦个人主页:Weraphael ✍🏻作者简介:目前正在学习c和算法 ✈️专栏:Linux 🐋 希望大家多多支持,咱一起进步!😁 如果文章有啥瑕疵,希望大佬指点一二 如果文章对…...
MySQL--增、删、改、查,
数据库的概述、发展、现状、历史、分类 MySQL关系型数据库、架构(C/S) window系统安装MySQL数据库 Linux系统【选学】 数据库对象——数据库(database) show、create、drop命令 数据库对象——表(tableÿ…...

5.12学习总结
一.JAVA聊天室项目 文件发送 使用 Java Socket 实现聊天内容或文件的传输的原理如下: 服务器端启动:聊天室的服务器端在指定的端口上监听客户端的连接。它创建一个 ServerSocket 对象,并通过调用 accept() 方法等待客户端的连接请求。客户…...

ansible利用playbook 部署lamp架构
搭建参考:ansible批量运维管理-CSDN博客 定义ansible主机清单 [rootansible-server ~]# vim /etc/hosts 192.168.200.129 host01 192.168.200.130 host02 [rootansible-server ~]# vim /etc/ansible/hosts [webserver] host01 host02 在ansible端编写index.html…...

SPI通信(使用SPI读写W25Q64)
SPI通信协议 • SPI(Serial Peripheral Interface)是由Motorola公司开发的一种通用数据总线 • 四根通信线: SCLK:串行时钟线,用来提供时钟信号的。 MOSI:主机输出,从机输入 MISO:从机输出,主机输入 SS:…...
<sa8650>QCX Usecase 使用详解—拓扑图 XML 定义
<sa8650>QCX Usecase 使用详解—拓扑图 XML 定义 一 、前言二、拓扑图 XML 定义2.1 <Node, port, link>2.2 < XML prolog >2.3 < UsecaseDef >2.4 < Usecase>2.5 < Targets>2.5.1 < Target>2.5.2 < Range>2.6 < Pipeline>2.…...
使用C++11实现Golang的defer功能
本文主要用C11标准来实现Golang的defer功能。 背景 目前笔者的主力语言是Golang,其次是C,再次是JS、Delphi。在Golang工程中大量使用了defer关键字实现函数的延迟调用。如打开文件的出错处理。近来在C工程中遇到类似需求,在函数返回时进行某…...

前端之电力系统SVG图低代码
其实所有的图形都是由点,线,面组成的。点线面可以组成一个设备。下面就简单讲讲点线面是怎么画的吧 对于线,可以用path <g><path:d"M ${beginX},${beginY} L ${endX},${endY}":stroke-width"lineWidth":strok…...

括号生成[中等]
优质博文:IT-BLOG-CN 一、题目 数字n代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。 示例 1: 输入:n 3 输出:["((()))","(()())","(())(…...
配置ubuntu的VNC时遇到报错_XSERVTransmkdir: Mode of /tmp/.X11-unix should be set to 1777
现在win11内嵌了ubuntu系统,我在根据打造基于 VNC 的 Ubuntu 20.04 的远程桌面 配置VNC server时,到了 vncserver :1 这一步,遇到报错: vncserver: /usr/bin/Xtigervnc did not start up, please look into /root/.vnc/xxxxx.:1.…...

openstack部署nova中出现的问题:
[rootcontroller nova]# su -s /bin/sh -c “nova-manage db sync” nova /usr/lib/python2.7/site-packages/pymysql/cursors.py:170: Warning: (1831, u’Duplicate index block_device_mapping_instance_uuid_virtual_name_device_name_idx. This is deprecated and will be…...
【OpenCV 基础知识 3】边缘检测
文章目录 cvCanny完整示例代码 cvCanny 这行代码使用OpenCV库中的 cvCanny 函数对灰度图像进行边缘检测。让我解释一下: cvCanny(gray, dst, 10, 100, 3);gray: 这是输入的灰度图像,即要进行边缘检测的图像。dst: 这是输出的边缘图像,即将结…...
拓宽知识储备量(指数级成长)
对于增强自己的知识储备,不是什么知识都往脑袋里去塞,最好的办法就是让自己的心态回到自己初心的时候,始终保值一颗学者的心,你像那些成功人士,比如格力,华为,腾讯等这样的大公司创始人哪个不是…...

x264 帧类型代价计算原理:slicetype_mb_cost 函数分析
slicetype_mb_cost 函数 函数功能 计算每个宏块 MB 的代价 cost。函数参数分析 x264_t *h:全局编码结构体x264_mb_analysis_t *a:宏块分析结构体x264_frame_t **frames:系列帧数据结构体int p0:帧序号之一,一般指向靠前帧int p1:帧序号之一,一般指向靠后帧int b:帧标志…...

战网国际服加速器哪个好用 暴雪战网免费加速器分享
战网国际服(Battle.net International或Battle.net Global)是由暴雪娱乐公司(Blizzard Entertainment)运营的面向全球玩家的多人在线游戏平台。与专注于特定地区的版本不同,国际服允许玩家不受地域限制地访问暴雪的多款…...

Java入门基础学习笔记26——break,continue
跳转关键字: break: 跳出并结束当前所在循环的执行。 continue: 用于跳出当前循环中的当次执行,直接进入循环中的下一次执行。 package cn.ensource.loop;public class BreakContinueDemo8 {public static void main(String[] a…...

HNU-算法设计与分析-作业6
第六次作业【分支限界法】 文章目录 第六次作业【分支限界法】<1> 算法实现题6-2 最小权顶点覆盖问题<2> 算法实现题6-6 n后问题<3> 算法实现题6-7 布线问题 <1> 算法实现题6-2 最小权顶点覆盖问题 ▲问题重述 问题描述: 给定一个赋权无向…...

2D Chests Assets - Mega Pack
科幻/奇幻/经典主题的箱子和容器。AAA质量,高分辨率,VFX,源PSD文件。 这是一个带有手绘套装的大包装: -【梦幻之栗】 -【科幻钱包】 AAA质量。高分辨率。一切都已准备就绪,可供使用。包括PSD文件。 在1.1版本中添加了VFX并将项目更新为URP。请注意,新的VFX仅适用于URP/HD…...

一种基于电场连续性的高压MOSFET紧凑模型,用于精确表征电容特性
来源:A Compact Model of High-Voltage MOSFET Based on Electric Field Continuity for Accurate Characterization of Capacitance(TED 24年) 摘要 本文提出了一种新的高压MOSFET(HV MOS)紧凑模型,以消…...
vue阶段性测试题,内容丰富,案例典型,题目配有答案
阶段性测试 理论题实践题 1)理论题 请简述Vue、Node.js、Vscode是什么,以及有什么关系 1. vue是一个轻量级、比较灵活的且支持组件开发的网络框架 2. node.js是让JavaScript运行在服务器上的一直环境 3. Vscode是一款有着丰富插件的代码编辑器 4. 关系…...

铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...
Cesium1.95中高性能加载1500个点
一、基本方式: 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...

【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...

2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...

DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...