[基础IO]文件描述符{C库函数\系统接口\初识fd}

news2024/7/6 18:06:15

文章目录

  • 1.基础知识
    • 1.1对文件的认识
    • 1.2对系统调用接口的认识
    • 1.3如何理解LInux下一切皆文件?
  • 2.C语言的库函数
    • 2.1FILE *fopen(const char *path, const char *mode);
    • 2.2对fopen()的mode的w/a的深层认识
    • 2.3fclose()
    • 2.4size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
    • 2.5put()系列 -- fputs()
    • 2.6get()系列 -- fgets()
    • 2.7C语言文件库函数
      • 1.用C语言将字符串写到文件里 计算字符串长度时strlen()函数用+1吗?
      • 2.代码理解
  • 3.系统调用接口
    • 3.1如何用函数传递标志位 -- 数据结构之位图
    • 3.2FILE 是什么?
    • 3.3fd是什么?
    • 3.4内核中如何看待被打开的文件?
    • 3.5ssize_t read(int fd, void *buf, size_t count);
    • 3.6int fprintf(FILE * stream, const char* format, ...);
    • 3.7ssize_t write(int fd, const void *buf, size_t count);`
    • 3.8int open(const char *pathname, int flags, mode_t mode);`
    • 3.9代码理解

1.基础知识

1.1对文件的认识

  1. 文件 = 内容 + 属性(也是数据)
  2. 文件的所有操作: a. 对内容 b. 对属性 对内容操作可能引起属性操作 如: 增加内容 文件变大 标识文件大小的属性变化
  3. 文件在磁盘上存放 磁盘是硬件 用户访问文件: 代码–编译—可执行程序—运行—进程通过OS提供的系统调用接口访问文件
  4. 向磁盘(硬件)写入内容 只有OS有权利 普通用户要想写入 只能使用OS提供的文件类系统调用接口
    在这里插入图片描述

1.2对系统调用接口的认识

  1. 要想用系统调用接口 首先得了解怎么用 及使用者需要对系统有一定的认识与了解 而系统调用接口使用较难或者说系统太难理解 学习计算机的同学都是从易到难学习的 C/C++/java等等 或者说先是学习较简单的语言 然后再学例如计算机组成原理/编译原理/操作系统等较难课程 而从计算机发展历史看 实际上是先有的计算机组成/OS 而后才有的语言 但是我们不得不从语言开始学 因为一开始就学OS根本就学不懂 这就好比我们先学语言 再学数据结构一样 我们首先需要具备一定的语言知识 才能更好的学习底层 其次 底层配合语言让我们对计算机的理解更加深刻
  2. 为了让初学者去使用接口 或者说让这些系统调用接口能够被更好的使用 在接口上做了封装 形成各类语言的库函数 学习这些语言的人就能调用库函数来间接实现对接口的调用
  3. 不同的语言有不同的风格和体系 这也造成了不同语言的文件函数使用上具有很大差异 但是底层都是封装的系统接口
  4. 而你使用的OS基本上只有一个 基于此OS的系统调用接口 只有一套 如果我们学习了本质即底层 那么学习其他语言的接口将会是如鱼得水
  5. 上面为我们讲到 语言对系统调用接口封装形成库函数一大目的是更好更方便更简单的使用系统调用接口 那么还有第二大目的就是实现语言的跨平台性 如果语言不提供对文件的系统调用接口的封装 那么用该语言写出的代码一旦涉及到访问文件的操作都必须/只能调用系统调用接口 而在linux下写的语言就必须调用Linux的接口 这份语言 到windows下 由于Windows没有linux的接口或者说二者根本就无法用统一接口调用对应操作 使得这份语言不具备跨平台性

语言是如何实现跨平台的?

把基于所有平台(windows/Linux/MacOS)的代码都实现一遍条件编译 动态裁剪 在什么机器上跑 就用对应的封装

对显示器的认识

  1. 显示器是硬件 pintf/cout向显示器打印 本质上也是向硬件写入
  2. 磁盘我们无法向显示器一样直观看到 所以向显示器打印内容时 我们不觉得奇怪 因为一眼就能看到
  3. 向显示器打印和磁盘上文件的写入本质没有区别

1.3如何理解LInux下一切皆文件?

在Linux中,一切皆文件的原则是指Linux将所有的资源都视为文件或文件类型的一种。这包括硬件设备、目录、文件、进程、套接字等等。在Linux中,每个文件都有一个唯一的文件描述符,它是一个非负整数,用于标识打开的文件。通过文件描述符,我们可以对文件进行读写等操作。这种一切皆文件的设计理念使得Linux系统的操作变得非常简单和统一,因为所有的资源都可以通过相同的方式进行访问和操作。同时,这种设计理念也为Linux系统提供了很好的可扩展性和灵活性,因为新的设备和资源可以很容易地被添加到系统中,并且可以通过相同的方式进行管理和访问。

举个例子,如果你想要查看CPU的温度,你可以在Linux中打开一个文件,该文件位于/sys/class/thermal/thermal_zone0/temp,然后读取该文件的内容,就可以得到CPU的温度信息。这个文件就是一个虚拟文件,它代表了CPU的温度传感器,通过读取该文件的内容,我们就可以获取到CPU的温度信息。

另外,Linux中的文件类型也非常丰富,包括普通文件、目录文件、字符设备文件、块设备文件、套接字文件等等。每种文件类型都有自己的特点和用途,例如普通文件用于存储文本、二进制数据等,目录文件用于存储其他文件和目录等。理解Linux中的文件类型对于正确地使用和管理Linux系统非常重要。

如何理解文件?

  1. 最初我们认识到的文件是从语言级别认识的 例如C语言调用fopen/fread/fwrite等函数可以对文件进行打开关闭读写操作
  2. 后来我么认识并了解到 显示器和键盘也具有文件的一些属性如 读和写 printf/cout向显示器打印内容 实际上就是一种write scanf/cin从键盘获取数据 实际上就是一种read 至于为什么从键盘输入的内容能显示到显示器上 这实际上是一种回显 这些调用库函数实现对文件的读写操作 是站在程序的角度 而程序要想能够执行这些操作 首先他得运行成为进程 即代码和数据加载到内存 即以上这些过程 是站在内存的角度 通过进程来完成的
  3. 从文件中读数据到文件中的流程: 进程调用fopen/fread(Input)函数从A文件中读入数据到进程的内部(内存) 然后调用fwrite(Outpute)函数写到B文件中
  4. 由此我们得出文件的概念: 站在系统的角度 能够被input读取或者能够被output写出的设备 就叫做文件
  5. 之前认识的文件是文件的子集,是狭义上的文件即磁盘上的文件
  6. 广义上的文件如显示器,键盘,网卡,声卡,显卡,磁盘,几乎所有的外设,都可以称之为文件

2.C语言的库函数

2.1FILE *fopen(const char *path, const char *mode);

在这里插入图片描述

mode的不同作用和目的

在这里插入图片描述
r: 为了读打开一个文件 文件流定位在文件首 原文件不存在则报错
w: 为了写打开一个文件 清空文件原有内容 文件不存在创建一个新文件 文件流定位在文件首
a: 为了追加打开一个文件 文件不存在创建一个新文件 文件流定位在文件尾
(r+ w+ a+ : 为了读和写打开文件 其他对应一致)

2.2对fopen()的mode的w/a的深层认识

w/a 打开不存在的文件时 会创建一个新文件 这个文件创建在哪里?

  1. 当前路径
  2. 准确一点是源代码对应的可执行程序所在的路径
  3. 精确一点是Linux下源代码对应的可执行程序运行变为进程所处的工作路径 (Windows-VS下的源代码和可执行程序不在同一路径 有所区别)
  4. fopen()会将不存在文件名建立在 “当前路径” 下 以此作为新文件的路径

谁创建的?

源代码对应的可执行程序运行起来成为进程后进程调用系统接口创建的 ==> OS创建的!

ls /proc/pid -l.会显示什么?

  1. cwd: current work directory 当前进程所执行的程序的所在目录
  2. exe: 当前进程所执行的可执行程序路径+文件名
    即 当一个进程运行时 会记录自己当前所处的工作路径 可执行程序的路径变化 对应的进程的工作路径也会变化
    继续回答上面的问题 当前路径指的是什么?. 一个进程运行时 当前所处的工作路径

2.3fclose()

在这里插入图片描述

2.4size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

在这里插入图片描述

回顾之前的字符串函数

在这里插入图片描述

2.5put()系列 – fputs()

在这里插入图片描述
#include <stdio.h>
int fputc(int c, FILE *stream);
int fputs(const char *s, FILE *stream);
int putc(int c, FILE *stream);
int putchar(int c);
int puts(const char *s);

2.6get()系列 – fgets()

在这里插入图片描述 #include <stdio.h>
int fgetc(FILE *stream);
char *fgets(char *s, int size, FILE *stream);
int getc(FILE *stream);
int getchar(void);
char *gets(char *s);
int ungetc(int c, FILE *stream);

2.7C语言文件库函数

1.用C语言将字符串写到文件里 计算字符串长度时strlen()函数用+1吗?

  1. 在C语言里字符串末尾有一个标识字符串结尾的标识符叫\0 它不属于字符串的内容 \0是C语言自己的规定
  2. 用C语言将字符串写到文件后 文件上的字符串与C语言再无瓜葛 文件要保存的是数据 不用也压根没必要遵守某种语言的规定 所以答案是不用+1
  3. 如果+1 文件内容会出现某一处乱码 因为文件无法对\0做有效解读

那文件里的字符串没有\0读的时候怎么分辨?\n怎么分辨?

读是用语言读的 语言级别上读的时候识别到后加上就行了 这就是系统与语言的区别

命令行下模拟w操作

echo hello txt > test.txt//向文件写内容.
> test.txt//输出重定向: 先打开文件 清空内容 又什么都不写 模拟完成.
实际上 echo命令 底层就是C语言调用fopen函数执行w操作完成的

按行读取char *fgets(char *s, int size, FILE *stream);

会自动在读到的字符串尾部+\0

C语言程序执行后三个标准输入输出流

FILE* : 把硬件看成了文件
extern FILE *stdin; --键盘
extern FILE *stdout; --显示器
extern FILE *stderr; --显示器

在这里插入图片描述

2.代码理解

int main(int argc, char *argv[])
{
    if(argc != 2) 
    {
        printf("argv error!\n");
        return 1;
    }

    //FILE* fopen(const char* path, const char* mode);
    FILE* fp = fopen(argv[1], "r"); /* ./myfile test.txt */
    //./mycat log.txt 模拟实现输出文件内容
    if(fp == NULL)
    {
        perror("fopen");
        return 2;
    }

    //按行读取
    char line[64];
    //char* fgets(char* s, int size, FILE * stream);  
    // fgetstring -- fgets 自动在所读取的字符结尾添加\0
    while(fgets(line, sizeof(line), fp) != NULL)
    {
        //printf("%s", line);
        fprintf(stdout, "%s", line);
    }

    //文件操作
    //size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE* stream);
    //const char *s1 = "hello file\n"; 
    //fwrite(s1, strlen(s1), 1, fp);

    //const char *s2 = "hello fprintf\n";
    //fprintf(fp, "%s", s2);

    //const char *s3 = "hello fputs\n";
    //fputs(s3, fp); int fputs(const char *s, FILE *stream);

    fclose(fp);

    return 0;
}

3.系统调用接口

C库函数: fopen fclose fread fwrite
系统接口: open close read write

3.1如何用函数传递标志位 – 数据结构之位图

应用层上一个简单的动作,在系统接口层面/OS层面,要做非常多的操作

//用比特位 标识状态
#define ONE 0x1   //0000 0001
#define TWO 0x2   //0000 0010
#define THREE 0x4 //0000 0100

void show(int flags) 
{
    if(flags & ONE)    //0000 0001
        printf("hello one\n");
    if(flags & TWO)    //0000 0010
        printf("hello two\n");
    if(flags & THREE)  //0000 0100
        printf("hello three\n");
}

int main()
{
    show(ONE); //000 0001
    printf("-----------------------------------------\n");

    show(TWO); //0000 0010
    printf("-----------------------------------------\n");

    show(ONE | TWO);  //000 0001 | 0000 0010 == 0000 0011
    printf("-----------------------------------------\n");
   
    show(ONE | THREE);
    printf("-----------------------------------------\n");

    show(ONE | TWO | THREE); //000 0001 | 0000 0010 | 0000 0100 == 0000 0111
    printf("-----------------------------------------\n");

    return 0;
}

fd: file descriptor 文件描述符 为什么创建一个文件从3开始? 0 1 2 呢?

在这里插入图片描述

3.2FILE 是什么?

  1. FILE是个C标准库提供的结构体 内部有很多成员 其中就封装了fd
  2. C库函数底层不一定都封装了系统接口 C关于文件的库函数底层都调用了系统接口 系统角度认识fd 但不认识C的FILE

3.3fd是什么?

  1. 进程要访问文件 必须先打开文件
  2. 一个进程可以打开多个文件 进程 : 文件 == 1 : n
  3. 文件被进程直接访问的前提是加载到内存中
  4. 一个进程有可以打开多个文件 多个进程会打开超多文件 此时系统中会存在大量的被打开的文件 OS要把如此多的文件管理起来 ==> 先描述再组织
  5. 在内核中 fd本质是一个数组下标

3.4内核中如何看待被打开的文件?

OS内部为管理每一个被打开的文件 为每一个被打开的文件构建一个file结构体对象 充当被打开的文件 然后把这些文件对象用双链表组织起来

struct FILE
{
	struct file* prev;
	struct file* next;
	//包含一个被打开的文件的几乎所有内容(权限,缓冲区,链接信息,属性等)
}

在这里插入图片描述

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

在这里插入图片描述

  1. 从文件描述符fd向buf缓冲区读取最多count个字节
  2. 读取成功返回所读的字节数
  3. 读取错误返回-1

3.6int fprintf(FILE * stream, const char* format, …);

在这里插入图片描述

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

在这里插入图片描述

3.8int open(const char *pathname, int flags, mode_t mode);`

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.9代码理解

int main()
{
    //int open(const char* pathname, int flags, mode_t mode);
    
    //不被系统的umask掩码影响 设置umask掩码为0 (就近)
    //目的是调用open()接口时 传的mode直接作为文件的权限
    umask(0);

    //只读
    // int fd = open("log.txt", O_RDONLY);
  
    //只写 目标文件不存在需创建新文件 每次打开清空原有内容  fopen("log.txt", "w");
    //int fd = open("log.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666); //rw-rw-rw-
    //if(fd < 0)
    //{
    //    perror("open");
    //    return 1;
    //}
    //char buffer[64];
    //memset(buffer, '\0', sizeof(buffer));
    // 
    //  fread()调用read时会执行一个操作: 
    // 在所读到的字符串结尾 + \0 
    // 而系统接口read()不会 read是按字节数读的 
    // 所以将buf数组全部置成\0 可以使得读完后最后有一个\0
    // 
    //read(fd, buffer, sizeof(buffer));  //ssize_t read(int fd, void *buf, size_t count);
    //printf("%s", buffer);
   
    //const char *s = "hello write\n";
    //const char *s = "hi\n";
    //write(fd, s, strlen(s)); //ssize_t write(int fd, const void *buf, size_t count);
    
    //只写 目标文件不存在需创建新文件 追加写入  fopen("log.txt", "a");
    int fd1 = open("log1.txt", O_WRONLY | O_CREAT | O_APPEND, 0666); 
    printf("open success, fd: %d\n", fd1);
    int fd2 = open("log2.txt", O_WRONLY | O_CREAT | O_APPEND, 0666);
    printf("open success, fd: %d\n", fd2);
    int fd3 = open("log3.txt", O_WRONLY | O_CREAT | O_APPEND, 0666);
    printf("open success, fd: %d\n", fd3);
    int fd4 = open("log4.txt", O_WRONLY | O_CREAT | O_APPEND, 0666);
    printf("open success, fd: %d\n", fd4);
    close(fd1);
    close(fd2);
    close(fd3);
    close(fd4);

    return 0;
}

int main()
{
    char input[16] = { 0 };
    ssize_t s = read(0, input, sizeof(input));
    if (s > 0)
    {
        input[s] = '\0';
        printf("%s\n", input);
    }

    int a = 0;
    fscanf(stdin, "%d", &a);  //scanf
    fprintf(stdout, "%d\n", a); //printf

    //ssize_t write(int fd, const void *buf, size_t count);
    const char* s = "hello stdout(1)\n";
    write(1, s, strlen(s));
    return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

固态硬盘无法识别?三大方法帮你搞定

随着科技的迅猛发展&#xff0c;固态硬盘&#xff08;SSD&#xff09;已成为许多计算机用户首选的存储设备。然而&#xff0c;有时我们可能会遭遇固态硬盘无法识别的问题&#xff0c;这给用户带来了不便与困扰。本文将深入研究固态硬盘无法识别的原因&#xff0c;并为您提供三种…

STM32 寄存器配置笔记——USART DMA接收

一、简介 本文主要介绍STM32如何配合USART的IDLE中断实现USART DMA接收不定长的数据。其中使用的接收缓存还是延用前面博客写的乒乓缓存。使用DMA USART接收来替代中断方式或轮询方式的接收主要是为了提高代码的运行效率&#xff0c;中断方式的接收&#xff0c;每接收一个字节便…

RZ、NRZ、NRZI、曼彻斯特编码

1、RZ编码 RZ编码也成为归零码&#xff0c;归零码的特性就是在一个周期内&#xff0c;用二进制传输数据位&#xff0c;在数据位脉冲结束后&#xff0c;需要维持一段时间的低电平 2、NRZ编码 NRZ编码也成为不归零编码&#xff0c;即高电平表示1&#xff0c;低电平表示0。它与RZ码…

swing快速入门(六)

注释很详细&#xff0c;直接上代码 上一篇 本篇新增内容 Gridlayout&#xff08;网格布局&#xff09; Textfield组件的最大限定长度 Panel()的默认布局方式 Gridlayout的默认布局位置 import java.awt.*;public class swing_test_4 {public static void main(String[]ar…

Android 11.0 systemui锁屏页面时钟显示样式的定制功能实现

1.前言 在11.0的系统ROM定制化开发中,在进行systemui的相关开发中,当开机完成后在锁屏页面就会显示时间日期的功能,由于 开发产品的需求要求时间显示周几上午下午接下来就需要对锁屏显示时间日期的相关布局进行分析,然后实现相关功能 效果图如图: 2.systemui锁屏页面时钟显…

c语言->自定义类型联合体和枚举类型

系列文章目录 文章目录 前言 ✅作者简介&#xff1a;大家好&#xff0c;我是橘橙黄又青&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;橘橙黄又青_C语言,函数,指针-CSDN博客 目的&#xff1a;学习联合体和枚举类型的…

Web安全之XXE漏洞原理及实践学习

一、原理&#xff1a; XXE漏洞全称即XML外部实体注入漏洞。 攻击者强制XML解析器去访问攻击者指定的资源内容(可能是系统上本地文件亦或是远程系统上的文件)&#xff0c;导致可加载恶意外部文件&#xff0c;利用file协议造成文件读取、命令执行、内网端口扫描、攻击内网网站等…

网络基础(五):网络层协议介绍

目录 一、网络层 1、网络层的概念 2、网络层功能 3、IP数据包格式 二、ICMP协议 1、ICMP的作用和功能 2、ping命令的使用 2.1ping命令的通用格式 2.2ping命令的常用参数 2.3TypeCode&#xff1a;查看不同功能的ICMP报文 2.4ping出现问题 3、Tracert 4、冲突域 5、…

农副产品行业ERP有哪些?农副产品行业ERP是做什么的

现实生活当中有很多种类的农副产品&#xff0c;这些琳琅满目的商品有多元化的营销渠道和策略&#xff0c;同时在保质期、包装、价格策略、配料、生产工艺等诸多方面存在明显的差异。 由于行业的特殊性&#xff0c;传统的人工统计分析工作量较大&#xff0c;同时也难以确保业务…

酷开系统丨非比寻常,酷开科技带你感受智能电视的妙处

智能电视的出现不仅改变了人们的观影方式&#xff0c;也在一定程度上改变了人们的生活方式。有人说&#xff0c;选择电视机其实就是在选择智能电视系统。在纷乱繁杂的电视市场里&#xff0c;想必大家在挑选的时候也是费尽了心力。 众所周知&#xff0c;内容已经成为衡量智能电…

各个数据库存二进制大文件性能测试

1前言 ​ 有个项目软件前端将二进制大文件存在了indexDB,每次给后端传文件&#xff08;需要传到底层C进行调用&#xff09;都会导致内存占用飙升&#xff0c;想着使用前后端都能共同操作的数据库来解决这个内存占用的问题&#xff0c;并且希望这个更具尽可能的轻量&#xff0c…

案例044:基于微信小程序的消防隐患在线举报系统

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…

项目实战二——性能测试方案

这里写目录标题 一、性能测试整体流程介绍二、性能测试时机&#xff08;什么时候去做&#xff1f;&#xff09;三、测试背景(务虚&#xff1a;让不懂的人尽可能看懂)四、术语约定五、测试范围1、调研分析&#xff1a;2、测试范围&#xff1a; 六、性能需求分析1、业务模型预估&…

低多边形植物模型法线贴图

在线工具推荐&#xff1a; 3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器 - 3D模型语义搜索引擎 当谈到游戏角色的3D模型风格时&#xff0c;有几种不同的风格&#xf…

学习-面试java基础-(集合)

String 为什么不可变&#xff1f; 1线程安全 2支持hash映射和缓存。因为String的hash值经常会使用到&#xff0c;比如作为 Map 的键&#xff0c;不可变的特性使得 hash 值也不会变&#xff0c;不需要重新计算。 3出于安全考虑。网络地址URL、文件路径path、密码通常情况下都是以…

使用JLink仿真器实现调试打印的N种方法

方法一&#xff1a;使用MCU的串口 这是最古老也是最简单的方法。 电脑上面插一个USB转TTL&#xff0c;然后与MCU的UART_RX/UART_TX/GND连接起来。PC端再打开一个串口调试助手。两边的波特率一致&#xff0c;就可以收到MCU发过来的打印信息了。 方法二&#xff1a;使用JLink仿…

低功耗模式的通用 MCU ACM32F0X0 系列,具有高整合度、高抗干扰、 高可靠性的特点

ACM32F0X0 系列是一款支持多种低功耗模式的通用 MCU。集成 12 位 1.6 Msps 高精度 ADC 以及比 较器、运放、触控按键控制器、段式 LCD 控制器&#xff0c;内置高性能定时器、多路 UART、LPUART、SPI、I2C 等丰富的通讯外设&#xff0c;内建 AES、TRNG 等信息安全模块&#xff0…

初识文件系统

文章目录 1、概述2、inode结构3、block BitMap 和 inode BitMap4、软链接和硬链接4.1 硬链接4.2 软链接 5、Linux下的文件类型的 1、概述 文件存储在硬盘上&#xff0c;硬盘的最小存储单位叫做“扇区”&#xff08;Sector&#xff09;。每个扇区储存512字节 操作系统读取硬盘…

vue3 添加编辑页使用 cron 表达式生成

示例效果图 1、添加组件 <template><div class"v3c"><ul class"v3c-tab"><li class"v3c-tab-item" :class"{ v3c-active: tabActive 1 }" click"onHandleTab(1)">秒</li><li class&qu…

智能优化算法应用:基于蝙蝠算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于蝙蝠算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于蝙蝠算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.蝙蝠算法4.实验参数设定5.算法结果6.参考文献7.MA…