linux系统编程重点复习--进程之间通信

news2024/11/15 12:21:49

目录

复习目标

2 进程间通信相关概念

2.1 什么是进程间通信

 2.2 进程间通信的方式

3 管道-pipe

3.1管道的概念

3.2管道的原理

3.3管道的局限性

3.4创建管道-pipe函数

3.5父子进程使用管道通信

3.6 管道练习

3.7 管道的读写行为

3.8 如何设置管道为非阻塞

3.9 如何查看管道缓冲区大小

4 FIFO

4.1 FIFO介绍

4.2 创建管道

4.3 使用FIFO完成两个进程通信

5 内存映射区

5.1 存储映射区介绍

 5.2 mmap函数

5.3 munmap函数

5.4 mmap注意事项

5.5 有关mmap函数的使用总结

5.6 mmap函数相关思考题

5.7 mmap应用练习


  1. 复习目标

  • 熟练使用pipe进行父子进程间通信
  • 熟练使用pipe进行兄弟进程间通信
  • 熟练使用fifo进行无血缘关系的进程间通信
  • 使用mmap进行有血缘关系的进程间通信
  • 使用mmap进行无血缘关系的进程间通信

2 进程间通信相关概念

2.1 什么是进程间通信

Linux环境下,进程地址空间相互独立,每个进程各自有不同的用户地址空间。任何一个进程的全局变量在另一个进程中都看不到,所以进程和进程之间不能相互访问,要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲区把数据读走,内核提供的这种机制称为进程间通信(IPC,InterProcess Communication)。

 2.2 进程间通信的方式

  • 管道 (使用最简单)
  • 信号 (开销最小)
  • 共享映射区 (无血缘关系)
  • 本地套接字 (最稳定)

3 管道-pipe

3.1管道的概念

管道是一种最基本的IPC机制,也称匿名管道,应用于有血缘关系的进程之间,完成数据传递。调用pipe函数即可创建一个管道。

有如下特质:

  • 管道的本质是一块内核缓冲区
  • 由两个文件描述符引用,一个表示读端,一个表示写端。
  • 规定数据从管道的写端流入管道,从读端流出。
  • 当两个进程都终结的时候,管道也自动消失。
  • 管道的读端和写端默认都是阻塞的。

3.2管道的原理

  • 管道的实质是内核缓冲区,内部使用环形队列实现。
  • 默认缓冲区大小为4K,可以使用ulimit -a命令获取大小。
  • 实际操作过程中缓冲区会根据数据压力做适当调整。

3.3管道的局限性

  • 数据一旦被读走,便不在管道中存在,不可反复读取。
  • 数据只能在一个方向上流动,若要实现双向流动,必须使用两个管道

只能在有血缘关系的进程间使用管道

3.4创建管道-pipe函数

  • 函数作用:

创建一个管道

  • 函数原型:

int pipe(int fd[2]);

  • 函数参数:

若函数调用成功,fd[0]存放管道的读端,fd[1]存放管道的写端

  • 返回值:
  • 成功返回0;
  • 失败返回-1,并设置errno值。

函数调用成功返回读端和写端的文件描述符,其中fd[0]是读端, fd[1]是写端向管道读写数据是通过使用这两个文件描述符进行的,读写管道的实质是操作内核缓冲区。管道创建成功以后,创建该管道的进程(父进程)同时掌握着管道的读端和写端。如何实现父子进程间通信呢?

3.5父子进程使用管道通信

一个进程在由pipe()创建管道后,一般再fork一个子进程,然后通过管道实现父子进程间的通信(因此也不难推出,只要两个进程中存在血缘关系,这里的血缘关系指的是具有共同的祖先,都可以采用管道方式来进行通信)。父子进程间具有相同的文件描述符,且指向同一个管道pipe,其他没有关系的进程不能获得pipe()产生的两个文件描述符,也就不能利用同一个管道进行通信。

第一步:父进程创建管道

 第二步:父进程fork出子进程

 第三步:父进程关闭fd[0],子进程关闭fd[1]

创建步骤总结:

  • 父进程调用pipe函数创建管道,得到两个文件描述符fd[0]和fd[1],分别指向管道的读端和写端。
  • 父进程调用fork创建子进程,那么子进程也有两个文件描述符指向同一管。
  • 父进程关闭管道读端,子进程关闭管道写端。父进程可以向管道中写入数据,子进程将管道中的数据读出,这样就实现了父子进程间通信。

3.6 管道练习

  • 一个进程能否使用管道完成读写操作呢?
  • 使用管道完成父子进程间通信?
  • 父子进程间通信, 实现ps aux | grep bash使用execlp函数和dup2函数
  • 兄弟进程间通信, 实现ps aux | grep bash
  • 使用execlp函数和dup2函数

父进程要调用waitpid函数完成对子进程的回收

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>

int main()
{
	//创建管道
	//int pipe(int pipefd[2]);
	int fd[2];
	int ret = pipe(fd);
	if(ret<0)
	{
		perror("pipe error");
		return -1;
	}

	//创建子进程
	pid_t pid = fork();
	if(pid<0) 
	{
		perror("fork error");
		return -1;
	}
	else if(pid>0)
	{
		//关闭读端
		close(fd[0]);
		sleep(5);
		write(fd[1], "hello world", strlen("hello world"));	

		wait(NULL);
	}
	else 
	{
		//关闭写端
		close(fd[1]);
		
		char buf[64];
		memset(buf, 0x00, sizeof(buf));
		int n = read(fd[0], buf, sizeof(buf));
		printf("read over, n==[%d], buf==[%s]\n", n, buf);
	
	}

	return 0;
}

3.7 管道的读写行为

  • 读操作
  • 有数据

read正常读,返回读出的字节数

  • 无数据
  • 写端全部关闭

read解除阻塞,返回0, 相当于读文件读到了尾部

没有全部关闭。

read阻塞

  • 写操作
  • 读端全部关闭

管道破裂,进程终止, 内核给当前进程发SIGPIPE信号

  • 读端没全部关闭
  • 缓冲区写满了

write阻塞

  • 缓冲区没有满

继续write

3.8 如何设置管道为非阻塞

默认情况下,管道的读写两端都是阻塞的,若要设置读或者写端为非阻塞,则可参

考下列三个步骤进行:

第1步: int flags = fcntl(fd[0], F_GETFL, 0);

第2步: flag |= O_NONBLOCK;

第3步: fcntl(fd[0], F_SETFL, flags);

若是读端设置为非阻塞:

  • 写端没有关闭,管道中没有数据可读,则read返回-1;
  • 写端没有关闭,管道中有数据可读,则read返回实际读到的字节数
  • 写端已经关闭,管道中有数据可读,则read返回实际读到的字节数
  • 写端已经关闭,管道中没有数据可读,则read返回0
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <fcntl.h>

int main()
{
	//创建管道
	//int pipe(int pipefd[2]);
	int fd[2];
	int ret = pipe(fd);
	if(ret<0)
	{
		perror("pipe error");
		return -1;
	}
	printf("pipe size==[%ld]\n", fpathconf(fd[0], _PC_PIPE_BUF));
	printf("pipe size==[%ld]\n", fpathconf(fd[1], _PC_PIPE_BUF));

	//close(fd[0]);
	//write(fd[1], "hello world", strlen("hello world"));	

	//关闭写端
	close(fd[1]);

	//设置管道的读端为非阻塞
	int flag = fcntl(fd[0], F_GETFL);
	flag |= O_NONBLOCK;
	fcntl(fd[0], F_SETFL, flag);

	char buf[64];
	memset(buf, 0x00, sizeof(buf));
	int n = read(fd[0], buf, sizeof(buf));
	printf("read over, n==[%d], buf==[%s]\n", n, buf);

	return 0;
}

3.9 如何查看管道缓冲区大小

  • 命令
  • ulimit -a

  • 函数
  • long fpathconf(int fd, int name);

    printf("pipe size==[%ld]\n", fpathconf(fd[0], _PC_PIPE_BUF));

    printf("pipe size==[%ld]\n", fpathconf(fd[1], _PC_PIPE_BUF));

//使用pipe完成ps aux | grep bash操作
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>

int main()
{
	//创建管道
	//int pipe(int pipefd[2]);
	int fd[2];
	int ret = pipe(fd);
	if(ret<0)
	{
		perror("pipe error");
		return -1;
	}

	//创建子进程
	pid_t pid = fork();
	if(pid<0) 
	{
		perror("fork error");
		return -1;
	}
	else if(pid>0)
	{
		//关闭读端
		close(fd[0]);

		//将标准输出重定向到管道的写端
		dup2(fd[1], STDOUT_FILENO);
		
		execlp("ps", "ps", "aux", NULL);

		perror("execlp error");
	}
	else 
	{
		//关闭写端
		close(fd[1]);
	
		//将标准输入重定向到管道的读端
		dup2(fd[0], STDIN_FILENO);

		execlp("grep", "grep", "--color=auto", "bash", NULL);

		perror("execlp error");
	}

	return 0;
}

 

4 FIFO

4.1 FIFO介绍

FIFO常被称为命名管道,以区分管道(pipe)。管道(pipe)只能用于“有血缘关系”的进程间通信。但通过FIFO,不相关的进程也能交换数据。

FIFO是Linux基础文件类型中的一种(文件类型为p,可通过ls -l查看文件类型)。但FIFO文件在磁盘上没有数据块,文件大小为0,仅仅用来标识内核中一条通道。进程可以打开这个文件进行read/write,实际上是在读写内核缓冲区,这样就实现了进程间通信。

4.2 创建管道

  • 方式1-使用命令 mkfifo

命令格式: mkfifo 管道名

例如:mkfifo myfifo

  • 方式2-使用函数

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

参数说明和返回值可以查看man 3 mkfifo

当创建了一个FIFO,就可以使用open函数打开它,常见的文件I/O函数都可用于FIFO。如:close、read、write、unlink等。

FIFO严格遵循先进先出(first in first out),对FIFO的读总是从开始处返回数据,对它们的写则把数据添加到末尾。它们不支持诸如lseek()等文件定位操作。

//fifo完成两个进程间通信的测试
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>

int main()
{
	//创建fifo文件
	//int mkfifo(const char *pathname, mode_t mode);
	//判断myfofo文件是否存在,若不存在则创建
	int ret = access("./myfifo", F_OK);
	if(ret!=0)
	{
		ret = mkfifo("./myfifo", 0777);
		if(ret<0)
		{
			perror("mkfifo error");
			return -1;
		}
	}

	//打开文件
	int fd = open("./myfifo", O_RDWR);
	if(fd<0)
	{
		perror("open error");
		return -1;
	}

	//读fifo文件
	int n;
	char buf[64];
	while(1)
	{
		memset(buf, 0x00, sizeof(buf));
		n = read(fd, buf, sizeof(buf));
		printf("n==[%d], buf==[%s]\n", n, buf);
	}

	//关闭文件
	close(fd);

	//getchar();

	return 0;
}

4.3 使用FIFO完成两个进程通信

使用FIFO完成两个进程通信的示意图

思路:

  • 进程A:
  • 创建一个fifo文件:myfifo
  • 调用open函数打开myfifo文件
  • 调用write函数写入一个字符串如:“hello world”(其实是将数据写入到了内核缓冲区)
  • 调用close函数关闭myfifo文件
  • 进程B:
  • 调用open函数打开myfifo文件
  • 调用read函数读取文件内容(其实就是从内核中读取数据)
  • 打印显示读取的内容
  • 调用close函数关闭myfifo文件

注意:myfifo文件是在进程A中创建的,如果先启动进程B会报错。思考一下如何解决这个问题呢???

//fifo完成两个进程间通信的测试
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>

int main()
{
	//创建fifo文件
	//int mkfifo(const char *pathname, mode_t mode);
	int ret = access("./myfifo", F_OK);
	if(ret!=0)
	{		
		ret = mkfifo("./myfifo", 0777);
		if(ret<0)
		{
			perror("mkfifo error");
			return -1;
		}
	}

	//打开文件
	int fd = open("./myfifo", O_RDWR);
	if(fd<0)
	{
		perror("open error");
		return -1;
	}

	//写fifo文件
	int i = 0;
	char buf[64];
	while(1)
	{
		memset(buf, 0x00, sizeof(buf));
		sprintf(buf, "%d:%s", i, "hello world");
		write(fd, buf, strlen(buf));
		sleep(1);

		i++;
	}

	//关闭文件
	close(fd);

	//getchar();

	return 0;
}

5 内存映射区

5.1 存储映射区介绍

存储映射I/O (Memory-mapped I/O) 使一个磁盘文件与存储空间中的一个缓冲区相映射。从缓冲区中取数据,就相当于读文件中的相应字节;将数据写入缓冲区,则会将数据写入文件。这样,就可在不使用read和write函数的情况下,使用地址(指针)完成I/O操作。

使用存储映射这种方法,首先应通知内核,将一个指定文件映射到存储区域中。这个映射工作可以通过mmap函数来实现。

 5.2 mmap函数

  • 函数作用:

建立存储映射区

  • 函数原型

   void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);

  • 函数返回值:
  • 成功:返回创建的映射区首地址;
  • 失败:MAP_FAILED宏
  • 参数:
    • addr: 指定映射的起始地址, 通常设为NULL, 由系统指定
    • length:映射到内存的文件长度
    • prot: 映射区的保护方式, 最常用的:
      1. 读:PROT_READ
      2. 写:PROT_WRITE
      3. 读写:PROT_READ | PROT_WRITE
        • flags: 映射区的特性, 可以是
          1. MAP_SHARED: 写入映射区的数据会写回文件, 且允许其他映射该文件的进程共享。
          2. MAP_PRIVATE: 对映射区的写入操作会产生一个映射区的复制(copy-on-write), 对此区域所做的修改不会写回原文件。
        • fd:由open返回的文件描述符, 代表要映射的文件。
      4. offset:以文件开始处的偏移量, 必须是4k的整数倍, 通常为0, 表示从文件头开始映射

5.3 munmap函数

  • 函数作用:

释放由mmap函数建立的存储映射区

  • 函数原型:

int munmap(void *addr, size_t length);

  • 返回值:

成功:返回0

失败:返回-1,设置errno值

  • 函数参数:
  • addr:调用mmap函数成功返回的映射区首地址

length:映射区大小(mmap函数的第二个参数)

5.4 mmap注意事项

  • 创建映射区的过程中,隐含着一次对映射文件的读操作,将文件内容读取到映射区
  • 当MAP_SHARED时,要求:映射区的权限应 <=文件打开的权限(出于对映射区的保护)。而MAP_PRIVATE则无所谓,因为mmap中的权限是对内存的限制。
  • 映射区的释放与文件关闭无关,只要映射建立成功,文件可以立即关闭。
  • 特别注意,当映射文件大小为0时,不能创建映射区。所以,用于映射的文件必须要有实际大小;mmap使用时常常会出现总线错误,通常是由于共享文件存储空间大小引起的。
  • munmap传入的地址一定是mmap的返回地址。坚决杜绝指针++操作。
  • 文件偏移量必须为0或者4K的整数倍
  • mmap创建映射区出错概率非常高,一定要检查返回值,确保映射区建立成功再进行后续操作。

5.5 有关mmap函数的使用总结

  • 第一个参数写成NULL
  • 第二个参数要映射的文件大小 > 0
  • 第三个参数:PROT_READ 、PROT_WRITE
  • 第四个参数:MAP_SHARED 或者 MAP_PRIVATE
  • 第五个参数:打开的文件对应的文件描述符
  • 第六个参数:4k的整数倍

5.6 mmap函数相关思考题

  • 可以open的时候O_CREAT一个新文件来创建映射区吗?
  • 如果open时O_RDONLY, mmap时PROT参数指定PROT_READ|PROT_WRITE会怎样?
  • mmap映射完成之后, 文件描述符关闭,对mmap映射有没有影响?
  • 如果文件偏移量为1000会怎样?
  • 对mem越界操作会怎样?
  • 如果mem++,munmap可否成功?
  • mmap什么情况下会调用失败?
  • 如果不检测mmap的返回值,会怎样?

5.7 mmap应用练习

        

  • 练习1:使用mmap完成对文件的读写操作
  • 练习:2:使用mmap完成父子进程间通信
  • 图解说明
  • 思路
  • 调用mmap函数创建存储映射区,返回映射区首地址ptr
  • 调用fork函数创建子进程,子进程也拥有了映射区首地址
  • 父子进程可以通过映射区首地址指针ptr完成通信
  • 调用munmap函数释放存储映射区
  • 练习3:使用mmap完成没有血缘关系的进程间通

思路:两个进程都打开相同的文件,然后调用mmap函数建立存储映射区,这样两个进程共享同一个存储映射区。

//fifo完成两个进程间通信的测试
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>

int main()
{
	//创建fifo文件
	//int mkfifo(const char *pathname, mode_t mode);
	//判断myfofo文件是否存在,若不存在则创建
	int ret = access("./myfifo", F_OK);
	if(ret!=0)
	{
		ret = mkfifo("./myfifo", 0777);
		if(ret<0)
		{
			perror("mkfifo error");
			return -1;
		}
	}

	//打开文件
	int fd = open("./myfifo", O_RDWR);
	if(fd<0)
	{
		perror("open error");
		return -1;
	}

	//读fifo文件
	int n;
	char buf[64];
	while(1)
	{
		memset(buf, 0x00, sizeof(buf));
		n = read(fd, buf, sizeof(buf));
		printf("n==[%d], buf==[%s]\n", n, buf);
	}

	//关闭文件
	close(fd);

	//getchar();

	return 0;
}

使用mmap函数建立匿名映射:

mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);

//fifo完成两个进程间通信的测试
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>

int main()
{
	//创建fifo文件
	//int mkfifo(const char *pathname, mode_t mode);
	//判断myfofo文件是否存在,若不存在则创建
	int ret = access("./myfifo", F_OK);
	if(ret!=0)
	{
		ret = mkfifo("./myfifo", 0777);
		if(ret<0)
		{
			perror("mkfifo error");
			return -1;
		}
	}

	//打开文件
	int fd = open("./myfifo", O_RDWR);
	if(fd<0)
	{
		perror("open error");
		return -1;
	}

	//读fifo文件
	int n;
	char buf[64];
	while(1)
	{
		memset(buf, 0x00, sizeof(buf));
		n = read(fd, buf, sizeof(buf));
		printf("n==[%d], buf==[%s]\n", n, buf);
	}

	//关闭文件
	close(fd);

	//getchar();

	return 0;
}

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

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

相关文章

Maven设置阿里云路径(防止加载过慢)

<?xml version="1.0" encoding="UTF-8"?><!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regardin…

git | git使用心得记录

公司里项目最近使用Git进行协作开发&#xff0c;总结一下使用心得 一、第一次用git&#xff0c;完全同步最新代码checkout 按照以下步骤操作 1、git init 2、git remote add origin 远程仓库的地址https://gitlab.xxxx.com.cn/xx/xx/xxx/Android/baseline/x.x.x.git(远程仓库…

剑指offer48.最长不含重复字符的子字符串

我一开始的想法是创建一个大小为26的int数组&#xff0c;下标为0对应的是‘a&#xff0c;25对应的是’z&#xff0c;然后一开始都赋为-1&#xff0c;用一个for循环从头遍历这个字符串&#xff0c;通过char c s.charAt(i)获得字符&#xff0c;然后c-97&#xff0c;就是它对应的…

《向量数据库指南》——向量数据库向专业化和智能化的发展趋势

随着数据的规模不断扩大和信息技术的发展,向量数据库在各个行业中扮演着越来越重要的角色。未来,随着技术的不断进步和市场需求的不断增长,向量数据库的应用将更加广泛和深入,同时也会出现更加专业化和智能化的趋势。 一、向量数据库的专业化发展 随着各个行业数据量的不…

【雕爷学编程】Arduino动手做(178)---超迷你哦,用徽商香烟盒做个智能小车2

早上去打羽毛球&#xff0c;路上捡到一个香烟盒子&#xff0c;于是就想尝试一下&#xff0c;捣鼓捣鼓。 经测试&#xff0c;控制器与电机使用同一组电源会互相干扰&#xff0c;故只好再加一组电池 商徽烟盒小车内部结构总算整好了&#xff0c;够迷你吧 小车轮子准备用矿泉水瓶盖…

【ChatGPT辅助学Rust | 基础系列 | Cargo工具】Cargo介绍及使用

文章目录 前言一&#xff0c;Cargo介绍1&#xff0c;Cargo安装2&#xff0c;创建Rust项目2&#xff0c;编译项目&#xff1a;3&#xff0c;运行项目&#xff1a;4&#xff0c;测试项目&#xff1a;5&#xff0c;更新项目的依赖&#xff1a;6&#xff0c;生成项目的文档&#xf…

Go学习第二天

Defer语句调用顺序 package mainimport "fmt"func main() {defer fmt.Println("main end1 先进后出")defer fmt.Println("main end2 后进先出")fmt.Println("main hello go 1")fmt.Println("main hello go 2") }重点&…

Android性能优化—LeakCanary内存泄漏检测框架分析。

一、什么叫内存泄漏、内存溢出&#xff1f; 内存溢出(out of memory)&#xff1a;是指程序在申请内存时&#xff0c;没有足够的内存空间供其使用&#xff0c;出现out of memory&#xff1b;比如申请了一个10M的Bitmap&#xff0c;但系统分配给APP的连续内存不足10M&#xff0c…

Cpp7 — 继承和多态

继承 -------- 面向对象的三大特性之一 面向对象的三大特性&#xff1a;封装、继承、多态 封装&#xff1a;把数据和方法都封装在一起&#xff0c;想给你访问的变成共有&#xff0c;不想给访问的&#xff0c;写成私有。 继承&#xff1a;继承是类设计层次的复用 多态&#…

物联网远程智能控制设备——开关量/正反转百分比控制

如今生产生活的便利性极大程度上得益于控制技术的发展&#xff0c;它改变了传统的工作模式&#xff0c;并将人们从【纯劳力】中解放出来。如今&#xff0c;随着科学技术的进步&#xff0c;控制器的种类及应用领域也越来越多。 物联网远程智能控制设备就是一种新型的、能够用于…

VSCode自定义闪烁光标

打开VSCode 组合键ctrlshiftp搜索"settings.json",打开User Settings 加上这一句 "editor.cursorStyle": "block","workbench.colorCustomizations": {"editorCursor.foreground": "#5c8fb1","terminalCurs…

拓数派入选中国信通院 “铸基计划”「高质量数字化转型产品及服务全景图」

7 月 27 日&#xff0c;由中国信息通信研究院&#xff08;以下简称 “中国信通院”&#xff09;主办的 “2023 数字生态发展大会” 暨中国信通院 “铸基计划” 年中会议在京召开&#xff0c;本次大会深度展示了中国信通院在数字化领域的工作成果&#xff0c;并正式发布了《高质…

HCIP BGP概念、工作原理、特点总结

BGP概念 BGP---边界网关路由协议&#xff0c;无类别的路径矢量EBP协议 BGP类别的路由协议&#xff0c;用于AS与AS间进行路由条目共享&#xff1b; AS指的是在同一个组织管理下&#xff0c;使用统一选路策略的设备集合&#xff0c;不同AS号通过AS号来区分&#xff0c;AS号存在…

小程序如何上传商品图片

了解如何在小程序商城中上传商品图片是非常重要的&#xff0c;因为商品图片的质量和展示效果直接影响到用户对商品的购买决策。下面&#xff0c;我将介绍怎么在小程序上传产品图片的方法和注意事项。 1. 图片准备&#xff1a;在上传商品图片之前&#xff0c;首先要准备好商品图…

Android手机使用无线调试进行adb连接

平时进行真机调试apk的时候&#xff0c;总是要插着数据线&#xff0c;比较麻烦&#xff0c;而使用无线调试就可以方便的进行连接&#xff0c;步骤如下&#xff1a; 1、进入设置找到开发者选项 2、打开开发者选项中的无线调试 3、使用配对码进行配对&#xff0c;输入命令&…

IDEA中修改代码中注释的字体颜色

IDEA中修改代码中注释的字体颜色 一、修改文档注释的字体颜色 选择File--Settings--Color Scheme--Language Defaults&#xff0c;可以修改单行注释的字体颜色&#xff0c;多行注释的字体颜色以及文档注释的颜色&#xff0c;我一般习惯将文档注释和多行注释设置成绿色 008017…

运用大数据软件提高竞彩足球胜平负分析的准确率

竞彩足球是一种以足球比赛结果为基础的体育游戏&#xff0c;它吸引了众多热爱足球的球迷和彩票爱好者的参与。然而&#xff0c;要在竞彩足球中取得最佳的胜平负预测结果并非易事。幸运的是&#xff0c;随着大数据技术的不断发展和应用&#xff0c;我们可以利用大数据软件来提高…

这次,常温超导能否变为现实?

关注科研和技术的朋友近几天应当都听到韩国研发常温超导材料的消息了&#xff0c;作为攻城狮的我自然也是非常感兴趣&#xff0c;经过一番思想斗争还是放下了手上的单片机&#xff0c;想要一看这个常温超导的究竟&#xff0c;毕竟印象之中之前已经搞过好几次乌龙了。常温超导要…

overpass-turbo下载铁路线

overpass turbo /* This has been generated by the overpass-turbo wizard. The original search was: “road” */ [out:json]; rel(198494); out body; >; out skel qt; 上面的198498代表在osm中铁路线的id&#xff0c;这个id获取流程是从osm网站查询出来的 我也没啥好…

MPAndroidCahrt_linechart折线图实现读取本地文件生成曲线

目录 标题(Description)设置图例(Legend)设置(部分和标题一样的没写)X轴(XAxis)设置(上面有的属性不再写了)数据源(LineData)设置MainActivity 注释部分可以删掉,看需不需要效果如下,目前实现基本的读取数据生成曲线,可以正常运行 还有很多bug,比如生成一个数据在生成另…