【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. 关系…...
ssc377d修改flash分区大小
1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...
基于服务器使用 apt 安装、配置 Nginx
🧾 一、查看可安装的 Nginx 版本 首先,你可以运行以下命令查看可用版本: apt-cache madison nginx-core输出示例: nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...
鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/
使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题:docker pull 失败 网络不同,需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

企业如何增强终端安全?
在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...

关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...

用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...