Linux标准库API

目录

1.字符串函数

2.数据转换函数

3.格式化输入输出函数

4.权限控制函数

5.IO函数

6.进程控制函数

7.文件和目录函数


1.字符串函数

2.数据转换函数

 

 

 

 

 

3.格式化输入输出函数

 

#include<stdarg.h>


void test(const char * format , ...){
    
        va_list ap;
        va_start(ap,format);
        vprintf(format,ap);
        char buffer[5000] = "";
        va_start(ap,format);
        vsnprintf(buffer,sizeof (buffer) , format , ap ); 
        va_start(ap,format);
        vsprintf(buffer , format,ap);

}

int main(){

    test("%s %d %f " , "bug" , 20 , 20.145);

}

 

4.权限控制函数

 补充知识:

#chmod
# 语法格式: chmod who [+|-|=] mod 文件名
	- who:
		- u: user  -> 文件所有者
		- g: group -> 文件所属组用户
		- o: other -> 其他
		- a: all, 以上是三类人 u+g+o
	- 对权限的操作:
		+: 添加权限
		-: 去除权限
		=: 权限的覆盖
	- mod: 权限
		r: read, 读
		w: write, 写
		x: execute, 执行
		-: 没有权限
		
# 将文件所有者权限设置为读和执行, 也就是权限覆盖
robin@OS:~/Linux$ chmod u=rx b.txt 
robin@OS:~/Linux$ ll b.txt         
-r-xrw-r-- 2 robin robin 2929 Apr 14 18:53 b.txt*

# 给其他人添加写和执行权限
robin@OS:~/Linux$ chmod o+wx b.txt 
robin@OS:~/Linux$ ll b.txt         
-r-xrw-rwx 2 robin robin 2929 Apr 14 18:53 b.txt*

# 给文件所属组用户去掉读和执行权限
robin@OS:~/Linux$ chmod g-rx b.txt 
robin@OS:~/Linux$ ll b.txt         
-r-x-w-rwx 2 robin robin 2929 Apr 14 18:53 b.txt*

# 将文件所有者,文件所属组用户,其他人权限设置为读+写+执行
robin@OS:~/Linux$ chmod a=rwx b.txt
robin@OS:~/Linux$ ll b.txt 
-rwxrwxrwx 2 robin robin 2929 Apr 14 18:53 b.txt*

# 语法格式: chmod [+|-|=] mod 文件名
	- 对权限的操作:
		+: 添加权限
		-: 去除权限
		=: 权限的覆盖, 等号可以不写
	- mod: 权限描述, 所有权限都放开是 7
		- 4: read, r
		- 2: write, w
		- 1: execute , x
		- 0: 没有权限
		
# 分解: chmod 0567 a.txt

    0           5           6             7
  八进制     文件所有者  文件所属组用户    其他人
              r + x       r + w         r+w+x

######################### 举例 #########################
# 查看文件 c.txt 的权限			   
robin@OS:~/Linux$ ll c.txt 
-rwxrwxrwx 2 robin robin 2929 Apr 14 18:53 c.txt*

# 文件所有者去掉执行权限, 所属组用户去掉写权限, 其他人去掉读+写权限
robin@OS:~/Linux$ chmod -123 c.txt
robin@OS:~/Linux$ ll c.txt 
-rw-r-xr-- 2 robin robin 2929 Apr 14 18:53 c.txt*

# 文件所有者添加执行权限, 所属组用户和其他人权限不变
robin@OS:~/Linux$ chmod +100 c.txt
robin@OS:~/Linux$ ll c.txt 
-rwxr-xr-- 2 robin robin 2929 Apr 14 18:53 c.txt*

# 将文件所有者,文件所属组用户,其他人权限设置为读+写, 没有执行权限
robin@OS:~/Linux$ chmod 666 c.txt
robin@OS:~/Linux$ ll c.txt 
-rw-rw-rw- 2 robin robin 2929 Apr 14 18:53 c.txt


# 语法1-只修改所有者: 
$ sudo chown 新的所有者 文件名

# 语法2-同时修改所有者和所属组: 
$ sudo chown 新的所有者:新的组名 文件名

# 查看文件所有者:b.txt 属于 robin 用户
robin@OS:~/Linux$ ll b.txt 
-rw-rw-rw- 2 robin robin 2929 Apr 14 18:53 b.txt

# 将 b.txt 的所有者修改为 luffy
robin@OS:~/Linux$ sudo chown luffy b.txt
[sudo] password for robin: 
robin@OS:~/Linux$ ll b.txt 
-rw-rw-rw- 2 luffy robin 2929 Apr 14 18:53 b.txt

# 修改文件所有者和文件所属组
# 查看文件所有者和所属组
robin@OS:~/Linux$ ll b.txt 
-rw-rw-rw- 2 luffy robin 2929 Apr 14 18:53 b.txt

# 同时修改文件所有者和文件所属组
robin@OS:~/Linux$ sudo chown robin:luffy b.txt 
robin@OS:~/Linux$ ll b.txt 
-rw-rw-rw- 2 robin luffy 2929 Apr 14 18:53 b.txt

 

# 只修改文件所属的组, 普通用户没有这个权限, 借助管理员的权限
# 语法: sudo chgrp 新的组 文件名

# 查看文件所属组信息
robin@OS:~/Linux$ ll b.txt 
-rw-rw-rw- 2 robin luffy 2929 Apr 14 18:53 b.txt

# 修改文件所属的组
robin@OS:~/Linux$ sudo chgrp robin b.txt 
robin@OS:~/Linux$ ll b.txt 
-rw-rw-rw- 2 robin robin 2929 Apr 14 18:53 b.txt


 

 

下面说一下文件设置用户ID位,这个ID仅仅是一个二进制的bit位,在文件stat结构的st_mode成员中,对于一般的文件,该位是置为无效的,只有可执行文件的该位是置为有效的。

 改变三个用户ID的方法

 

 

 2. 什么时候用到设置用户id和设置组id?

 小实验

 此时给上文件用户设置ID和文件设置组ID的权限s,此时执行时

 特权用户使用这几个函数的时候,都是直接用参数的值来设置实际用户ID或者有效用户ID,这些值都可以是任意的。
例如:setreuid(ruid, euid), 如果是特权用户,则直接设置实际用户ID为ruid,有效用户ID为euid。

但非特权用户就不行了,非特权用户用setuid(),seteuid()则只能将有效有户ID设置为实际用户ID或保存的设置用户ID,如果不是这两个数,设置失败!

此时我们改变一下文件的用户和用户组为zhz

 

 

创建会话ID:

pid_t setsid(void)                    守护进程的关键调用函数

1.用户和组要有足够的权限2.当前进程只能是子进程才能调用成功


5.IO函数

头文件

<sys/types.h>

<sys/stat.h>

<fcntl.h>

打开文件

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

 

 

 

 <fcntl.h>

测试代码:

#include <cstdio>
#include<iostream>
#include<unistd.h>  //头文件


#include<fcntl.h>
#include<sys/file.h>
#include<error.h>  //errno
#include<string.h> //strerror

void f() {

    //int fd = open("/home/zhz/text.txt", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
    int fd = open("/home/zhz/text.txt", O_RDWR | O_CREAT, 0755);

    //文件锁是一个建议性锁,此时是无效上锁
    /*
    if (fd >= 0) { 
        printf("write:%d\n", write(fd, "hello", 5));
        printf("flock:%d\n", flock(fd, LOCK_EX));
        sleep(6);
        flock(fd, LOCK_UN);
        close(fd);
    }
    */
    if (fd >= 0) {
        printf("flock:%d\n", flock(fd, LOCK_EX));  //先上锁在写(你认为这有锁才起效果)
        printf("write:%d\n", write(fd, "hello", 5));
        sleep(6);
        flock(fd, LOCK_UN);
        close(fd);
    }
    else {
        std::cout << strerror(errno) << std::endl;
    }

}
int main()
{
    f();
    return 0;
}

 

6.进程控制函数

exec函数族提供了一个在进程中启动另一个程序执行的方法。它可以根据指定的文件名或目录名找到可执行文件,并用它来取代原调用进程的数据段、代码段和堆栈段,在执行完之后,原调用进程的内容除了进程号外,其他全部被新程序的内容替换了。

在Linux中使用exec函数族主要有以下两种情况

1.当进程认为自己不能再为系统和用户做出任何贡献时,就可以调用任何exec 函数族让自己重生。

2.如果一个进程想执行另一个程序,那么它就可以调用fork函数新建一个进程,然后调用任何一个exec函数使子进程重生。

1参数传递方式:exec函数族的参数传递有两种方式,一种是逐个列举(l)的方式,而另一种则是将所有参数整体构造成指针数组(v)进行传递。

在这里参数传递方式是以函数名的第5位字母来区分的,字母为“l”(list)的表示逐个列举的方式,字母为“v”(vertor)的表示将所有参数整体构造成指针数组传递,然后将该数组的首地址当做参数传给它,数组中的最后一个指针要求是NULL。读者可以观察execl、execle、execlp的语法与execv、execve、execvp的区别。

2.环境变量:exec函数族使用了系统默认的环境变量,也可以传入指定的环境变量。这里以“e”(environment)结尾的两个函数execle、execve就可以在envp[]中指定当前进程所使用的环境变量替换掉该进程继承的环境变量。

3.PATH环境变量说明

        PATH环境变量包含了一张目录表,系统通过PATH环境变量定义的路径搜索执行码,PATH环境变量定义时目录之间需用用“:”分隔,以“.”号表示结束。PATH环境变量定义在用户的.profile或.bash_profile中,下面是PATH环境变量定义的样例,此PATH变量指定在“/bin”、“/usr/bin”和当前目录三个目录进行搜索执行码。

PATH=/bin:/usr/bin:.

export $PATH

4.进程中的环境变量说明

    在Linux中,Shell进程是所有执行码的父进程。当一个执行码执行时,Shell进程会fork子进程然后调用exec函数去执行执行码。Shell进程堆栈中存放着该用户下的所有环境变量,使用execl、execv、execlp、execvp函数使执行码重生时,Shell进程会将所有环境变量复制给生成的新进程;而使用execle、execve时新进程不继承任何Shell进程的环境变量,而由envp[]数组自行设置环境变量。
 

void f() {

    pid_t pid = fork();
    if (pid > 0) {
        //这是父进程
        sleep(5);
        std::cout << "parent!!!!" << std::endl;
    }
    else {
        execl("/bin/ls", "ls", "-l", NULL);
    }
}

 进程的数量是有限的

#include<assert.h>

 C/C++ assert()函数用法总结 - 白菜菜白 - 博客园 (cnblogs.com)

 (9条消息) 多进程之进程退出函数:exit,_exit,atexit详解_c语言 exit() atexit_谢永奇1的博客-CSDN博客

 (9条消息) on_exit()函数使用说明_Ahren.zhao的博客-CSDN博客

#include <cstdio>
#include<iostream>
#include<unistd.h>  //头文件


#include<fcntl.h>
#include<sys/file.h>
#include<error.h>  //errno
#include<string.h> //strerror
#include<assert.h>

void fa() {
    printf("father is over\n");
}

void son(int status , void * str) {


    printf("%d   %s\n", status , (char *)str);

}
void pra() {

    pid_t pid = fork();
    if (pid > 0) {
        atexit(fa);
        std::cout << "parent!!!!" << std::endl;
        exit(0);
    }
    else {
        char s[10] = "i am son";
        char* str = &s[0];
        on_exit(son, str );
        exit(0);
    }
}
int main()
{
    pra();
    return 0;
}

 

#include <cstdio>
#include<iostream>
#include<unistd.h>  //头文件


#include<fcntl.h>
#include<sys/file.h>
#include<error.h>  //errno
#include<string.h> //strerror
#include<assert.h>





#include<setjmp.h>
#include<signal.h>
jmp_buf jmpbuf;   //用来存储寄存器的信息

void test002() {

    //to do somethings

    longjmp(jmpbuf, 1);  //此时程序发生错误1
}



void test001() {

    //to do somethings

    //...

    test002();
}



void signal_deal(int sig) {   //注册信号处理函数
    if (sig == SIGSEGV) {
        longjmp(jmpbuf, SIGSEGV);
    }

}


void pra() {

    signal(SIGSEGV,signal_deal);  //异常捕获


    int ret = setjmp(jmpbuf);  //保存所有寄存器的值

    if (ret == 0) {  //c语言处理异常的一种机制
        test001();
        *(int*)(NULL) = 0;  //段错误
    }
    else if (ret == 1) {
        printf("error 1\n");
    }
    else if (ret == SIGSEGV) {
        printf("error SIGSEGV\n");
    }
}

int main()
{
    pra();
    return 0;
}

 当注释掉test001()时,此时引发段错误信号,进入异常捕获处理函数。

 知识补充:

信号是进程在运行过程中,由自身产生或由进程外部发过来的消息。

信号是硬件中断的软件模拟(软中断)。每个信号用一个整型常量宏表示,以SIG开头,比如SIGCHLD、SIGINT等,它们在系统头文件中<signal.h>定义。

由进程的某个操作产生的信号称为同步信号(synchronous signals),例如除0;由用户击键之类的进程外部事件产生的信号叫做异步信号。(asynchronous signals)。

signal()

C 库函数 void (*signal(int sig, void (*func)(int)))(int) 设置一个函数来处理信号,即带有 sig 参数的信号处理程序。

进程接收到信号以后,可以有如下3种选择进行处理:

1. 接收默认处理:接收默认处理的进程通常会导致进程本身消亡。例如连接到终端的进程,用户按下CTRL+c,将导致内核向进程发送一个SIGINT的信号,进程如果不对该信号做特殊的处理,系统将采用默认的方式处理该信号,即终止进程的执行;

2.忽略信号:进程可以通过代码,显示地忽略某个信号的处理,例如:signal(SIGINT,SIGDEF);但是某些信号是不能被忽略的,

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>

void sighandler(int);

int main()
{
   signal(SIGINT, sighandler);

   while(1) 
   {
      printf("开始休眠一秒钟...\n");
      sleep(1);
   }

   return(0);
}

void sighandler(int signum)
{
   printf("捕获信号 %d,跳出...\n", signum);
   exit(1);
}

让我们编译并运行上面的程序,这将产生以下结果,且程序会进入无限循环,需使用 CTRL + C 键跳出程序。

3.捕捉信号并处理:进程可以事先注册信号处理函数,当接收到信号时,由信号处理函数自动捕捉并且处理信号。

有两个信号既不能被忽略也不能被捕捉,它们是SIGKILL和SIGSTOP。即进程接收到这两个信号后,只能接受系统的默认处理,即终止线程。

 

 which的取值根据who来选择,一般关注进程优先级

PRIO_PROCESS  PRIO_PGRP   PRIO_USER

 

 

 

 

#include <cstdio>
#include<iostream>
#include<unistd.h>  //头文件


#include<fcntl.h>
#include<sys/file.h>
#include<error.h>  //errno
#include<string.h> //strerror
#include<assert.h>
#include<setjmp.h>
#include<signal.h>




#include<stdlib.h>

void pra(){

	int ret = system("ls -l");
	printf("system return : %d\n", ret);
	ret = system("mkdir test");
	printf("system return : %d\n", ret);
	char buffer[512] = "";
	snprintf(buffer, sizeof buffer, "echo \"%s\">test/test.txt", __FUNCTION__);
	//组合使用可以进行批处理
	printf("%s\n", buffer);
	ret = system(buffer);
	printf("system return : %d\n", ret);
}

int main() {

	pra();
	return 0;
}

 补充知识:

 

 

 

7.文件和目录函数

 总结open与fopen的区别 - NickyYe - 博客园 (cnblogs.com)

 

 实现文件输出重定向

 

void pra1() {


	FILE* pFile = fopen("./test.txt", "r");
	if (pFile != NULL) {
		//char buffer[4096] 栈上申请的buffer不要超过64k
		char* buffer = new char[1024*10];  //单词内存分配最好不要超过2G
		memset(buffer, 0 , 1024 * 10);
		size_t ret = fread(buffer, 1, 1024, pFile);
		printf("num : %d  <%s> \n", ret,buffer);
		fclose(pFile);
	}
	else {
		printf("open error\n");
	}


}

 

void pra() {


	FILE* pFile = fopen("./test.txt", "r");
	if (pFile != NULL) {
		char* buffer = new char[1024*10];  //单词内存分配最好不要超过2G
		printf("%s(%d):%s  [%c]\n", __FILE__, __LINE__, __FUNCTION__,fgetc(pFile));
		printf("%s(%d):%s  [%s]\n", __FILE__, __LINE__, __FUNCTION__, fgets(buffer,1024*10 ,pFile));
		printf("[%d]\n", fgetc(pFile));
		fclose(pFile);
	}
	else {
		printf("open error\n");
	}


}

 每次读写都会改变文件中位值的指针记录

 

 

 

 

 

 

 

while(!feof(pFile)){
    bzero(buffer,sizeof buffer);
    fgets(buffer,sizeof buffer,pFile);
}

	int ret = 0;
	ret = mkdir( "he" ,  755);

	std::cout << ret << std::endl;

int ret = 0;
//ret = mkdir( "he" ,  755);
remove("he");
std::cout << ret << std::endl;

 

 

 

 

 递归遍历目录

 

 

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

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

相关文章

测试的概念

测试职责 需求分析 测试分析 设计测试用例 执行测试用例 掌握自动化测试技术 验证产品是否实现了应该实现的功能,或者实现了不应该实现的功能 在整个软件生命周期中&#xff0c;测试是一个贯穿始终的过程&#xff0c;它包含了不同阶段和不同类型的测试,以此来保证软件工程的稳…

黑马头条---day1

手机端查看 docker 容器&#xff0c;镜像操作命令 1、docker删除所有镜像命令 删除所有镜像的命令是Docker中一个非常常见的操作。下面是具体的实现步骤和命令示例&#xff1a; $ docker stop $(docker ps -aq) 停止所有正在运行的容器。 $ docker rm $(docker ps -aq) 删…

靶机精讲之NYX

主机发现 端口扫描 服务扫描 -sV漏洞脚本扫描 UDP扫描 那些开发那些关闭 脚本扫描 或许有价值.php web渗透 看源码 目录爆破 没有扫到有价值的信息 继续web渗透&#xff0c;访问admin目录 继续目录扫描 sudo gobuster dir -u http://192.168.10.206 -x txt,sql,php,jsp -w…

20.1 HTML 介绍

1. W3C组织 万维网联盟(World Wide Web Consortium, W3C): 是一个国际性的标准化组织, 致力于开发和推广Web标准.W3C的使命是通过制定和推广Web技术标准, 促进Web的长期发展和互操作性, 它由许多组织和个人组成, 包括浏览器制造商, 软件开发商, 网络服务提供商, 学术机构和个…

线性代数(应用篇):第五章:特征值与特征向量、第六章:二次型

文章目录 第5章 特征值与特征向量、相似矩阵(一) 特征值与特征向量1.定义2.性质3.求解(1)具体型矩阵试根法、多项式带余除法&#xff1a;三阶多项式分解因式 (2)抽象型矩阵 (二) 相似1.矩阵相似(1)定义(2)性质 2.相似对角化(1)定义(2)相似对角化的条件&#xff08;n阶矩阵A可相…

python机器学习(五)逻辑回归、决策边界、代价函数、梯度下降法实现线性和非线性逻辑回归

线性回归所解决的问题是把数据集的特征传入到模型中&#xff0c;预测一个值使得误差最小&#xff0c;预测值无限接近于真实值。比如把房子的其他特征传入到模型中&#xff0c;预测出房价&#xff0c; 房价是一系列连续的数值&#xff0c;线性回归解决的是有监督的学习。有很多场…

【微服务】springboot整合mongodb使用详解

目录 一、mongodb简介 1.1 什么是mongodb 1.2 mongodb特点 二、mongodb中的核心术语 2.1 mogodb与数据库对比 2.2 mongodb中的核心概念 2.3 与关系数据库的差异 2.3.1 半结构化 2.3.2 支持多级嵌套 2.3.3 关系弱化 三、mongodb 技术优势和应用场景 3.1 mongodb 技术…

【C#】并行编程实战:并行编程中的模式

本章将介绍并行编程模式&#xff0c;重点是理解并行代码问题场景并使用并行编程/异步技术解决他们。本章会介绍几种最重要的编程模式。 本教程学习工程&#xff1a;魔术师Dix / HandsOnParallelProgramming GitCode 1、MapReduce 模式 引入 MapReduce 是为了解决处理大数据的问…

睡眠健康数据分析

项目背景 背景描述 本数据集涵盖了与睡眠和日常习惯有关的诸多变量。如性别、年龄、职业、睡眠时间、睡眠质量、身体活动水平、压力水平、BMI类别、血压、心率、每日步数、以及是否有睡眠障碍等细节。 数据集的主要特征&#xff1a; 综合睡眠指标&#xff1a; 探索睡眠持续时…

UNISOT让食品欺诈无处遁形

​​发表时间&#xff1a;2023年5月11日 全世界的消费者开始越来越关注食物的来源和采购方式。这是因为人们渴望吃得更健康、更用心&#xff0c;同时人们也认识到了购买可持续且合乎伦理道德的产品的必要性。 近年来&#xff0c;人们对食品溯源的渴望进一步加速&#xff0c;原…

Python读取csv、Excel文件生成图表

简介 本文章介绍了通过读取 csv 或 Excel 文件内容&#xff0c;将其转换为折线图或柱状图的方法&#xff0c;并写入 html 文件中。 目录 1. 读取CSV文件 1.1. 生成折线图 1.1.1. 简单生成图表 1.1.2. 设置折线图格式 1.2. 生成柱状图 1.2.1. 简单生成图表 1.2.2. 设置柱…

文章详情页 - 评论功能的实现

目录 1. 准备工作 1.1 创建评论表 1.2 创建评论实体类 1.3 创建 mapper 层评论接口和对应的 xml 实现 1.4 准备评论的 service 层 1.5 准备评论的 controller 层 2. 总的初始化详情页 2.1 加载评论列表 2.1.1 实现前端代码 2.1.2 实现后端代码 2.2 查询当前登录用户的…

Docker安装es以及ik分词器

1、拉取镜像 docker pull elasticsearch:7.10.12、下载对应版本的ik分词、并将它们解压到ik文件夹下&#xff0c;如图 https://github.com/medcl/elasticsearch-analysis-ik/releases 3、在服务器上创建文件夹 mkdir /usr/elklog/elk/es mkdir /usr/elklog/elk/es/data mkdi…

【C进阶】回调函数(指针进阶2,详解,小白必看)

目录 6. 函数指针数组 6.1简单计算器 6.2函数指针数组实现计算器 7. 指向函数指针数组的指针(仅作了解即可) 8.回调函数 8.1关于回调函数的理解​编辑 8.1.1用回调函数改良简单计算器 8.2qsort库函数的使用 8.2.1冒泡排序 8.2.2qsort的概念 8.3冒泡排序思想实现qsor…

docker存储空间报错解决(谨慎操作,会影响原来的容易镜像,不熟练切勿操作)

报错内容 [rootDream package]# docker build -t imapp . [] Building 21.0s (6/19)> [internal] load build definition from Dockerfile 0.1s> > transferring …

TCP 三次握手四次挥手浅析

大家都知道传输层中的TCP协议是面向连接的&#xff0c;提供可靠的连接服务&#xff0c;其中最出名的就是三次握手和四次挥手。 一、三次握手 三次握手的交互过程如下 喜欢钻牛角尖的我在学习三次握手的时候就想到了几个问题&#xff1a;为什么三次握手是三次&#xff1f;不是…

AnimateDiff论文解读-基于Stable Diffusion文生图模型生成动画

文章目录 1. 摘要2. 引言3. 算法3.1 Preliminaries3.2. Personalized Animation3.3 Motion Modeling Module 4. 实验5.限制6. 结论 论文&#xff1a; 《AnimateDiff: Animate Your Personalized Text-to-Image Diffusion Models without Specific Tuning》 github: https://g…

销售易和管易云接口打通对接实战

销售易和管易云接口打通对接实战 来源系统:销售易 销售易CRM支持企业从营销、销售到服务的全流程自动化业务场景&#xff0c;创新性地利用AI、大数据、物联网等新型互联网技术打造双中台型CRM&#xff1b;既能帮助B2B企业连接外部经销商、服务商、产品以及最终用户&#xff0c;…

支持多种通信方式和协议方便接入第三方服务器或云平台

2路RS485串口是一种常用的通信接口&#xff0c;可以支持Modbus Slave协议&#xff0c;并可接入SCADA、HMI、DSC、PLC等上位机。它还支持Modbus RTU Master协议&#xff0c;可用于扩展多达48个Modbus Slave设备&#xff0c;如Modbus RTU远程数据采集模块、电表、水表、柴油发电机…

【Rust学习 | 基础系列3 | Hello, Rust】编写并运行第一个Rust程序

文章目录 前言一&#xff0c;创建项目二&#xff0c;两种编译方式1. 使用rustc编译器编译2. 使用Cargo编译 总结 前言 在开始学习任何一门新的编程语言时&#xff0c;都会从编写一个简单的 “Hello, World!” 程序开始。在这一章节中&#xff0c;将会介绍如何在Rust中编写并运…