当前位置: 首页 > news >正文

mmap详解

想写一篇文章,详细的介绍一下mmap,主要是原理、用法、mmap泄露来进行介绍。说到mmap,首先得从堆空间说起。

申请堆空间

其实,不管是 32 位系统还是 64 位系统,内核都会维护一个变量 brk,指向堆的顶部,所以,brk 的位置实际上就决定了堆的大小。Linux 系统为我们提供了两个重要的系统调用来修改堆的大小,分别是 sbrk 和 mmap。接下来,我们来学习这两个系统调用是如何使用的。我们先来看 sbrk。

sbrk

sbrk 函数的头文件和原型定义如下:

#include <unistd.h>void* sbrk(intptr_t incr);

sbrk 通过给内核的 brk 变量增加 incr,来改变堆的大小,incr 可以为负数。当 incr 为正数时,堆增大,当 incr 为负数时,堆减小。如果 sbrk 函数执行成功,那返回值就是 brk的旧值;如果失败,就会返回 -1,同时会把 errno 设置为 ENOMEM。

在实际应用中,我们很少直接使用 sbrk 来申请堆内存,而是使用 C 语言提供的 malloc 函数进行堆内存的分配,然后用 free 进行内存释放。这里你要注意的是,malloc 和 free 函数不是系统调用,而是 C 语言的运行时库。Linux 上的主流运行时库是 glibc,其他影响力比较大的运行时库还有 musl 等。C 语言的运行时库多是以动态链接库的方式实现的。

在 C 语言的运行时库里,malloc 向程序提供分配一小块内存的功能,当运行时库的内存分配完之后,它会使用 sbrk 方法向操作系统再申请一块大的内存。我们可以将 C 语言的运行时库类比为零售商,它从操作系统那里批发一块比较大的内存,然后再通过零售的方式一点点地提供给程序员使用。

mmap

另一个可以申请堆内存的系统调用是 mmap,它是最重要的内存管理接口。mmap 的头文件和原型如下所示:

#include <unistd.h>
#include <sys/mman.h>void *mmap(void *start,size_t length,int prot,int flags,int fd,off_t offsize); 

我来解释一下上述代码中的各个变量的意义:

start 代表该区域的起始地址;

length 代表该区域长度;

prot 描述了这块新的内存区域的访问权限;

flags 描述了该区域的类型;

fd 代表文件描述符;

offset 代表文件内的偏移值。

mmap 的功能非常强大,根据参数的不同,它可以用于创建共享内存,也可以创建文件映射区域用于提升 IO 效率,还可以用来申请堆内存。决定它的功能的,主要是 prot, flags和 fd 这三个参数,我们分别来看看。

prot 的值可以是以下四个常量的组合:

PROT_EXEC,表示这块内存区域有可执行权限,意味着这部分内存可以看成是代码段,它里面存储的往往是 CPU 可以执行的机器码。

PROT_READ,表示这块内存区域可读。

PROT_WRITE,表示这块内存区域可写。

PROT_NONE,表示这块内存区域的页面不能被访问。

而 flags 的值可取的常量比较多,你可以通过 man mmap 查看,这里我只列举一下最重要的四种可取值常量:

MAP_SHARED:创建一个共享映射的区域,多个进程可以通过共享映射的方式,来共享同一个文件。这样一来,一个进程对该文件的修改,其他进程也可以观察到,这就实现了数据的通讯。

MAP_PRIVATE:创建一个私有的映射区域,多个进程可以使用私有映射的方式,来映射同一个文件。但是,当一个进程对文件进行修改时,操作系统就会为它创建一个独立的副本,这样它对文件的修改,其他进程就看不到了,从而达到映射区域私有的目的。

MAP_ANONYMOUS:创建一个匿名映射,也就是没有关联文件。使用这个选项时,fd 参数必须为空。

MAP_FIXED:一般来说,addr 参数只是建议操作系统尽量以 addr 为起始地址进行内存映射,但如果操作系统判断 addr 作为起始地址不能满足长度或者权限要求时,就会另外再找其他适合的区域进行映射。如果 flags 的值取是 MAP_FIXED 的话,就不再把addr 看成是建议了,而是将其视为强制要求。如果不能成功映射,就会返回空指针。

通常,我们使用私有匿名映射来进行堆内存的分配。

我们再来看参数 fd。当参数 fd 不为 0 时,mmap 映射的内存区域将会和文件关联,如果fd 为 0,就没有对应的相关文件,此时就是匿名映射,flags 的取值必须为MAP_ANONYMOUS。

明白了 mmap 及其各参数的含义后,你肯定想知道什么场景下才会使用 mmap,我们又该怎么使用它。

mmap 的其他应用场景

mmap 这个系统调用的能力非常强大,我们在后面还会经常遇到它。在这节课里,我们先来了解一下它最常见的用法。
根据映射的类型,mmap 有四种最常用的组合:

其中,私有匿名映射常用于分配内存,也就是我们上文讲的申请堆内存,而私有文件映射常用于加载动态库。

这里我们重点看看共享匿名映射。我们通过一个例子,来了解一下 mmap 是如何用于父子进程之间的通信的,它的用法示例代码如下:

共享匿名映射 / 匿名共享映射

#include <stdio.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <unistd.h>int main(int argc,char* argv[])
{pid_t pid;char* shm = (char*)mmap(0, 4096, PROT_READ | PROT_WRITE,MAP_SHARED | MAP_ANONYMOUS, -1, 0);if(!(pid = fork())){sleep(1);printf("child got a message: %s\n",shm);sprintf(shm, "%s", "hello, father.");exit(0);}sprintf(shm, "%s", "hello, my child");sleep(2);printf("parent got a message: %s\n", shm);return 0;
}

wj@wj:~/WORK/Learning/learning/cpp_learning$ gcc test.c -o test.out 
wj@wj:~/WORK/Learning/learning/cpp_learning$ ./test.out 
child got a message: hello, my child
parent got a message: hello, father.

在这个过程中,我们先是用 mmap 方法创建了一块共享内存区域,命名为 shm,接着,又通过 fork 这个系统调用创建了子进程:具体来讲,子进程休眠一秒后,从 shm 中取出一行字符并打印出来,然后又向共享内存中写入了一行消息。

在子进程的执行逻辑之后,是父进程的执行逻辑:父进程先写入一行消息,然后休眠两秒,等待子进程完成读取消息和发消息的过程并退出后,父进程再从共享内存中取出子进程发过来的消息。

我想请你结合我刚才的讲解,来分析一下这个程序运行的结果,这样你就理解的更透彻
了。

关于共享匿名映射,我们就讲到这里,至于 mmap 的另一个组合共享文件映射。它的作用其实和共享匿名映射相似,也可以用于进程间通讯。不同的是,共享文件映射是通过文件名来创建共享内存区域的,这就让没有父子关系的进程,也可以通过相同的文件创建共享内存区域,从而可以使用共享内存进行进程间通讯。

私有匿名映射

mmap用途小结

mmap最常见的四种用途分别是:

  1. 私有匿名映射,用于分配堆空间;
  2. 私有文件映射,用于加载动态链接库;
  3. 共享匿名映射,用于父子进程之间通讯;
  4. 共享文件映射,用于多进程之间通讯。

mmap原理

私有匿名映射

私有匿名映射是最简单的情况, 在调用 mmap 时,只需要在文件映射区域分配一块内存, 然后创建这块内存所对应的 vma 结构,这次调用就结束了
当访问到这块虚拟内存时,由于这块虚拟内存都没有映射到物理内存上,就会发生缺页中 断,但这一次的缺页中断与 execve 时的缺页中断不一样,这次是匿名映射,所以关联文件属性为空。此时,内核就会调用 do_anonymous_page 来分配一个物理内存,并将整个物理页全部初始化为 0,然后在页表里建立起虚拟地址到物理地址的映射关系。

私有文件映射

在内核中,如果有一个进程打开了一个文件,PCB 中就会有一个 struct file 结构与这个文件对应。struct file 结构是与进程相关,假如进程 A 与进程 B 都打开了文件 f,那么进程 A 中就会有一个 struct file 结构,进程 B 中也会有一个。
Linux 的文件系统中有一个叫做 inode 的结构,这个结构与具体的磁盘上的文件是一一对应的,也就是说对于同一个文件,整个内核中只会有一个 inode 结构。所以进程 A 与进程 B 的 file struct 结构都有一个指针指向 inode 结构,这就将 file struct 与 inode 结构联系起来了。
在 inode 结构中,有一个哈希表,以文件的页号为 key,以物理内存页为 value。当进程 A 打开了文件 f,然后读取了它的第 4 页,这时,内核就会把 4 和这个物理页,放入这个 哈希表中。当进程 B 再打开文件 f,要读取它的第 4 页时,因为 f 的第 4 页的内容已经被 加载到物理页中了,所以就不用再加载一次了。只需要将 B 的虚拟地址与这个物理页建立 映射就可以了,如下图所示:

我要提醒你的是, 哈希表在现代的 Linux 内核中,已经被优化成了 Radix tree 和最小堆 的一种优化的数据结构,它们比哈希表有更好的时间效率,所以你在阅读不同版本的 Linux 内核代码时要注意这个变化
如果文件是只读的话,那这个文件在物理页的层面上其实是共享的。也就是进程 A 和进程 B 都有一页虚拟内存被映射到了相同的物理页上。但如果要写文件的时候,因为这一段内 存区域的属性是私有的,所以内核就会做一次写时复制,为写文件的进程单独地创建一份 副本。这样,一个进程在写文件时,并不会影响到其他进程的读。
对于共享库文件,代码段的私有属性其实并不影响它在所有进程间共享;但如果数据段在 执行的过程发生变化,内核就可以通过写时复制机制为每个进程创建一个副本。这就是对 于共享库文件要选择私有文件映射的根本原因。
这里我们就有这样一个结论: 私有文件映射的只读页是多进程间共享的,可写页是每个进 程都有一个独立的副本,创建副本的时机仍然是写时复制

共享文件映射

在私有文件映射的基础上,共享文件映射就很简单了: 对于可写的页面,在写的时候不进 行复制就可以了 。这样的话,无论何时,也无论是读还是写,多个进程在访问同一个文件 的同一个页时,访问的都是相同的物理页面。

共享匿名映射

在这节课之前,你可能会觉得共享匿名映射在父子进程间通讯是最简单的,因为父子进程 共享了相同的 mmap 的返回值,看上去最直观。但实际上,从内核的角度说,它却是最复杂的。
原因是 mmap 并不真正分配物理内存,它只是分配了一段虚拟内存,也就是说只在 PCB 中创建了一个 vma 结构而已。这就导致 fork 在复制页表的时候,页表中共享匿名映射区 域都是未映射状态
请你设想一下,如果内核不做特殊处理的话,在父进程因为访问共享内存区域而遇到缺页 中断时,内核为它分配了物理页面,等子进程再访问共享内存区域时,内核也没有办法知 道子进程的虚拟内存,应该映射到哪个物理页面上,因为缺页中断只能知道当前进程是 谁,以及发生问题的虚拟地址是什么,这些信息不足够计算出,是否有其他进程已经把共享内存准备好了。
在内核中使用虚拟文件系统来解决这个问题之前,早期的 Linux 内核中并不支持共享匿名 映射。虚拟文件并不是真实地在磁盘上存在的。它只是由内核模拟出来的,但是它也有自 己的 inode 结构。这样一来,内核就能在创建共享匿名映射区域时,创建一个虚拟文件, 并将这个文件与映射区域的 vma 关联起来。
当 fork 创建子进程时,子进程会复制父进程的全部 vma 信息。接下来发生的事情就和共 享文件映射完全一样了,我们就不再重复了。
至此,我们才终于把 mmap 的核心原理分析清楚。 mmap 的功能之所以十分强大,主是因为操作系统综合使用写保护中断、缺页中断和文件 机制来实现 mmap 的各种功能

相关文章:

mmap详解

想写一篇文章&#xff0c;详细的介绍一下mmap&#xff0c;主要是原理、用法、mmap泄露来进行介绍。说到mmap&#xff0c;首先得从堆空间说起。 申请堆空间 其实&#xff0c;不管是 32 位系统还是 64 位系统&#xff0c;内核都会维护一个变量 brk&#xff0c;指向堆的顶部&…...

项目02—基于keepalived+mysqlrouter+gtid半同步复制的MySQL集群

文章目录 一.项目介绍1.拓扑图2.详细介绍 二.前期准备1.项目环境2.IP划分 三. 项目步骤1.ansible部署软件环境1.1 安装ansible环境1.2 建立免密通道1.3 ansible批量部署软件1.4 统一5台mysql服务器的数据 2.配置基于GTID的半同步主从复制2.1 在master上安装配置半同步的插件,再…...

【EI征稿】第二届机械电子工程与人工智能国际学术会议(MEAI 2023)

第二届机械电子工程与人工智能国际学术会议&#xff08;MEAI 2023&#xff09; The 2nd International Conference on Mechatronic Engineering and Artificial Intelligence 2023年第二届机械电子工程与人工智能国际学术会议&#xff08;MEAI 2023&#xff09;计划将于2023年…...

ros2 学习launch文件组织工程 yaml配置文件

简单范例 功能描述 使用launch文件&#xff0c;统一管理工程&#xff0c;实现img转点云&#xff0c;发送到img_pt的topic&#xff0c;然后用reg_pcl节点进行subscribe&#xff0c;进行点云配准处理&#xff0c;输出融合后的点云到map_pt的topic。最后由rviz2进行点云展示。 …...

奇舞周刊第 505 期:实践指南-前端性能提升 270%!

记得点击文章末尾的“ 阅读原文 ”查看哟~ 下面先一起看下本期周刊 摘要 吧~ 奇舞推荐 ■ ■ ■ 实践指南-前端性能提升 270% 当我们疲于开发一个接一个的需求时&#xff0c;很容易忘记去关注网站的性能&#xff0c;到了某一个节点&#xff0c;猛地发现&#xff0c;随着越来越多…...

【C++】泛型编程 | 函数模板 | 类模板

一、泛型编程 泛型编程是啥&#xff1f; 编写一种一般化的、可通用的算法出来&#xff0c;是代码复用的一种手段。 类似写一个模板出来&#xff0c;不同的情况&#xff0c;我们都可以往这个模板上去套。 举个例子&#xff1a; void Swap(int& a, int& b) {int tmp …...

web前端——简单的网页布局案列

✨博主&#xff1a;命运之光 &#x1f338;专栏&#xff1a;Python星辰秘典 &#x1f433;专栏&#xff1a;web开发&#xff08;简单好用又好看&#xff09; ❤️专栏&#xff1a;Java经典程序设计 ☀️博主的其他文章&#xff1a;点击进入博主的主页 目录 问题背景 解决样例 …...

线程安全问题(3)--- wait(),notify()

前言 在多线程的环境下&#xff0c;我们常常要协调多个线程之间的执行顺序&#xff0c;而为了实现这一点&#xff0c;Java提供了一些方法来帮助我们完成这一点。 一&#xff0c;wait() 作用&#xff1a; 使当前线程进入等待状态 释放当前的锁 (即该方法必须和 synchrnized 关键…...

【Android知识笔记】进程通信(一)

一、Android Framework 用到了哪些 IPC 方式 Linux 的 IPC 方式有: 管道Socket共享内存信号信号量消息队列管道通信 管道是基于pipefs文件系统实现的,也就是多个进程通过对同一个文件进行读写来实现进程间通信。半双工,单向的,通过 pipe(fds) 系统函数调用可得到一对文件描…...

存储空间压缩6倍 ,多点DMALL零售SaaS场景降本实践

&#x1f9d1;‍&#x1f4bc; 作者简介 冯光普&#xff1a;多点 DMALL 数据库团队负责人&#xff0c;负责数据库稳定性建设与 DB PaaS 平台建设&#xff0c;在多活数据库架构、数据同步方案等方面拥有丰富经验。 杨家鑫&#xff1a;多点高级 DBA&#xff0c;擅长故障分析与性能…...

BGP路由属性

任何一条BGP路由都拥有多个路径属性&#xff08;Path Attributes&#xff09;&#xff0c;当路由器通告BGP路由给它的对等体时&#xff0c;该路由将会携带多个路径属性&#xff0c;这些属性描述了BGP路由的各项特征&#xff0c;同时在某些场景下也会影响BGP路由优选的决策。 一…...

Java面试常用函数

1. charAt() 方法用于返回字符串指定索引处的字符。索引范围为从 0 到 length() - 1。 map.getOrDefault(num, 0) :如果map存在num这个key&#xff0c;则返回num对应的value&#xff0c;否则返回0. Arrays.sort(nums); 数组排序 Arrays.asList("a","b",&q…...

linux编译curl库(支持https)

openssl下载和编译 https://www.openssl.org/source/old/ 解压 tar -xvf openssl-3.0.1.tar.gz cd openssl-3.0.1/配置 ./config如果是编译静态库加入 -fPIC no-shared 如果指定安装路径,使用 --prefix=/usr/local/openssl/选项指定特定目录 编译和安装 make sodu make i…...

Ei Scopus检索 | 2024年第三届能源与环境工程国际会议(CFEEE 2024)

会议简介 Brief Introduction 2024年第三届能源与环境工程国际会议(CFEEE 2024) 会议时间&#xff1a;2024年9月1日-3日 召开地点&#xff1a;新西兰奥克兰 大会官网&#xff1a;https://www.cfeee.org/ 2024年第三届能源与环境工程国际会议(CFEEE 2024) 将于2024年12月12日至1…...

thinkphp6(tp6)创建定时任务

使用 thinkphp6 框架中提供的命令行形式实现定时任务 一、创建一个自定义命令类文件 php think make:command Hello 会生成一个 app\command\Hello.php 命令行指令类&#xff0c;我们修改内容如下&#xff1a; <?php declare (strict_types1);namespace app\command;use …...

【学习笔记】C++ 中 static 关键字的作用

目录 前言static 作用在变量上static 作用在全局变量上static 作用在局部变量上static 作用在成员变量上 static 作用在函数上static 作用在函数上static 作用在成员函数上 前言 在 C/C 中&#xff0c;关键字 static 在不同的应用场景下&#xff0c;有不同的作用&#xff0c;这…...

攻防世界-web-file_include

1. 题目描述 打开界面&#xff0c;如下代码&#xff1a; 代码很简单&#xff0c;从参数中获取到filename然后include这个filename 2. 思路分析 2.1 首先参考常见做法&#xff0c;将参数设置为php://filter/readconvert.base64-encode/resourceflag.php&#xff0c;看是否有…...

C语言的函数指针、指针函数, 函数数组

函数指针 是指向函数的指针&#xff0c;它允许您在程序运行时动态选择要调用的函数。函数指针可以像普通变量一样传递、存储和使用&#xff0c;这使得它们在许多编程场景中非常有用&#xff0c;如回调函数、函数表、插件架构等。 以下是一个简单的例子来说明函数指针的概念&a…...

笔记本开启WiFi

笔记本开启WiFi 为了节省流量&#xff1a;笔记本开启WiFi 条件 支持热点的电脑&#xff1b;我的是华硕飞行堡垒7。 注意事项 笔记本连接公司网络&#xff0c;公司网络通常都在监管下的&#xff0c;手机连接wifi后&#xff0c;刷抖音、购物网站&#xff0c;公司后台会捕获你…...

力扣第37天----第322题、第279题

力扣第37天----第322题、第279题 文章目录 力扣第37天----第322题、第279题一、第322题--零钱兑换二、第279题--组合总和 Ⅳ 一、第322题–零钱兑换 ​ 整体思路&#xff0c;跟前面的几道完全背包差不多&#xff0c;就不具体解释了。有一些细节要注意&#xff0c;见代码注释。…...

【ArcGIS Pro二次开发】(67):处理面要素空洞

这个一个简单的小功能。 有些面要素可能会存在空洞&#xff0c;这个工具的目的就是获取面要素的空洞&#xff0c;或者去除空洞获取要素的边界。 这个功能其实在之前做拓扑功能的时候就已经有了&#xff0c;这次只是单独把它提取出来。因为有时候会单独用到这个功能。 一、要实…...

FPGA-结合协议时序实现UART收发器(一):UART协议、架构规划、框图

FPGA-结合协议时序实现UART收发器&#xff08;一&#xff09;&#xff1a;UART协议、架构规划、框图 记录FPGA的UART学习笔记&#xff0c;以及一些细节处理&#xff0c;主要参考奇哥fpga学习资料。 本次UART主要采用计数器方法实现&#xff0c;实现uart的稳定性发送和接收功能…...

web请求cookie中expires总结

用意 cookie 有失效日期 "expires"&#xff0c;如果还没有过失效期&#xff0c;即使重新启动电脑&#xff0c;cookie 仍然不会丢失 注意&#xff1a;如果没有指定 expires 值&#xff0c;那么在关闭浏览器时&#xff0c;cookie 即失效。 设置 如果cookie存储时间大…...

如何学习Java核心知识

Java作为一门广泛应用于软件开发的编程语言&#xff0c;拥有着强大的生态系统和丰富的资源&#xff0c;是值得投入时间和精力去学习的。以下是一些建议&#xff0c;帮助你系统地学习Java核心知识。 1. 学习Java语言基础&#xff1a; 学习Java语言基础是学习Java的第一步&…...

【AWS】如何用SSH连接aws上的EC2实例(虚拟机)?

目录 0.环境 1.连接结果示例 2.SSH连接思路 3.具体步骤 1&#xff09;安装并运行ssh服务 2&#xff09;启动ssh服务 3&#xff09;在AWS上找到正在运行的EC2实例&#xff0c;并且根据提供的ssh连接语句进行连接 0.环境 windows 11 64位 前提&#xff1a; 有aws账户&…...

数据结构——看完这篇保证你学会队列

数据结构——队列 一、队列的概念二、队列的实现方式三、队列所需要的接口四、接口的详细实现4.1初始化4.2销毁4.3入队4.5出队4.6获取队头元素4.7获取队尾元素4.8获取队列元素个数4.9判空 五、完整代码5.1Queue.h5.2Queue.c5.3test.c 一、队列的概念 队列&#xff1a;只允许在…...

开源免费缺陷管理工具:对比6款

在软件开发环境中&#xff0c;缺陷管理工具是关键的基础设施。例如&#xff0c;在构建一个电商平台时&#xff0c;这些工具能系统地跟踪从发现到解决的各个问题阶段。它们支持多用户协作&#xff0c;实现信息和状态的实时共享。通过数据分析&#xff0c;这些工具还能帮助团队识…...

Weblogic反序列化漏洞

文章目录 1、搭建环境2、漏洞特征3、漏洞利用1)获取用户名密码2)后台上传shell 4、检测工具 1、搭建环境 漏洞环境基于vulhub搭建–进入weak_password的docker环境 sudo docker-compose up -d拉取靶场 2、漏洞特征 404特征Weblogic常用端口&#xff1a;7001 3、漏洞利用…...

element-ui el-table 滚动到底部,进行加载下一页

使用element-ui 自带的InfiniteScroll 无限滚动组件无法使用在table里面&#xff0c;所以项目只能组件写一个 俺的方法是写了一个自定义组件&#xff0c;进行监听滚动条是否拉到最底部进行一个处理。方法如下 直接复制完事了&#xff0c; loadTableMore: { bind(el, binding…...

线性代数的学习和整理19,特征值,特征向量,以及引入的正交化矩阵概念(草稿)

目录 1 什么是特征值和特征向量&#xff1f; 1.1 特征值和特征向量这2个概念先放后 1.2 直观定义 1.3 严格定义 2 如何求特征值和特征向量 2.1 方法1&#xff1a;结合图形看&#xff0c;直观方法求 2.1.1 单位矩阵的特征值和特征向量 2.1.2 旋转矩阵 2.2 根据严格定义…...

WordPress网站生成小程序/深圳网络营销

RickGray 2016/06/02 13:45Author: RickGray (知道创宇404安全实验室)0x00 简介好像很久没发文了&#xff0c;近日心血来潮准备谈谈 “漏洞检测的那些事儿”。现在有一个现象就是一旦有危害较高的漏洞的验证 PoC 或者利用 EXP 被公布出来&#xff0c;就会有一大群饥渴难忍的帽…...

wordpress茶叶模板/关键词搜索神器

走进JVM的世界小强是一个工作3年有余的开发工程师&#xff0c;从他的发量你就可以知道&#xff0c;小强资历还尚浅。程序员惊人发量最近公司没什么事&#xff0c;他也开始无聊起来了。这天下午&#xff0c;同事们在激烈的讨论这业务&#xff0c;但他没有参与&#xff0c;于是他…...

开发软件需要什么软件/seo官网优化详细方法

在 linux 中&#xff0c;如果我们想添加一个用户&#xff0c;那么使用的命令如下&#xff1a; 用户管理命令&#xff1a; useradd 基础的命令 命令名称&#xff1a;useradd 命令的所在路径&#xff1a;/usr/bin/useradd 执行权限&#xff1a;root 语法&#xff1a;useradd 用户…...

wordpress编辑文章图片文字对齐/大亚湾发布

------- android培训、java培训、期待与您交流&#xff01; ---------- Servlet&#xff1a; 当然&#xff0c;在servlet中&#xff0c;一般跳转都发生在doGet, doPost等方法里面。 1) redirect 方式 response.sendRedirect("/a.jsp"); 页面的路径是相对路径。sendRe…...

建设网站一般多少钱/百度投放广告

室内可见光定位装置1.1 设计任务设计并制作可见光室内定位装置&#xff0c;其构成示意图如图 1 所示。参赛者自行搭建不小于 80cm80cm80cm 的立方空间&#xff08;包含顶部、底部和 3 个侧面&#xff09;。顶部平面放置 3 个白光 LED&#xff0c;其位置和角度自行设置&#xff…...

公司做网站 需要准备什么/企业百度推广

炸裂&#xff1a;将一行数据&#xff0c;炸裂为多行&#xff0c; 也就是“列转行” 例如&#xff1a;hive的订单表order_table有一个字段item_list,是一个列表结构的 array<struct<item_id:string,item_sku_id:string,price:double,quantity:bigint,title:string>>…...