【1++的Linux】之文件(三)

news2025/2/26 3:37:38

👍作者主页:进击的1++
🤩 专栏链接:【1++的Linux】

文章目录

  • 一,磁盘结构
  • 二,磁盘的抽象结构
  • 三,文件系统
  • 四,文件的增删查改
  • 五,软硬链接
  • 六,动静态库
    • 1. **动态库和静态库是什么?**
    • 2. 创建动静态库
  • 七,动静态库的使用

一,磁盘结构

我们前面学习的都是打开的文件,即内存文件。既然有被打开的文件,那么也有没有被打开的文件,其存在哪里呢?—磁盘,即磁盘级文件。
我们的内存是一种掉电易失的存储介质;磁盘则是一种永久性的存储介质—我们的U盘,磁带等也都是永久性的存储介质。并且磁盘是一种外设,而且是我们计算机中的唯一的机械设备,因此其的一个大缺点就是慢!!!
那么磁盘的结构是怎样的呢?

在这里插入图片描述

在这里插入图片描述

传统的磁盘就是如上这种结构,有一个或多个盘片用于存储数据,多采用铝合金材料。中间有一个主轴,所有盘片都围绕着这个主轴转,每个盘面上都会有一个磁头来进行数据的读写。盘面有正反两面,有多少个盘面就有多少个磁头。
磁头和盘面的距离是无线接近,但又不接触的,为的是防止高速旋转时,划伤盘面,造成数据损失。高速旋转的盘体产生明显的陀螺效应,所以,在硬盘工作时不宜搬动,否则,将增加轴承的工作负荷。为了高速存储和读取信息,硬盘驱动器的磁头质量小,惯性也小,所以,硬盘驱动器的寻道速度明显快于软驱和光驱。磁头停留在启停区,当需要从硬盘读写数据时,磁盘开始旋转。旋转速度达到额定的高速时,磁头就会因盘片旋转产生的气流而抬起,这时磁头才向盘片存放数据的区域移动。该区是没有数据的,适合磁头的软着陆。
磁盘在格式化时被划分成许多同心圆,这些同心圆轨迹叫做磁道(Track)。磁道从外向内从0开始顺序编号。硬盘的每一个盘面有300~1 024个磁道,新式大容量硬盘每面的磁道数更多。信息以脉冲串的形式记录在这些轨迹中,这些同心圆不是连续记录数据,而是被划分成一段段的圆弧,这些圆弧的角速度一样。由于径向长度不一样,所以,线速度也不一样,外圈的线速度较内圈的线速度大,即同样的转速下,外圈在同样时间段里,划过的圆弧长度要比内圈划过的圆弧长度大。每段圆弧叫做一个扇区,扇区从“1”开始编号,每个扇区中的数据作为一个单元同时读出或写入。扇区是磁盘进行读写的最小单位,其大小为512字节 。

二,磁盘的抽象结构

在物理上是如何将数据写入磁盘中的呢?

通过CHS寻址去找到指定扇区,然后进行写入。

那么什么是CHS寻址呢?
CHS寻址模式将硬盘划分为磁头(Heads)、柱面(Cylinder)、扇区(Sector)。先是通过磁头找到在哪一个柱面上,然后找到其在哪一个磁道上,最后找在哪一个扇区上。直到了CHS值我们就能找到任意一个扇区。那么OS也可以通过CHS来管理磁盘吗?答案是不可以!OS是软件,磁盘是硬件,要是通过CHS来管理磁盘,万一磁盘的物理结构变了,那不就OS也得改变。显然是不行的。
因此就有了磁盘的抽象结构

在这里插入图片描述

如上图我们可以想到磁带的读取方法,我们将其展开,便可以得到一个线性的结构,那么我们能不能将磁盘也展开呢?–可以的!我们可以像拆线团一样,按磁道一层一层将磁盘展开,这是一段段的扇区就连到了一块形成了线性结构。然而,扇区又太小,每次读取这么小的单位,效率又太低,因此又将几个扇区合并到一块,形成4KB的逻辑块,OS就可以通过数组来对磁盘进行管理了。
并且要是OS和磁盘使用一样的基本单位,要是磁盘的基本单位变了,那OS是不是也得改?
所以为了软硬之间的解耦,OS每次IO的大小为4KB。

此时我们就初步完成了从物理逻辑到线性逻辑的抽象,由于数组天然的就有下标,那么我们只要知道了数组下表,不就能够找到对应的扇区了吗?通常OS是以4KB的逻辑块来进行IO的,一个逻辑块有八个扇区。计算机的常规访问方式:起始地址+偏移量。因此我们在读取时是第一个扇区的地址+4KB。这是不是和数组一摸一样,因此块的地址就是数组的下标。

因此OS通过数组下标就可以进行LBA寻址,从而找到逻辑块的地址。
但是磁盘只认识CHS地址,因此就又有了LBA----CHS之间的相互转化。

最后对磁盘的管理就变成了对数组的管理,这符合我们前面文章所提到了OS的管理方案:先描述,后组织。

三,文件系统

我们常见的磁盘基本都是成百上千GB大小的,直接管理难度太大。那么要怎么管理呢?分而治之!!!。将磁盘分区,这样我们可以将不同的文件分开,而且还可以提高寻址的速度。
一个区又可以分成若干个组。
如下图:
在这里插入图片描述

在 Linux 系统中,最长见的是 ext2 系列的文件系统。我们上述的讲解都是以ext2为例的

原则上,Block 的大小与数量在格式化后就不能够发生改变了,每个 Block
内最多只会存放一个文件的数据(即不会出现两个文件的数据被放入同一个 Block 的情况),如果文件大小超过了一个 Block 的 size,则会占用多个 Block 来存放文件,如果文件小于一个 Block 的 size,则这个 Block 剩余的空间就浪费掉了。

sudo dumpe2fs /dev/sda1 | grep "Block size://查看逻辑块的大小

在这里插入图片描述

下面是每个分区的结构:
Boot Block:
每个磁盘分区的开头 1024 字节大小都预留为分区的启动扇区,存放引导程序和数据,所以又叫引导块。引导块在第一个 Block,即 Block 0 中存放,但是未必占满这个 Block,原因是 Block 的大小可能大于 1024 字节。
这里是存放开机管理程序的地方,这是个非常重要的设计。因为这样使得我们能够把不同的开机管理程序安装到每个文件系统的最前端,而不用覆盖整颗磁盘唯一的 MBR,这样就能支持多系统启动了。

MBR 共占用了一个扇区,也就是 512 Byte。其中 446 Byte 安装了启动引导程序,其后 64 Byte 描述分区表,最后的 2Byte 是结束标记。我们已经知道,每块硬盘只能划分 4 个主分区,原因就是在 MBR 中描述分区表的空间只有 64Byte。其中每个分区必须占用 16 Byte,那么 64 Byte 就只能划分 4 个主分区。每个分区的 16 字节的规划 .
还有一个问题,BIOS 只能找到 MBR 中的启动引导程序,而找不到在分区的引导扇区中的启动引导程序。那么,要想完成多系统启动,我们的方法是増加启动引导程序的功能,让安装到 MBR 中的启动引导程序(GRUB)可以调用在分区的引导扇区中的其他启动引导程序

每个分区又可以分成多个组。下面是每个组的结构:

super block:
其里面记录了:
block 与 inode 的总量
未使用与已使用的 inode/block 数量
block 与 inode 的大小(block 为 1,2,4K,inode 为 128 Bytes 或 256 Bytes)
filesystem 的挂载时间、最近一次写入数据的时间、最近一次检验磁盘(fsck)的时间等文件系统的相关信息
一个 valid bit 数值,若此文件系统已被挂载,则 valid bit 为 0,若未被挂载,则 valid bit 为 1。

Superblock 的大小为 1024 Bytes,它非常重要,因为分区上重要的信息都在上面。如果Superblock挂掉了,分区上的数据就很难恢复了。可以使用 dumpe2fs 命令查看 分区的Superblock 信息。

**Group Description:**该块组的描述符,描述该组内的属性信息,block的开始与结束位置等。

Block bitmap: 统计该组内的block哪些被使用了,哪些没有被使用。
Inode bitmap: 统计该组内的inode哪些被使用了,哪些没有被使用。
Inode table: 放着一个个inode,inode是一个大小为128kb的空间,里面记录了对应文件的属性以及数据实际放在哪些block中。一个inode对应一个inode编号,一般一个文件对应一个inode编号。
Data block: 这是用来放文件内容的地方。

为什么要有上述这样的分区:目的是为了让一个文件的信息可被追溯,方便管理。

快组分割,并写入相关的管理数据,从而将整个分区都写入文件系统,这其实就是我们的格式化。

若是文件特别大怎么办?
data block不止能存文件的内容,还能够存储其他块的块号。最终就可以得到好多的块。

在Linux中,系统只认识inode编号,文件名是给上层用户用的。

目录的本质也是文件,有其自己的inode编号,那目录的内容是什么呢?存的是该目录下的文件名以及其inode编号,在目录内文件名和inode互为key值。

为什么有时候我们会创建文件失败呢?因为data block的数量是固定的,inode的数量也是固定的。那么就会存在谁先用完,另一个还没有用完的情况。

四,文件的增删查改

查:

我们以log.txt文件为例。
首先OS会根据该文件的目录及其文件名找到对应的inode编号。结合目录的inode编号找到特定分区的特定组,在Inode table中找到该文件的inode进而找到文件所用的数据块。

删:
根据inode找到对应的区组,找到对应的inode,获得其所占用的数据块的编号,再找到blockbitmap,将其对应的位置为0即可,再找到inodebitmap,将其inode对应的位置为0 ,并没有删除其实际的数据内容,那么文件删除后能恢复出来吗?
答案是:可以的!!!只有能够找到其原来的inode,并且原来的数据没有被覆盖就是可以的 。

既然文件的删除只是将其对应的位图置0,

增:
创建文件后系统会给该文件分配一个inode编号,并在inodetable中记录其属性,在inodebitmap与blockbitmap中将对应的位置为1 。

五,软硬链接

在这里插入图片描述

如上述图,我们为test2创建了硬链接test2-hard;创建了软连接test2-soft。
我们通过对比软硬链接发现其权限后面的数字也发生了变化。这个数字代表的就是硬链接数。

我们可以通过ls -i来查看inode编号。
在这里插入图片描述
我们发现硬链接的inode编号是一样的。根据我们上面所描述,既然inode编号一样,那么其所对应的文件内容也是一样的,并没有创建新的我文件,也就是说这是同一个文件,只不过有两个名字对应同一个inode编号。
所以创建硬链接,实际做的是:在指定目录下建立文件名和指定inode的对应关系而已。

软连接的inode的编号不同,硬链接编号为1 。**因此其是一个独立的文件,**里面放的是指向文件对应的路径。这和我们window下的快捷方式是一样的 。
在这里插入图片描述
我们新建一个空文件夹,其本质也是一个文件。我们发现上述file文件夹的硬链接数竟然是2。
我们进入文件夹内,查看其所有内容(包括隐藏的文件)
在这里插入图片描述
我们发现其有两文件:. 和 … 。并且 . 的inode的编号和file文件夹的inode编号一样,因此 . 就是file的硬链接。也就是我们的当前目录。我们在运行程序时所写的: ./xxx.exe,就是在当前目录下运行程序。那么还有一个 … 是什么呢?我们退回上级目录。
在这里插入图片描述
与上级目录的inode 编号一样,所偶一… 代表的是上级目录的硬链接,因此其硬链接数位3 :文件夹,. ,… 。这样它就有三个硬链接了。我们常用的cd … 返回上级目录就是利用的其硬链接。

在这里插入图片描述
我们删除test2-hard,我们发现test2并没有一起消失,二是硬链接数变为了1,因此一个文件的删除,实际上是利用了引用计数,只有当计数为0时才会真正删除这个文件。

六,动静态库

1. 动态库和静态库是什么?

  1. 静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库
  2. 动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。
  3. 一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码。
  4. 在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个过程称为动态链接(dynamic linking)动态库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。操作系统采用虚拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用,节省了内存和磁盘空间。

2. 创建动静态库

创建一个静态库:
在这里插入图片描述
我们写一个加法的函数。包括声明和定义。再写一个调用其函数的主函数。
我们将其全部生成.o文件,再进行链接生成可执行文件test。
在这里插入图片描述
在这里插入图片描述
我们./test 运行,是可以打印出结果的。
在这里插入图片描述
以上过程就是将一个外部的函数链接到我们的可执行程序中的过程。那么这就叫做静态库吗?
显然它还不能叫做库。

在这里插入图片描述

在这里插入图片描述
我们将myadd.o进行打包形成libmy.a,将libmy.a放进libs文件夹中,其.h文件放进include中,最终形成lib-staticd就是我们所创建的静态库 。(其.h文件是供外界使用的,告诉使用者使用方法)
我们在使用语言所提供的静态库时直接包头文件就可以使用,而我们所写的库叫做第三方库,需要给出其搜索路径系统才可以找到。gcc默认搜索头文件的路径为:/usr/include. 默认的搜索库文件的路径为:/lib64 or /usr/lib64 。
我们将库拷到默认路径下就叫做库的安装。

创建动态库
创建过程与静态库类似
在这里插入图片描述
加fPIC生成位置无关代码 库名规则 libxxx.so
shared: 表示生成共享库格式。
关于fPIC有下面的相关文章可供参考动态库之fPIC

在这里插入图片描述

七,动静态库的使用

我们先来说静态库的使用:
我们再创建一个新的test.文件,包myadd.h头文件后进行编译,
在这里插入图片描述
你会发现找不到这个头文件。原因是:头文件的搜索有两种路径。一种是在当前路径下查找头文件。一种是系统头文件路径下查找。所以,我们可以把头文件和库文件拷贝到系统路径下。
在这里插入图片描述

在这里插入图片描述
但我们发现
在这里插入图片描述
仍会报错,这是为什么呢?
虽然我们将自己所写的库拷贝到了默认路径,但是编译器是不认识我们的库的,需要我们指定链接的第三方库的名称(后加-l)

在这里插入图片描述
但是我们不建议这样做,因为这样会污染我们的系统的库文件和头文件。
我们可以指定路径;
在这里插入图片描述
-I(大写)的意思是:头文件查找路径
-L的意思是:库文件搜索路径
-l(小写)的意思是:在-L指定的路径下你要链接的是哪一个库.

动态库的使用:
第一种方法啊还是将路径拷贝到系统的默认路径下。
我们来看第二种方法:指定路径。
在这里插入图片描述
但是我们发现其会报错。
在这里插入图片描述

这是为什么呢?因为我们的动态链接是在程序运行起来后才会进行链接加载的。而-I和-L是作用与gcc的,在程序运行前起作用,所以我们运行起来的程序找不到库文件就会报错了。

解决方法:
第一种方法就是导入环境变量:
当程序运行时,会在环境变量中(LD_LIBRARY_PATH)查找自己需要的动态库路径。
在这里插入图片描述

在这里插入图片描述
ldd命令可以查看一个可执行程序依赖的共享库.
在这里插入图片描述
此方法,当我们重启xshell后,我们导入环境变量就会恢复默认值。

因此还有以下这种方法:
Linux是通过 /etc/ld.so.cache 文件搜寻要链接的动态库的。而 /etc/ld.so.cache 是 ldconfig 程序读取 /etc/ld.so.conf 文件生成的。(注意, /etc/ld.so.conf 中并不必包含 /lib 和 /usr/lib,ldconfig程序会自动搜索这两个目录)。
如果我们把 libmax.so 所在的路径添加到 /etc/ld.so.conf 中,再以root权限运行 ldconfig 程序,更新 /etc/ld.so.cache ,test3运行时,就可以找到 libmax.so。

在这里插入图片描述
配置文件还没有生效。
在这里插入图片描述
运行 ldconfig 程序
在这里插入图片描述
还可以通过软连接的方式进行:

在这里插入图片描述

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

动静态库的区别:
静态库:在链接阶段库将会与目标汇编后的目标文件.o一起打包生成可执行文件。成为可执行文件的一部分,后续此库就可以消失了。也就是说在编译的最后一步(链接阶段),如果程序需要使用静态库,在这一步都会一起打包到可执行文件中。

优点:
1、 使可执行文件依赖项少,已经被打包到可执行文件中了
2、 编译阶段完成链接,执行期间代码装载速度快

缺点:
1、使可执行文件变大
2、若作为其他库的依赖库,将会造成多余的副本,因为必须与目标文件打包
3、升级不方便,升级必须重新编译

动态库:而动态库在编译阶段都不会有什么动作,只有在程序运行时才被加载(被加载到堆栈之间的共享区),也就是动态库的链接是发生在程序运行时期的,它和可执行文件是分开的,只是可执行文件在运行的某个时期调用了它。

优点:
1、动态库可以实现进程之间资源共享,有一份就行。
2、升级程序简单,不需要重新编译。

缺点:
1、运行期间在加载,将会减慢代码执行速度。
2、增加程序的依赖项,必须跟着可执行文件一起

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

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

相关文章

Socket实现服务器搭建

一、前言: Socket上篇文章已经介绍过了 他是实现网络编程的基础 。 在服务器模型中通常都是多个客户端一个服务器端,那么服务器是如何处理多个客户端的请求? 1.顺序处理 依次处理--效率低下 2.并发处理 2.1 多线程并发(线程池…

《向量数据库》——Zilliz X Dify.AI ,快速打造知识库 AI 应用

Zilliz 大模型生态矩阵再迎新伙伴!近日,Zilliz 和 Dify.AI 达成合作,Zilliz 旗下的产品 Zilliz Cloud、Milvus 与开源 LLMOps 平台 Dify 社区版进行了深度集成。 01. Zilliz Cloud v.s. Dify Dify 作为开源的 LLMs App 技术栈,在此前已支持丰富多元的大型语言模型的接入,…

解密Java中神奇的Synchronized关键字

文章目录 🎉 定义🎉 JDK6以前🎉 偏向锁和轻量级锁📝 偏向锁📝 轻量级锁📝 自旋锁📝 重量级锁🔥 1. 加锁🔥 2. 等待🔥 3. 撤销 🎉 锁优化&#x1f…

将字符串中的数据按指定分隔符分割依次存入一维数组中 numpy.fromstring()

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 将字符串中的数据 按指定分隔符分割 依次存入一维数组中 numpy.fromstring() [太阳]选择题 请问以下代码中执行语句输出结果依次是? import numpy as np str1 "1.0 2.0 3.…

力扣第55题 跳跃游戏 c++ 贪心 + 覆盖 加暴力超时参考

题目 55. 跳跃游戏 中等 相关标签 贪心 数组 动态规划 给你一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个下标,如果可以,返回 true &…

【算法训练-动态规划 四】【子序列类型问题】连续子数组的最大和

废话不多说,喊一句号子鼓励自己:程序员永不失业,程序员走向架构!本篇Blog的主题是【动态规划】,使用【数组】这个基本的数据结构来实现,这个高频题的站点是:CodeTop,筛选条件为&…

架构设计系列5:如何设计高可用架构

#1024程序员节|参与投稿,赢限定勋章和专属大奖# 当今的数字时代,高可用架构已经成为了现代应用和服务的基石。无论是企业级应用、云计算平台还是互联网服务,高可用性都是确保系统在面临各种挑战时保持稳定运行的关键要素。 本文…

计算机算法分析与设计(19)---回溯法(装载问题)

文章目录 1. 题目描述2. 算法思路3. 代码编写 1. 题目描述 2. 算法思路 1. 思路: 容易证明,如果一个给定装载问题有解,则采用下面的策略可得到最优装载方案。 (1) 首先将第一艘轮船尽可能装满。(2) 将剩余的集装箱装上第二艘轮船。 2. 将第一…

基于springboot实现基于Java的超市进销存系统项目【项目源码+论文说明】

基于springboot实现基于Java的超市进销存系统演示 摘要 随着信息化时代的到来,管理系统都趋向于智能化、系统化,超市进销存系统也不例外,但目前国内仍都使用人工管理,市场规模越来越大,同时信息量也越来越庞大&#x…

Xilinx的FIR滤波器IP的设计与仿真

平台:Vivado2021.1 芯片:xcku115-flva1517-2-i (active) 语言:VerilogHDL 参考文件:pg149.下载地址 FIR Compiler LogiCORE IP Product Guide • FIR Compiler (PG149) • 阅读器 • AMD 自适应计算文档门户 (xilinx.com) FI…

【漏洞复现】panalog日志审计系统任意用户创建漏洞和后台命令执行

漏洞描述 panalog为北京派网软件有限公司,一款流量分析,日志分析管理的一款软件。存在任意用户创建漏洞和后台命令执行漏洞,可先通过任意用户创建,然后进行后台命令执行,获取服务器权限。 免责声明 技术文章仅供参考,任何个人和组织使用网络应当遵守宪法法律,遵守公…

怎么保护公司文件安全

怎么保护公司文件安全 无纸化办公时代,无论是企业还是个人在生活的方方面面都依赖于对电子化软件以及设备的使用。尤其是对于企业而言,在日常办公中产生的相关电子文件都是以电子文档的形式存储在电脑上。 下载试用安企神数据防泄密软件 若企业未实施…

力扣刷题 day53:10-23

1.二进制表示中质数个计算置位 给你两个整数 left 和 right ,在闭区间 [left, right] 范围内,统计并返回 计算置位位数为质数 的整数个数。 计算置位位数 就是二进制表示中 1 的个数。 例如, 21 的二进制表示 10101 有 3 个计算置位。 方…

Uncaught TypeError: Cannot use ‘in‘ operator to search for ‘path‘ in undefined

Uncaught TypeError: Cannot use ‘in’ operator to search for ‘path’ in undefined 报错如下: Uncaught TypeError: Cannot use in operator to search for path in undefinedat resolve (vue-router.esm-bundler.js:2882:13)at pushWithRedirect (vue-router…

Java将djvu文件转成pdf

需求来源 迫于有部分资源是djvu格式的文件,需要预览这部分文件,web端无法直接预览djvu,所以需要将djvu转成pdf。 转换方法 简单来说就是先把djvu文件转换成tiff文件,再将tiff文件转换成pdf文件。 Ubuntu服务器 如果服务器是U…

【软考-中级】系统集成项目管理工程师-项目收尾管理历年案例

持续更新。。。。。。。。。。。。。。。 目录 2017 下 试题三(17分)背诵整理1. 项目总结会议一般讨论的内容2. 系统文档验收所涉及的文档都有哪些 系列文章 2017 下 试题三(17分) 阅读下列说明,回答问题 1至问题 4,将解答填入答题纸的对应栏内     …

几种基本的高斯分布数学运算,加法、乘法、缩放和卷积及运用场景

文章目录 高斯分布进行乘法运算几种基本的数学运算上述这些运算可以运用与什么场景?高斯分布进行乘法运算 当两个高斯分布进行乘法运算时,这通常是在估计或滤波的上下文中,如在卡尔曼滤波中的更新步骤。为了理解背后的数学原理,我们首先定义两个高斯分布: 当我们将这两个…

107. 面试官:JS如何实现继承?

107期 1. JS如何实现继承? 2. meta标签中的viewport有什么用? 3. 说手webpack的构建流程? 上面问题的答案会在第二天的公众号(程序员每日三问)推文中公布 也可以小程序刷题,已收录500面试题及答案 106期问题及答案 1. webpack如…

华为昇腾NPU卡 ChatGLM2模型使用

参考:https://gitee.com/mindspore/mindformers/blob/dev/docs/model_cards/glm2.md#chatglm2-6b 1、安装环境: 昇腾NPU卡对应英伟达GPU卡,CANN对应CUDA底层; mindspore对应pytorch;mindformers对应transformers 本…

第1章 Java、IDEA环境部署与配置

JavaEE简介与IDE环境部署 课程目录 JavaEE简介JDK环境部署IntelliJ IDEA环境部署 JavaEE简介 1. JavaEE是什么? Java EE(Java Platform,Enterprise Edition)是sun公司(2009年4月20日甲骨文将其收购)推…