【Linux系统编程】基本IO函数

目录

    • 1、open 函数
    • 2、create 函数
    • 3、write 函数
    • 4、read 函数
    • 5、lseek 函数
    • 6、access 函数
    • 7、unlink 函数
    • 8、remove 函数
    • 9、fcntl 函数
      • 写锁互斥锁示例
      • 读锁共享锁示例

1、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
文件打开模式,用于指定打开文件的方式。以下是常用的标志:

必选标志(必须指定其中一个):

O_RDONLY:只读模式。 O_WRONLY:只写模式。 O_RDWR:读写模式。

可选标志(可以组合使用):

O_CREAT:如果文件不存在,则创建文件。
O_EXCL:与O_CREAT一起使用,如果文件已存在,则返回错误。
O_TRUNC:如果文件存在且为普通文件,则将其长度截断为 0。
O_APPEND:以追加模式打开文件,每次写操作都会将数据追加到文件末尾。
O_NONBLOCK:以非阻塞模式打开文件。
O_SYNC:每次写操作都会等待数据写入磁盘。

mode
当使用 O_CREAT 标志时,需要指定文件的权限模式(八进制表示)。例如:
0644:文件所有者可读写,其他用户只读。
0755:文件所有者可读、写、执行,其他用户可读、执行。

0664 的每一位含义如下:

第一位 0:忽略(通常用于特殊权限,如 SUID、SGID 等)。
第二位 6:文件所有者具有读 ® 和写 (w) 权限。
第三位 6:文件所属组具有读 ® 和写 (w) 权限。
第四位 4:其他用户具有读 ® 权限

通过umask命令查看系统权限掩码
在这里插入图片描述
mode的实际权限是减去权限掩码后的权限,比如创建时mode=0666,权限掩码是0002,那么实际的权限是0664。如果mode=0775,实际还是0775,因为umask的0002是去除w权限,而mode中的5是r-x不包含w权限,所以就不减去2,还是0775。

返回值

成功时,返回一个文件描述符(非负整数)。一般成功是3(因为0,1,2被stdinstdoutstderr占用了)

失败时,返回 -1,并设置 errno 以指示错误类型。

注意:
open()可以打开设备文件,但是不能创建设备文件

示例:
创建并打开一个新文件(读写模式)

#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>int main()
{const char *path = "hello.txt";int fd = open(path,O_WRONLY | O_CREAT | O_TRUNC,0664);if (fd < 0){perror("open file error");return -1;}printf("fd = %d\n",fd);close(fd);
}

2、create 函数

头文件

	   #include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>

函数定义

int creat(const char *pathname, mode_t mode);

参数说明、返回值
同上

文件权限

文件的实际权限由 mode 参数和当前进程的 umask 共同决定。
计算公式:实际权限 = mode & ~umask。
例如: 如果 mode 为 0666,umask 为 0022,则实际文件权限为 0644

注意事项

  • creat() 函数只能以只写模式(O_WRONLY)打开文件。如果需要以读写模式打开文件,应使用 open() 函数。
  • 如果文件已存在,creat() 会清空文件内容。如果需要保留文件内容,应使用 open() 函数,并避免使用 O_TRUNC 标志。
  • creat() 函数在现代编程中较少使用,通常直接使用 open() 函数替代。

与 open() 的关系

creat() 函数是 open() 函数的一个特例,以下两种调用是等价的:

int fd1 = creat("file.txt", 0644);
int fd2 = open("file.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);

示例

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>int main()
{int fd = creat("hello2.txt", 0664);if (fd < 0){perror("oppen file error");return -1;}close(fd);
}

3、write 函数

头文件

#include <unistd.h>

函数定义

ssize_t write(int fd, const void *buf, size_t count);

参数说明

fd:文件描述符,表示要写入的目标(例如文件、管道、套接字等)。
buf:指向要写入数据的缓冲区的指针。
count:要写入的字节数。

返回值

  • 成功时,返回实际写入的字节数(ssize_t 类型)。
  • 失败时,返回 -1,并设置 errno 以指示错误类型。

示例

#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>typedef struct student
{char name[16];int age;
}stu_t;int main()
{const char *path = "hello2.txt";int fd = open(path,O_WRONLY | O_CREAT | O_TRUNC,0664);if (fd < 0){perror("oppen file error");return -1;}printf("fd = %d\n",fd);
#if 1//操作char *str = "hello world\n";char buf[128] = "hello world";int len1 = write(fd,str,strlen(str));if(len1 < 0){perror("write error");close(fd);return -1;}int len2 = write(fd,str,sizeof(str));if(len2 < 0){perror("write error");close(fd);return -1;}printf("len1 = %d\n",len1);printf("len2 = %d\n",len2);
#endif#if 1stu_t stu = {"zhangsan",18};int len = write(fd,&stu,sizeof(stu_t));  if(len < 0){perror("write data error");close(fd);return -1;}printf("len = %d\n",len);   //20
#endifclose(fd);
}

4、read 函数

头文件

#include <unistd.h>

函数定义

ssize_t read(int fd, void *buf, size_t count);

参数说明

  • fd:文件描述符,表示要读取的目标(例如文件、管道、套接字等)。
  • buf:指向存储读取数据的缓冲区的指针。
  • count:要读取的最大字节数。

返回值

  • 成功时,返回实际读取的字节数(ssize_t 类型)。
  • 返回 0 表示已到达文件末尾(EOF)。 //可以判断是否为空文件
  • 失败时,返回 -1,并设置 errno 以指示错误类型。

示例

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>typedef struct student
{char name[16];int age;
} stu_t;int main()
{const char *path = "hello2.txt";int fd = open(path, O_RDONLY);if (fd < 0){perror("oppen file error");return -1;}printf("fd = %d\n", fd);#if 0       //循环读取char buf[5] = "";while (1){memset(buf,0,sizeof(buf));   //主要用于判断最后一次读的内容int len = read(fd, buf, sizeof(buf) - 1); // 尾0留一个字节if (len < 0){perror("read file error");close(fd);return -1;}if (len == 0) // len == 0 ,表示读到文件末尾break;printf("len = %d\n", len);printf("buf = %s\n", buf);}
#endif#if 1stu_t stu = {0};   //读取结构体内容int len = read(fd,&stu,sizeof(stu_t));if(len < 0){perror("read file error");close(fd);return -1;}printf("len = %d stu.name = %s stu.age = %d\n",len,stu.name,stu.age);
#endifclose(fd);
}

5、lseek 函数

头文件

	   #include <sys/types.h>#include <unistd.h>

函数定义

 off_t lseek(int fd, off_t offset, int whence);

参数说明

  • fd:文件描述符,表示要操作的文件。
  • offset:偏移量,表示要移动的字节数。 正数向右,负数向左
  • whence:基准位置,决定如何解释 offset 的值。它可以是以下常量之一:
    • SEEK_SET:从文件开头开始计算偏移量。
    • SEEK_CUR:从当前文件指针位置开始计算偏移量。
    • SEEK_END:从文件末尾开始计算偏移量。

返回值

  • 成功时,返回新的文件指针位置(从文件开头计算的字节数)。
  • 失败时,返回 -1,并设置 errno 表示错误原因。

注意事项

  • 对于普通文件,lseek() 允许将文件偏移量设置为超出文件末尾的位置。在这种情况下,后续的 write() 操作会扩展文件大小。
  • 对于管道、FIFO 或套接字,lseek() 不可用,因为这些设备不支持随机访问。
  • lseek() 不会导致 I/O 操作,它只是修改文件偏移量。

特殊用法

  • 获取文件大小:将文件偏移量移动到文件末尾,并返回当前偏移量。
off_t file_size = lseek(fd, 0, SEEK_END);
  • 扩展文件大小:将文件偏移量移动到超出文件末尾的位置,并写入数据。也叫空洞文件
    • 空洞文件的特性是:
      文件中存在未写入数据的区域(空洞)。
      这些空洞不会占用实际的磁盘空间。
      文件系统会记录文件的逻辑大小,但实际占用的磁盘空间只包括已写入数据的部分。
lseek(fd, 100, SEEK_END);
write(fd, "", 1);  // 扩展文件大小

示例

#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>int main()
{const char *path = "hello2.txt";int fd = open(path,O_RDWR,0664);if (fd < 0){perror("oppen file error");return -1;}printf("fd = %d\n",fd);#if 1// lseek(fd,1,SEEK_SET);lseek(fd,-2,SEEK_END);char buf[128] = "";read(fd,buf,sizeof(buf) -1);printf("buf = %s\n",buf);//获取文件大小int size = lseek(fd,0,SEEK_END);    //先移动到末尾,再获取当前的位置printf("%d\n",size);//创建空洞文件int size2 = lseek(fd,50,SEEK_SET);write(fd,"a",1);printf("%d\n",size2);#endif#if 0char *str = "aaaaaaaa";write(fd,str,strlen(str));lseek(fd,0,SEEK_SET);char buf[128] = "";read(fd,buf,sizeof(buf)-1);printf("buf = %s\n",buf);close(fd);
#endif
}

6、access 函数

头文件

#include <unistd.h>

函数定义

int access(const char *pathname, int mode);

参数说明

  • pathname:文件或目录的路径。
  • mode:检查的权限模式,可以是以下值的组合:
    • F_OK:检查文件是否存在。
    • R_OK:检查是否具有读权限。,而不是实际用户 ID 和实际组 ID。
    • X_OK: 检查是否有可执行权限
    • W_Ok: 检查是否有可写权限
  • 如果文件权限发生变化,access() 的结果可能会失效,因为它只是检查当前状态。
  • 如果文件是符号链接,access() 会检查符号链接指向的目标文件的权限。

返回值

  • 成功:返回 0,表示文件存在且具有指定的访问权限。
  • 失败:返回 -1,并设置 errno 为以下值之一:
    • EACCES:访问被拒绝。
    • ENOENT:文件或路径不存在。
    • ENOTDIR:路径中的某个部分不是目录。
    • EROFS:文件系统只读,无法写入。

注意事项

  • access 函数检查的是 当前进程 的权限,而不是文件的权限位。

  • 如果文件是符号链接,access 会检查链接指向的目标文件的权限。

  • 在多线程程序中,使用 access 可能会导致竞争条件(race condition),因为文件的状态可能在检查和使用之间发生变化。

示例

#include<stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>int main()
{// F_OK: check file exist or notif(access("hello.txt",F_OK) == 0){printf("hello.txt exist\n");}elseprintf("hello.txt not exist\n");//检查文件是否有读、写、执行权限if(access("hello.txt",W_OK | R_OK) == 0){printf("hello.txt have R_OK, W_OK\n");}elseprintf("hello.txt not have R_OK, W_OK\n");}

7、unlink 函数

头文件

#include <unistd.h>

函数定义

 int unlink(const char *pathname);

参数说明

  • pathname:要删除的文件的路径。

返回值

  • 成功时返回 0。
  • 失败时返回 -1

示例

#include <stdio.h>
#include <unistd.h>int main()
{//删除文件文件之前,判断文件是否存在if(access("hello2.txt",F_OK) == 0){int res = unlink("hello2.txt");if (res < 0){perror("unlink file error");return -1;}}}

8、remove 函数

头文件

#include <stdio.h>

函数定义

int remove(const char *pathname);

参数说明

  • pathname:要删除的文件的路径。

返回值

  • 成功时返回 0。
  • 失败时返回 -1

示例

#include <stdio.h>
#include <unistd.h>int main()
{  //remove 删除空目录if(access("dir",F_OK) == 0){int res = remove("dir");if (res < 0){perror("unlink file error");return -1;}}
}

9、fcntl 函数

头文件

 	   #include <unistd.h>#include <fcntl.h>

函数定义

int fcntl(int fd, int cmd, ... /* arg */ );

参数说明

  • fd:文件描述符,表示要操作的文件。
  • cmd:操作命令,指定要对文件描述符执行的操作。
  • arg:可选参数,具体内容取决于 cmd。

返回值

  • 成功时,返回值取决于 cmd。
  • 失败时,返回 -1。

常用命令(cmd)

- F_GETFL:获取文件状态标志(如 O_RDONLY、O_WRONLY、O_NONBLOCK 等)。

int flags = fcntl(fd, F_GETFL);

- F_SETFL:设置文件状态标志。

fcntl(fd, F_SETFL, flags | O_NONBLOCK); // 设置非阻塞模式

示例

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>int main()
{int fd = STDIN_FILENO;int flags = fcntl(fd,F_GETFL);//获取原来的flagsflags = flags | O_NONBLOCK; //O_NONBLOCK:非阻塞fcntl(fd,F_SETFL,flags);//把新的flags设置进去char buf[128] = "";// int len = 0;// while(1)// {// 	len = read(fd,buf,sizeof(buf) - 1);// 	printf("len = %d\n",len);// 	if(len > 0)// 	{// 		printf("len = %d  buf = %s\n",len,buf);// 		break;// 	}// 	sleep(1);// }// 重新改为阻塞flags = flags^O_NONBLOCK;//异或:相同为0  不同为1fcntl(fd,F_SETFL,flags);//重新设置新的falgsmemset(buf,0,sizeof(buf));read(fd,buf,sizeof(buf));printf("buf = %s\n",buf);}

文件锁结构体 struct flock

struct flock {short l_type;   // 锁类型:F_RDLCK(读锁)、F_WRLCK(写锁)、F_UNLCK(解锁)short l_whence; // 起始偏移的基准:SEEK_SET、SEEK_CUR、SEEK_ENDoff_t l_start;  // 起始偏移off_t l_len;    // 锁定长度pid_t l_pid;    // 持有锁的进程 ID(F_GETLK 时有效)
};

示例

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>int main()
{const char *path = "hello.txt";int fd = open(path,O_RDWR);if(fd < 0){perror("open file error");return -1;}struct flock rlock = {0};rlock.l_type = F_RDLCK;//读锁rlock.l_whence = SEEK_SET;  //文件开头rlock.l_start = 0;rlock.l_len = 0;  // 0表示锁整个文件rlock.l_pid = getpid(); //获取当前进程的进程号int res = fcntl(fd,F_SETLK,&rlock); //设置锁if(res < 0){perror("fcntl rlock error");close(fd);return -1;}struct flock lockstat = {0};fcntl(fd,F_GETLK,&lockstat);if(lockstat.l_type == F_RDLCK)printf("set read lock\n");else if(lockstat.l_type == F_WRLCK)printf("set write lock\n");else if(lockstat.l_type == F_UNLCK)printf("no lock\n");}

注意

  • 文件锁的作用范围:文件锁是基于进程的,不同进程之间的文件锁会相互影响。
  • 锁的类型:
    • 读锁(F_RDLCK):共享锁,允许多个进程同时获取读锁。
    • 写锁(F_WRLCK):互斥锁,只允许一个进程获取写锁。
  • 锁的继承:文件锁不会被子进程继承。

示例

写锁互斥锁示例

两个终端运行
读锁

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>//return value加锁成功返回0,失败返回-1
int setlock(int fd,short locktype)
{struct flock lock = {0};lock.l_type = locktype;  //读锁lock.l_whence = SEEK_SET;  //文件开头lock.l_start = 0;lock.l_len = 0;  // 0表示锁整个文件lock.l_pid = getpid(); //获取当前进程的进程号int res = fcntl(fd,F_SETLK,&lock); //设置锁// int res = fcntl(fd,F_SETLKW,&lock); //阻塞加锁if(res < 0){return -1;}return 0;
}int main()
{const char *path = "hello.txt";int fd = open(path,O_RDWR);if(fd < 0){perror("open file error");return -1;}//加锁// if (setlock(fd,F_RDLCK)<0)// {//     perror("set lock error");//     close(fd);//     return -1;// }while (setlock(fd,F_RDLCK)<0){perror("set lock error");sleep(1);}//读char buf[128] = "";read(fd,buf,sizeof(buf) - 1);printf("buf = %s\n",buf);getchar();//解锁if(setlock(fd,F_UNLCK) < 0){perror("unlock error");close(fd);return -1;}close(fd);}

写锁

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>//return value加锁成功返回0,失败返回-1
int setlock(int fd,short locktype)
{struct flock lock = {0};lock.l_type = locktype;  //读锁lock.l_whence = SEEK_SET;  //文件开头lock.l_start = 0;lock.l_len = 0;  // 0表示锁整个文件lock.l_pid = getpid(); //获取当前进程的进程号int res = fcntl(fd,F_SETLK,&lock); //设置锁// int res = fcntl(fd,F_SETLKW,&lock); //阻塞加锁if(res < 0){return -1;}return 0;
}int main()
{const char *path = "hello.txt";int fd = open(path,O_RDWR);if(fd < 0){perror("open file error");return -1;}//加写锁// if (setlock(fd,F_WRLCK)<0)// {//     perror("set lock error");//     close(fd);//     return -1; b // }while (setlock(fd,F_WRLCK)<0){perror("set lock error");sleep(1);}//写char buf[128] = "set write lock";write(fd,buf,strlen(buf));printf("write success\n");getchar();//解锁if(setlock(fd,F_UNLCK) < 0){perror("unlock error");close(fd);return -1;}close(fd);}

读锁共享锁示例

加锁后还能读,另一个进程也可以(新开终端模拟)

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>// 设置文件锁
int setlock(int fd, short locktype) {struct flock lock = {0};lock.l_type = locktype;      // 锁类型(读锁、写锁、解锁)lock.l_whence = SEEK_SET;    // 从文件开头开始lock.l_start = 0;           // 起始偏移量lock.l_len = 0;             // 0 表示锁整个文件lock.l_pid = getpid();      // 当前进程的进程号// 设置锁(非阻塞模式)int res = fcntl(fd, F_SETLK, &lock);if (res < 0) {return -1; // 加锁失败}return 0; // 加锁成功
}int main() {const char *path = "testfile.txt";int fd = open(path, O_RDWR); // 打开文件if (fd < 0) {perror("open file error");return -1;}// 加读锁(共享锁)printf("Trying to set read lock...\n");if (setlock(fd, F_RDLCK) < 0) {perror("set read lock error");close(fd);return -1;}printf("Read lock set successfully!\n");// 读取文件内容char buf[128] = {0};lseek(fd, 0, SEEK_SET); // 将文件指针移动到开头read(fd, buf, sizeof(buf) - 1);printf("File content: %s\n", buf);// 模拟读操作printf("Reading file... Press Enter to unlock.\n");getchar();// 解锁printf("Unlocking file...\n");if (setlock(fd, F_UNLCK) < 0) {perror("unlock error");close(fd);return -1;}printf("File unlocked.\n");close(fd); // 关闭文件return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Rancher证书到期致使平台无法浏览故障解决

1、修改系统时间&#xff0c;停止时间滚动更新。 # 关闭ntp同步&#xff0c;防止时间自动更新回来 timedatectl set-ntp false # 修改节点时间 timedatectl set-time 2020-07-01 00:00:00 2、重启容器。 #获取容器ID rancher_server_iddocker ps -a|grep -v CONTAINER|awk {…

tcc编译器教程6 进一步学习编译gmake源代码

本文以编译gmake为例讲解如何使用tcc进行复杂一点的c代码的编译 1 简介 前面主要讲解了如何编译lua解释器,lua解释器的编译很简单也很容易理解.当然大部分c语言程序编译没那么简单,下面对前面的gmake程序进行编译. 2 gmake源码结构 首先打开之前tcc-busybox-for-win32\gmak…

数据库基本建表操作

1.登录数据库并创建数据库db_ck 创建完成后使用到我们创建的数据库。 2.创建表t_hero 根据hero属性包括&#xff08;id&#xff0c;name&#xff0c;nickname&#xff0c;age&#xff0c;gender&#xff0c;address&#xff0c;weapon&#xff0c;types&#xff09; 创建完…

标准卷积(Standard Convolution)

标准卷积的基础操作图解&#xff1a; 卷积之后尺寸公式&#xff1a; 输入尺寸&#xff1a;WH卷积核尺寸&#xff1a;Fw​Fh​填充大小&#xff1a;P步长&#xff1a;S 输出尺寸 WoutHout可以通过以下公式计算&#xff1a; 其中[x]表示向下取整。 实例&#xff1a; 输入图像…

初阶数据结构习题【14】(4栈和队列)——225. 用队列实现栈

1. 题目描述 力扣在线OJ——225. 用队列实现栈 请你仅使用两个队列实现一个后入先出&#xff08;LIFO&#xff09;的栈&#xff0c;并支持普通栈的全部四种操作&#xff08;push、top、pop 和 empty&#xff09;。 实现 MyStack 类&#xff1a; void push(int x) 将元素 x …

使用NVM工具管理Node版本

Date: 2025.03.10 14:53:55 author: lijianzhan NVM&#xff08;Node Version Manager&#xff09;用于在同一个系统上管理多个 Node.js 版本,NVM 允许你安装、使用和切换不同的 Node.js 版本。这对于前端工作人员来说可以更方便的管理和维护不同nodejs版本的项目。 &#xff0…

vue使用slot时子组件的onUpdated执行问题

vue使用slot时子组件的onUpdated执行问题 在使用 Vue 的插槽 (slot) 功能时&#xff0c;可能会遇到一个问题&#xff1a;当父组件的任何状态更新时&#xff0c;子组件的 onUpdated 事件会被触发。这个问题在使用默认插槽时尤为明显。 为了避免这种情况&#xff0c;可以使用作用…

淘立方电商前端网站(HTML开发)源代码

一、页面展示 &#xff08;一&#xff09;欢迎界面 &#xff08;二&#xff09;首页 &#xff08;三&#xff09;登录界面 &#xff08;四&#xff09;女装界面 &#xff08;五&#xff09;女鞋界面 &#xff08;六&#xff09;商品详情页 &#xff08;七&#xff09;注册界面…

Flutter:StatelessWidget vs StatefulWidget 深度解析

目录 1. 引言 2. StatelessWidget&#xff08;无状态组件&#xff09; 2.1 定义与特点 2.2 代码示例 3. StatefulWidget&#xff08;有状态组件&#xff09; 3.1 定义与特点 3.2 代码示例 4. StatelessWidget vs StatefulWidget 对比 5. StatefulWidget 生命周期 5.1…

大模型是如何工作的

近几十年来&#xff0c;人工智能经历了从基础算法到生成式AI的深刻演变。生成式AI通过学习大量数据可以创造出全新的内容&#xff0c;如文本、图像、音频和视频&#xff0c;这极大地推动了AI技术的广泛应用。常见的应用场景包括智能问答&#xff08;如通义千问、GPT&#xff09…

SSL VXN

SSL VPN是采用SSL&#xff08;Security Socket Layer&#xff09;/TLS&#xff08;Transport Layer Security&#xff09;协议来实现远程接入的一种轻量级VPN技术,其基于B/S架构&#xff0c;免于安装客户端&#xff0c;相较与IPSEC有更高的灵活度和管理性&#xff0c;当隧道建立…

【C】链式二叉树算法题2

目录 1 另一棵树的子树 1&#xff09; 题目描述 示例1&#xff1a; 示例2&#xff1a; 2&#xff09; 算法解析 3&#xff09; 代码 2 二叉树的遍历 1&#xff09; 问题描述 2&#xff09; 算法解析 3&#xff09; 代码 3 总结 1 另一棵树的子树 leetcode链接…

【Java并发】【synchronized】适合初学者体质入门的synchronized

&#x1f44b;hi&#xff0c;我不是一名外包公司的员工&#xff0c;也不会偷吃茶水间的零食&#xff0c;我的梦想是能写高端CRUD &#x1f525; 2025本人正在沉淀中… 博客更新速度 &#x1f44d; 欢迎点赞、收藏、关注&#xff0c;跟上我的更新节奏 &#x1f4da;欢迎订阅专栏…

STM32---FreeRTOS消息队列

一、简介 1、队列简介&#xff1a; 队列&#xff1a;是任务到任务&#xff0c;任务到中断、中断到任务数据交流的一种机制&#xff08;消息传递&#xff09;。 FreeRTOS基于队列&#xff0c;实现了多种功能&#xff0c;其中包括队列集、互斥信号量、计数型信号量、二值信号量…

目标检测Anchor-based 与 Anchor-free

一.二者对比 anchor-free和anchor-based是两种不同的目标检测方法&#xff0c;区别在于是否使用预定义的anchor框来匹配真实的目标框。 anchor-based方法使用不同大小和形状的anchor框来回归和分类目标&#xff0c;例如faster rcnn、retinanet和yolo等。anchor-free&#xff0…

Node.js与VUE安装

目录 Win下载安装 Mac下载安装 Win与Mac配置检查是否安装成功切换淘宝NPM库检查镜像配置是否生效设置 npm 全局环境目录&#xff08;避免权限问题&#xff09;WinMac VUE安装安装 Vue CLI验证 Vue CLI打开vue面板 Win 下载 直接从官网下载官网地址&#xff1a;https://nodejs…

LabVIEW基于双通道FFT共轭相乘的噪声抑制

对于双通道采集的含噪信号&#xff0c;通过FFT获取复数频谱后&#xff0c;对第二通道频谱取共轭并与第一通道频谱相乘&#xff0c;理论上可增强相关信号成分并抑制非相关噪声。此方法适用于通道间信号高度相关、噪声独立的场景&#xff08;如共模干扰抑制&#xff09;。以下为L…

c语言笔记 静态数据与ELF程序格式

数据段&#xff1a; 1.全局变量 2.常量.rodata段 3.已初始化的静态数据(全局变量).data段 4.未初始化的静态数据(static修饰的局部变量).bss段 为什么需要静态数据? 全局变量 可以在任何文件&#xff0c;函数中使用&#xff0c;数据操作上更加方便。static修饰的局部变量&a…

算法 之 树形dp 树的中心、重心

文章目录 重心实践题目小红的陡峭值 在树的算法中&#xff0c;求解树的中心和重心是一类十分重要的算法 求解树的重心 树的重心的定义&#xff1a;重心是树中的一个节点&#xff0c;如果将这个点删除后&#xff0c;剩余各个连通块中点数的最大值最小&#xff0c;那么这个节点…

Ubuntu切换lowlatency内核

文章目录 一. 前言二. 开发环境三. 具体操作 一. 前言 低延迟内核&#xff08;Lowlatency Kernel&#xff09; 旨在为需要低延迟响应的应用程序设计的内核版本。Linux-lowlatency特别适合音频处理、实时计算、游戏和其他需要及时响应的实时任务。其主要特点是优化了中断处理、调…