【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语言对于文件写入有这几种方式:fputcfputsfwritefprintfsnprintf(大家可以去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开始递增呢?难道下标01、``2存储了其他被打开文件的地址吗?你的猜测是正确的!

在C语言中,默认情况下,当一个进程启动时,操作系统会打开三个标准流(本质上就是文件,不同的编程语言都会打开它的三个标准流)

  • stdin:标准输入,文件描述符 0。通常用来接收用户的输入,主要是键盘设备。

  • stdout:标准输出,文件描述符 1。通常用来输出程序的正常运行信息,主要是显示器设备。

  • stderr 标准错误,文件描述符 3。通常用来输出程序的错误信息,stderr 默认也将错误信息显示在终端上。主要也是显示器。

请添加图片描述

我们可以来验证:

请添加图片描述

FILEC语言封装文件操作的结构体,当你使用 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。当应用程序调用文件操作函数时,操作系统根据文件对象的实际类型来调用相应的方法,这种行为类似于多态的表现,即同一个接口可以根据不同的对象类型展现出不同的行为。

因此,一切皆文件可以被视为在操作系统级别实现的一种多态思想,使得不同类型的资源都能够以统一的方式进行访问和管理。

六、相关代码

本篇博客相关代码:点击跳转

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/630237.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【easyX】动手轻松掌握easyX 1

01 简单绘图 在这个程序中&#xff0c;我们先初始化绘图窗口。其次&#xff0c;简单绘制两条线。 #include <graphics.h>//绘图库头文件 #include <stdio.h> int main() {initgraph(640, 480);//初始化640✖480绘图屏幕line(200, 240, 440, 240);//画线(200,240)…

NAT技术总结与双向NAT配置案例

NAT的转换方式&#xff1a; 1.静态转换&#xff1a;固定的一对一IP地址映射。 interface GigabitEthernet0/0/1 ip address 122.1.2.24 nat static global 122.1.2.1 inside 192.168.1.1 #在路由器出接口 公网地址 私网地址。 2.动态转换&#xff1a;Basic NAT nat address-gr…

centos7下使用docker安装fastdfs服务

先查看容器是否已经存在 docker ps -a 删除掉之前的tracker及storage服务 docker rm tracker docker rm storage 1、没有镜像先下载镜像 docker pull morunchang/fastdfs 2、运行服务 a、不指定物理服务器路径 docker run -d --name tracker --nethost morunchang/fastdfs sh…

【Linux】系统登录,调用shell,shell配置文件,shell命令,特殊符号,shell快捷键,Linux运行级别,解决无限登录问题,修改提示符

目录 Linux系统的登录方式 以及 调用shell Linux shell 以及 shell配置文件 shell 命令 shell 特殊符号 shell 快捷键 Linux操作系统运行级别 单用户模式下解决无限登录问题 centos7修改命令行提示符 PS1 补充、centos7没有滚动条 Linux系统的登录方式 以及 调用shell…

AWS简介

AWS AWS&#xff0c;全称为Amazon Web Services&#xff0c;是亚马逊公司旗下的云计算服务平台&#xff0c;自2006年起向全球用户提供广泛而深入的云计算服务。AWS是全球最全面、应用最广泛的云平台之一&#xff0c;它从全球的数据中心提供超过200项功能齐全的服务&#xff0c…

每周一算法:恰好经过K条边的最短路

题目描述 牛站 给定一张由 M M M 条边构成的无向图&#xff0c;点的编号为 1 ∼ 1000 1\sim 1000 1∼1000 之间的整数。 求从起点 S S S 到终点 E E E 恰好经过 K K K 条边&#xff08;可以重复经过&#xff09;的最短路。 注意: 数据保证一定有解。 输入格式 第 1 …

维护表空间中的数据文件

目录 向表空间中添加数据文件 从表空间中删除数据文件 删除users表空间中的users02.dbf数据文件 对数据文件的自动扩展设置 Oracle从入门到总裁:​​​​​​https://blog.csdn.net/weixin_67859959/article/details/135209645 维护表空间中的数据文件主要包括向表空间中添…

C#【进阶】委托和事件

委托和事件 文章目录 1、委托1、委托概念2、基本语法3、定义自定义委托4、使用自定义委托5、委托变量可以存储多个函数6、系统定义好的委托思考 怪物死亡数据更新 2、事件1、事件概念2、事件的使用3、为什么有事件思考 热水器 3、匿名函数1、匿名函数概念2、基本语法3、使用4、…

电工能混到这份上

最近看到某电工师傅发了一篇帖子&#xff0c;大致内容是他在处理一个简单故障的时候居然花了很长的时间。我们一起来看看他遇到的是什么故障吧! plc 控制的一台设备&#xff0c;行走部分靠 2 个脚踏开关控制&#xff08;内部开关量控制方向&#xff0c;电位器控制速度&#xff…

jspXMl标记语言基础

1.打开命令框进入数据库 打开eclipse创建需要连接的项目 粘贴驱动程序 查看驱动器 使用sql的包 int代表个 conlm代表列名 <%page import"java.sql.ResultSet"%> <%page import"java.sql.Statement"%> <%page import"java.sql.Connect…

fl studio试用版文件保存无法打开??一个方法教你免费打开!

前言 当下&#xff0c;各款编曲软件五花八门&#xff0c;而这其中最有声誉的必为FL Studio莫属 这个软件呢国人习惯叫他水果&#xff0c;拥有强大的录音、编曲、混音等功能&#xff0c;所以广受音乐圈欢迎。如今&#xff0c;大部分水果一旦有编曲所需&#xff0c;一般都要使用…

阿里云 服务之前设置的密钥登陆,关闭了密码登录,现在打开密码登录

通过网页远程链接 切换用户 sudo -i 输入vim /etc/ssh/sshd_config 进入配置文件 找到 将这一项设置为yes 重启系统 systemctl restart sshd.service

std::remove-----std::remove_if

std::remove和std::remove_if 是 C11 标准库中的一个算法函数. std::remove 作用 遍历一遍容器&#xff0c;将容器中所有不是指定元素的元素往前复制。 总之就是一句话&#xff1a; 把不该删除的移动到前面&#xff0c;后面的就是应该删除的。 注意&#xff1a; 1&#…

汇聚荣科技:拼多多上架商品后需要做页面推广吗?

在电商平台上&#xff0c;商品的曝光率和销量往往成正比。那么&#xff0c;当您在拼多多上架了新品&#xff0c;是不是就意味着坐等订单呢?答案显然是否定的。商品一旦上架&#xff0c;接下来需要做的就是通过有效的页面推广来增加商品的可见度&#xff0c;吸引潜在买家的注意…

Golang RPC实现-day02

导航 Golang RPC实现一、客户端异步并发多个请求1、 客户端结构体2、 一个客户端&#xff0c;异步发送多个请求&#xff0c;使用call结构体代表客户端的每次请求3、客户端并发多个请求4、客户端接收请求 Golang RPC实现 day01 我们实现了简单的服务端和客户端。我们简单总结一…

Pencils Protocol Season 2 收官在即,展望Season 3 及其权益

此前 Scroll 生态 LaunchPad &聚合收益平台 Pencils Protocol&#xff08;原 Penpad&#xff09;&#xff0c;推出了首个资产即其生态代币 PDD 的 Launch&#xff0c;Season 2 活动主要是用户通过质押 ETH 代币、组件战队等方式&#xff0c;来获得 Point 奖励&#xff0c;并…

mysql的explain

explain可以用于select&#xff0c;delete&#xff0c;insert&#xff0c;update的statement。 当explain用于statement时&#xff0c;mysql将会给出其优化器&#xff08;optimizer&#xff09;的执行计划。 通过explain字段生成执行计划表。下面来解析这个执行计划表的每一列…

正则表达式和sed

一、正则表达式 主要用来匹配字符串&#xff08;命令结果&#xff0c;文本内容&#xff09;&#xff0c; 通配符匹配文件&#xff08;而且是已存在的文件&#xff09; 基本正则表达式 扩展正则表达式 1.元字符 . 匹配任意单个字符&#xff0c;可以是一个汉字 […

【企业宣传片】拍摄思维提升,专业影视质感核心揭密,一课搞定

课程下载&#xff1a;【企业宣传片】拍摄-课程网盘链接提取码下载.txt资源-CSDN文库 更多资源下载&#xff1a;关注我。 课程介绍 大量案例分析宣传片拍摄的痛点要点 根据案例告诉你解决方案&#xff0c;讲透概念 改变你对企业宣传片的思维层级与认知 归纳总结对比不同案…

基于SSM的婚恋网站的设计与实现(有报告)。Javaee项目。ssm项目。

演示视频&#xff1a; 基于SSM的婚恋网站的设计与实现&#xff08;有报告&#xff09;。Javaee项目。ssm项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Spri…