您的位置首页>企业动态>

在USB盘上搭建Linux微型桌面系统的方案设计与优势介绍

导读 大家好,我是极客范的本期栏目编辑小友,现在为大家讲解在USB盘上搭建Linux微型桌面系统的方案设计与优势介绍问题。1导言随着USB 3 0标

大家好,我是极客范的本期栏目编辑小友,现在为大家讲解在USB盘上搭建Linux微型桌面系统的方案设计与优势介绍问题。

1导言

随着USB 3.0标准的发布,存储容量从8GB到128GB的USB接口移动存储设备成为主流。由于u盘体积小,便于携带,同时可热插拔,给移动数据存储带来了便利。开源Linux操作系统具有可靠性和安全性高、硬件支持广泛、定制灵活实用等特点。这使得Linux桌面系统逐渐受到人们在办公应用中的青睐。在带有USB接口的移动存储设备上实现一个Linux迷你桌面系统将是一个不错的选择。但是在u盘上安装标准的Linux分发系统会占用将近2G的存储空间,而且移动办公也有很多我们不需要的软件。同时,从数据安全的角度出发,人们希望在不使用原有主机操作系统和数据的情况下,进行便捷的移动办公。因此,本文将从LFS系统入手,在u盘上搭建Linux mini桌面系统,实现操作系统与办公娱乐软件的集成,并使用squashfs文件系统压缩技术对整个系统进行压缩,最终通过grub和initrd实现系统的启动。

2微型桌面系统的组成

本文以LFS Live CD 6.3主机系统为基础,通过LFS技术搭建基本Linux系统后,使用chroot命令转移到基本系统,进而搭建整个桌面系统。

基于u盘的微桌面系统如图1所示,由以下几个部分组成:

引导管理器:Grub 0.97.Grub程序是电脑开机引导到u盘设备后运行的第一个程序。其目的是将Linux内核从u盘加载到内核中。

然后内核执行后续操作。

内核:作为Linux操作系统的核心,负责管理进程调度、内存管理、虚拟文件系统、网络接口和进程间通信,为主板、显卡、网卡、声卡、内存、USB设备等驱动提供支持。由于是移动系统,面对硬件平台多样性的问题,需要将一些常见的基础驱动和USB相关驱动编译到内核中,以模块的形式动态加载squashfs、aufs、声卡、显卡等相关支持,从而减少内核的镜像大小,提高系统的启动时间。

基本Linux系统:包括基本的文件系统结构、最常用的应用程序、基本函数库以及可以正常启动字符界面的相关配置文件。

图形桌面系统:桌面系统采用xfce4.6.2,安装以下应用软件:永中office 2009办公应用软件(集成Word、Excel、PowerPoint);Fcitx中文输入法;MPlayer媒体播放软件;网络配置工具软件;远程桌面连接控制软件;QQ;Vnc实验室自主研发的集播放、浏览于一体的网页浏览器Hfox[2];其他软件:图片查看器、文本编辑器、PDF阅读器、解压软件等。

图1基于USB接口的微桌面Linux系统组成

整个迷你桌面系统安装后占用约1.7GB的磁盘空间,通过运行mksquashfs命令压缩成只读的系统镜像system.squashfs(约495MB)。

3项关键技术

3.1内核编译

采用2.6.27.27的Linux内核版本。为了简化系统,有些模块不会编译到内核中:声卡驱动模块等。系统将通过u盘引导,SCSI设备、USBcore、Usb存储、环回设备支持、内存磁盘支持和Initrd需要编译到内核中。

将Squshfs和AUFS编译成模块,并通过Initrd引导加载它们。

常见的硬盘接口有IDE和SATA,在Linux中通常被标识为不同的驱动器号。为了避免内核挂载U packing系统时驱动器盘符名称不一致,需要将IDE和SATA硬盘中的驱动器盘符统一到/dev/sdX中,在内核编译时需要添加以下选项:

编译后的内核将平等对待这两种类型的硬盘。因此,不同接口的硬盘的盘符名称在Linux中统一为sdX,便于挂载系统。

="text-indent: 2em;">3.2 LFS 构建系统

LFS(Linux From Scratch 的缩写),是从源代码开始搭建的Linux 系统。LFS 有以下几个优点:

①LFS 是非常灵活的,可以根据自身需求定制。

②构建的LFS 系统是一个非常紧凑的系统,可以大大节省磁盘空间。

③LFS 可自定义安装相关的安全补丁,系统有保障。

本文目的是设计一款微型桌面系统,根据其小巧灵活实用的特点,与使用标准的Linux 发行版和使用精简的Linux 系统相比,LFS 更适合。

3.3 SquashFS+LZMA 只读压缩系统

构建一个小型或嵌入式Linux 系统,存储设备(软盘、U 盘等)的空间资源非常有限,因此压缩应尽可能用在各个方面。

SquashFS 是一种在Linux 下使用的只读压缩文件系统,是目前最好的压缩文件系统之一,它的目的是为通用只读文件系统使用。目前,SquashFS 压缩文件系统应用很广,已在Linux Live CD 各发行版、嵌入式系统、以及在服务器及桌面系统中都有着大量的应用。

LZMA(Lempel-Ziv-Markov chain-Algorithm 的缩写),是一个Deflate和LZ77算法改良和优化后的压缩算法,是目前最好的压缩算法之一。

SquashFS 默认的压缩算法是GZIP,本文中采用给SquashFS 打补丁,使其支持LZMA 算法压缩。实验证明,通过LZMA 算法压缩比GZIP 算法压缩率更高,而压缩时间比GZIP 算法稍长。通过对整个系统采用GZIP 和LZMA 算法进行Squashfs 压缩,在压缩时间和存储空间的比较如表1 如示。

表1 两种压缩算法的比较。

目前Linux 内核还不支持LZMA,在编译内核时需要将CONFIG_SQUASHFS*中所有值置为N;再单独将带LZMA 支持的Squshfs 编译成模块,通过动态加载方式运行。

3.4 AUFS 联合文件系统

AUFS( Another UnionFS 的缩写), 是一个与UnionFS 类似的可堆叠联合文件系统,它将多个目录整合成单一的目录,是Linux 文件系统联合挂载的实现。

SquashFS 压缩系统是只读的,从而避免了对磁盘不必要的擦写,但同时也造成了修改数据不能保存的问题。

AUFS 的出现正好解决了上述问题,它管理一个基本文件系统(即本文中的系统Squashfs 镜像,保持原只读状态)和一个读写存储文件系统(必须具有读写权限)。通过AUFS,用户可以虚拟地修改基本文件系统上的文件,但修改后的结果却保存在读写存储文件系统中,从而实现了数据的透明修改。

3.5 Initrd 初始化内存盘

Initrd(boot loader Initialized RAM Disk 的缩写),由boot loader 初始化。本系统使用的boot loader 为GNU GRUB 0.97.如果Grub 已配置Initrd,Linux 内核在启动前,会把存储设备中的Initrd 文件加载到内存,作为一个临时根文件系统;内核启动时通过先执行Initrd 中的init 文件,完成设备驱动模块和squashsf、aufs 文件系统模块的加载,并完成真正的根文件系统的挂载,然后执行系统中的/sbin/init 进程。

与普通IDE、SATA 硬盘相比,USB 接口存储设备从驱动模块加载到设备可用,比较慢,需要几秒钟。

因此内核在挂载USB 存储设备时,会出现:USB 设备没有初始化完成,真正根文件系统挂载失败的问题。为了解决此问题,笔者在Initrd 中修改init 可执行文件,当加载USB 驱动后,系统将休眠5 秒,让USB 设备初始化完成后再挂载USB 存储设备中的根文件系统。本系统的init 文件配置如下:

本系统Initrd 中的最小化根文件系统由BusyBox创建,包含bin、dev、etc、lib、mnt、proc、sbin、sys这些必须的目录和相关文件。由于BusyBox 生成的modprobe 命令不能正常执行,所以需要复制宿主系统中的modprobe 命令并替换Initrd 中的sbin 目录中的同名文件,同时通过ldd 查看modprobe 依赖的库文件,并复制到Initrd 中的lib 目录。

最后在宿主机器上通过命令:

find . | cpio –o –H newc | gzip > /boot/initrd.img-2.6.27.27 制作Initrd 镜像文件。

3.6 Grub 启动引导器

GNU GRUB (GNU GRand Unified Bootloader 的缩写),是GNU 项目中一个多操作系统启动引导程序,也是Linux 系统中最常用引导工具之一。为了让系统从USB 设备启动,必须将GRUB 程序安装在USB 存储设备的主引导记录(MBR)中。

以GRUB 0.9X 的安装步骤如下:

安装grub 程序在U 盘的/boot/grub 目录下,确保其目录存在menu.lst,stage1,stage2 三个文件。

进入grub 命令窗口,运行以下命令安装到U 盘的MBR:

grub>root(hd1,0) #假定Linux 系统所在盘符为第二块硬盘的第一个分区

grub>setup(hd1)

实际操作时根据硬盘分区不同作相应修改。

修改/boot/grub/menu.lst 文件,本文的menu.lst 如下:

3.7 Xfce 桌面环境

Xfce 是一款适用于多种*NIX 系统上运行的轻量级桌面环境,它的设计目的是在节省系统资源的情况下能够快速加载并执行应用程序。与Gnome 和KDE等比较臃肿的桌面环境相比,Xfce 占用的系统资源少,同时它拥有很小的依赖性和很好的模块性。本系统所用的Xfce 4.6.2 主要由实用工具libxfce4util、微件库libxfcegui4、扩展库exo、菜单库libxfce4menu、窗口管理xfwm4、桌面管理xfdesktop、面板xfce4-panel、会话管理xfce4-session、设置管理xfce4-settings、配置管理xfconf、文件管理thunar、实用程序xfce-utils、应用程序查找xfce4-appfinder 等部件构成。

4 具体实现

4.1 系统在USB 盘上的实现

在宿主系统上构建好整个Linux 桌面系统后,按前所述配置好只读文件系统镜像system.squashfs、初始化内存盘Initrd、内核镜像vmlinuz、Grub 中的menu.lst 文件、USB 盘标志文件LABEL,然后按以下步骤将系统移植进USB 盘。

①准备一个8G 的USB 盘,分为两个区:一个分区作为系统区,文件系统为EXT2,并激活为启动分区,作为Linux 系统使用;一个分区为数据区,文件系统为FAT32,平时作为与Windows 系统交互的分区,保存移动办公数据。

②将system.squashfs、Initrd、vmlinuz、LABEL 和Grub 相关文件复制到系统区,并在系统区中新建system_ro( 用于挂载squashfs 只读文件系统) 、system_rw(用于挂载aufs 文件系统时的修改文件存储目录)、system(用于最终文件系统的挂载目录)三个目录。

③运行grub 程序中的root、setup 命令将启动引导信息写入USB 盘的系统区的MBR.

4.2 系统启动过程

基于USB 接口的微型桌面Linux 系统的启动过程如图2 如示。

计算机开机自检, BIOS 引导到USB 接口的磁盘设备,通过启动引导管理器Grub,加载Linux 内核文件vmlinuz,内核将初始化内存盘initrd.img-2.6.27.27加载到内存,形成一个临时根文件系统,通过执行Initrd 中的init 可执行文件,进行sysfs、proc 文件系统的加载,并对硬件进行初始化,相关硬件驱动、squashfs、aufs 模块的加载后,挂载系统只读镜像system.squashfs,并通过联合文件系统aufs 使其可写,然后转到真正的根文件系统执行命令/sbin/init,完成微型桌面Linux 系统的启动。

图2 系统启动过程。

5 实验结果

本文实现了在USB 接口的存储设备上构建微型桌面Linux 系统,在具有USB 接口启动功能的各种主流品牌台式计算机、笔记本和兼容机上都能成功运行,并且在硬件配置比较低的老式486、586 等机器也能流畅地运行,根据机器硬件配置的不同,一般启动时间为20 秒至50 秒,具有很好的实用价值,真正实现了便捷、高效的移动办公需要。本系统成功启动图形桌面系统后的效果如图3 所示。

图3 Linux 微型桌面系统。

6 结论

本文在USB 接口的移动存储设备构建微型操作系统,具有小型便捷、速度快、空间占用率低、安全可靠的特点,研究具有很高的应用价值,人们可以参照构建过程中的关键性技术,在U 盘上制作出更多小型的专用系统:比如系统维护盘、网络防火墙、路由器、小型服务器、媒体播放器等以满足一些特定需求,同时可以将其研究应用到Live CD 上,在光盘上制作出相应的微型桌面系统。并且在使用过程中,整个系统只占了移动磁盘存储空间的小部分,而剩余的大部分空间可以另作他用,真正体现了资源的高效整合使用。

1 引言

随着USB 3.0 标准的发布,存储容量为8GB 至128GB 的USB 接口移动存储设备成为主流。由于USB盘体积小、携带方便、同时具有热插拔功能,给移动数据存储带来了便利。而开源的Linux 操作系统具有的高可靠性和安全性、广泛的硬件支持、灵活实用的可定制性等特点,使得Linux 桌面系统在办公应用方面也逐步受到人们的青睐。如果在USB 接口的移动存储设备上实现一个Linux 微型桌面系统,将是一个不错选择。然而,将标准的Linux 发行版系统安装在USB盘上,将占用近2G 的存储空间,其中有许多软件我们移动办公并不需要。同时,人们从数据安全性角度的考虑,希望在不使用原有宿主机操作系统和数据的前提下进行便捷的移动办公。因此本文将从LFS 系统开始,在USB 盘上搭建Linux 微型桌面系统,实现操作系统与办公娱乐软件的一体化,并采用squashfs 文件系统压缩技术,对整个系统进行压缩,最后通过grub和initrd 实现系统的启动。

2 微型桌面系统的构成

本文是在LFS Live CD 6.3 宿主系统上,通过LFS技术构建基本Linux 系统后,使用chroot 命令转入基本系统,完成后续整个桌面系统的搭建。

基于USB 盘的微型桌面系统构成如图1 所示,由以下几部分组成的:

①启动引导管理器:选用Grub 0.97.Grub 程序是计算机加电启动,引导到USB 盘设备后运行的第一个程序,其目的是将Linux 内核从USB 盘加载到内核中。

然后转由内核执行后续操作。

②内核:作为Linux 操作系统的核心,它负责管理进程调度、内存管理、虚拟文件系统、网络接口、进程间通信,并提供对主板、显卡、网卡、声卡、存储器、USB 设备等驱动的支持。由于是移动系统,面临硬件平台多样性的问题,所以需要将一些常用基本驱动和USB 相关驱动编译进内核,而将squashfs、aufs、声卡、显卡等相关支持以模块的形式动态加载,这样在减少内核镜像大小的同时,提高了系统启动时间。

③基本Linux 系统:包括能够正常启动字符界面的基本文件系统结构、最常用的应用程序、基本函数库和相关的配置文件。

④图形桌面系统:桌面系统采用xfce4.6.2,并安装如下应用软件:永中office 2009 办公应用软件(集Word、Excel、PowerPoint 于一体);fcitx 中文输入法;MPlayer 媒体播放软件;网络配置工具软件;远程桌面连接控件软件;QQ;Vnc;实验室自主研发的播放浏览一体化的网络浏览器Hfox[2];其他软件:图片查看器、文本编辑器、PDF 阅读器、解压缩软件等。

图1 基于USB 接口的微型桌面Linux 系统的组成

整个微型桌面系统安装完成后要占用大约1.7GB磁盘空间,通过运行mksquashfs 命令压缩成只读系统镜像system.squashfs(约495MB)。

3 关键技术

3.1 内核编译

采用版本为2.6.27.27 的Linux 内核。为使系统更精简,部分模块将不会被编译进内核:声卡驱动模块等。系统将由U 盘引导,需要将SCSI 设备、Usbcore、Usb-storage 、Loopback device support 、RAM disksupport 和Initrd 等编译到内核中。

将Squshfs、AUFS 编译成模块,通过Initrd 引导加载。

常见的硬盘接口为IDE 和SATA,在Linux 中通常将这两类硬盘标识为不同的盘符名。为了避免内核挂载U 盘根系统出现盘符名不一致的情况,需要将IDE 和SATA 硬盘中盘符统一成/dev/sdX,在内核编译时需要加如下的选项:

编译出来的内核会将这两类硬盘同等对待。从而使不同接口硬盘的盘符名在Linux 中都统一为sdX,方便本系统的挂载。

3.2 LFS 构建系统

LFS(Linux From Scratch 的缩写),是从源代码开始搭建的Linux 系统。LFS 有以下几个优点:

①LFS 是非常灵活的,可以根据自身需求定制。

②构建的LFS 系统是一个非常紧凑的系统,可以大大节省磁盘空间。

③LFS 可自定义安装相关的安全补丁,系统有保障。

本文目的是设计一款微型桌面系统,根据其小巧灵活实用的特点,与使用标准的Linux 发行版和使用精简的Linux 系统相比,LFS 更适合。

3.3 SquashFS+LZMA 只读压缩系统

构建一个小型或嵌入式Linux 系统,存储设备(软盘、U 盘等)的空间资源非常有限,因此压缩应尽可能用在各个方面。

SquashFS 是一种在Linux 下使用的只读压缩文件系统,是目前最好的压缩文件系统之一,它的目的是为通用只读文件系统使用。目前,SquashFS 压缩文件系统应用很广,已在Linux Live CD 各发行版、嵌入式系统、以及在服务器及桌面系统中都有着大量的应用。

LZMA(Lempel-Ziv-Markov chain-Algorithm 的缩写),是一个Deflate和LZ77算法改良和优化后的压缩算法,是目前最好的压缩算法之一。

SquashFS 默认的压缩算法是GZIP,本文中采用给SquashFS 打补丁,使其支持LZMA 算法压缩。实验证明,通过LZMA 算法压缩比GZIP 算法压缩率更高,而压缩时间比GZIP 算法稍长。通过对整个系统采用GZIP 和LZMA 算法进行Squashfs 压缩,在压缩时间和存储空间的比较如表1 如示。

表1 两种压缩算法的比较。

目前Linux 内核还不支持LZMA,在编译内核时需要将CONFIG_SQUASHFS*中所有值置为N;再单独将带LZMA 支持的Squshfs 编译成模块,通过动态加载方式运行。

3.4 AUFS 联合文件系统

AUFS( Another UnionFS 的缩写), 是一个与UnionFS 类似的可堆叠联合文件系统,它将多个目录整合成单一的目录,是Linux 文件系统联合挂载的实现。

SquashFS 压缩系统是只读的,从而避免了对磁盘不必要的擦写,但同时也造成了修改数据不能保存的问题。

AUFS 的出现正好解决了上述问题,它管理一个基本文件系统(即本文中的系统Squashfs 镜像,保持原只读状态)和一个读写存储文件系统(必须具有读写权限)。通过AUFS,用户可以虚拟地修改基本文件系统上的文件,但修改后的结果却保存在读写存储文件系统中,从而实现了数据的透明修改。

3.5 Initrd 初始化内存盘

Initrd(boot loader Initialized RAM Disk 的缩写),由boot loader 初始化。本系统使用的boot loader 为GNU GRUB 0.97.如果Grub 已配置Initrd,Linux 内核在启动前,会把存储设备中的Initrd 文件加载到内存,作为一个临时根文件系统;内核启动时通过先执行Initrd 中的init 文件,完成设备驱动模块和squashsf、aufs 文件系统模块的加载,并完成真正的根文件系统的挂载,然后执行系统中的/sbin/init 进程。

与普通IDE、SATA 硬盘相比,USB 接口存储设备从驱动模块加载到设备可用,比较慢,需要几秒钟。

因此内核在挂载USB 存储设备时,会出现:USB 设备没有初始化完成,真正根文件系统挂载失败的问题。为了解决此问题,笔者在Initrd 中修改init 可执行文件,当加载USB 驱动后,系统将休眠5 秒,让USB 设备初始化完成后再挂载USB 存储设备中的根文件系统。本系统的init 文件配置如下:

本系统Initrd 中的最小化根文件系统由BusyBox创建,包含bin、dev、etc、lib、mnt、proc、sbin、sys这些必须的目录和相关文件。由于BusyBox 生成的modprobe 命令不能正常执行,所以需要复制宿主系统中的modprobe 命令并替换Initrd 中的sbin 目录中的同名文件,同时通过ldd 查看modprobe 依赖的库文件,并复制到Initrd 中的lib 目录。

最后在宿主机器上通过命令:

find . | cpio –o –H newc | gzip > /boot/initrd.img-2.6.27.27 制作Initrd 镜像文件。

3.6 Grub 启动引导器

GNU GRUB (GNU GRand Unified Bootloader 的缩写),是GNU 项目中一个多操作系统启动引导程序,也是Linux 系统中最常用引导工具之一。为了让系统从USB 设备启动,必须将GRUB 程序安装在USB 存储设备的主引导记录(MBR)中。

以GRUB 0.9X 的安装步骤如下:

安装grub 程序在U 盘的/boot/grub 目录下,确保其目录存在menu.lst,stage1,stage2 三个文件。

进入grub 命令窗口,运行以下命令安装到U 盘的MBR:

grub>root(hd1,0) #假定Linux 系统所在盘符为第二块硬盘的第一个分区

grub>setup(hd1)

实际操作时根据硬盘分区不同作相应修改。

修改/boot/grub/menu.lst 文件,本文的menu.lst 如下:

3.7 Xfce 桌面环境

Xfce 是一款适用于多种*NIX 系统上运行的轻量级桌面环境,它的设计目的是在节省系统资源的情况下能够快速加载并执行应用程序。与Gnome 和KDE等比较臃肿的桌面环境相比,Xfce 占用的系统资源少,同时它拥有很小的依赖性和很好的模块性。本系统所用的Xfce 4.6.2 主要由实用工具libxfce4util、微件库libxfcegui4、扩展库exo、菜单库libxfce4menu、窗口管理xfwm4、桌面管理xfdesktop、面板xfce4-panel、会话管理xfce4-session、设置管理xfce4-settings、配置管理xfconf、文件管理thunar、实用程序xfce-utils、应用程序查找xfce4-appfinder 等部件构成。

4 具体实现

4.1 系统在USB 盘上的实现

在宿主系统上构建好整个Linux 桌面系统后,按前所述配置好只读文件系统镜像system.squashfs、初始化内存盘Initrd、内核镜像vmlinuz、Grub 中的menu.lst 文件、USB 盘标志文件LABEL,然后按以下步骤将系统移植进USB 盘。

①准备一个8G 的USB 盘,分为两个区:一个分区作为系统区,文件系统为EXT2,并激活为启动分区,作为Linux 系统使用;一个分区为数据区,文件系统为FAT32,平时作为与Windows 系统交互的分区,保存移动办公数据。

②将system.squashfs、Initrd、vmlinuz、LABEL 和Grub 相关文件复制到系统区,并在系统区中新建system_ro( 用于挂载squashfs 只读文件系统) 、system_rw(用于挂载aufs 文件系统时的修改文件存储目录)、system(用于最终文件系统的挂载目录)三个目录。

③运行grub 程序中的root、setup 命令将启动引导信息写入USB 盘的系统区的MBR.

4.2 系统启动过程

基于USB 接口的微型桌面Linux 系统的启动过程如图2 如示。

计算机开机自检, BIOS 引导到USB 接口的磁盘设备,通过启动引导管理器Grub,加载Linux 内核文件vmlinuz,内核将初始化内存盘initrd.img-2.6.27.27加载到内存,形成一个临时根文件系统,通过执行Initrd 中的init 可执行文件,进行sysfs、proc 文件系统的加载,并对硬件进行初始化,相关硬件驱动、squashfs、aufs 模块的加载后,挂载系统只读镜像system.squashfs,并通过联合文件系统aufs 使其可写,然后转到真正的根文件系统执行命令/sbin/init,完成微型桌面Linux 系统的启动。

图2 系统启动过程。

5 实验结果

本文实现了在USB 接口的存储设备上构建微型桌面Linux 系统,在具有USB 接口启动功能的各种主流品牌台式计算机、笔记本和兼容机上都能成功运行,并且在硬件配置比较低的老式486、586 等机器也能流畅地运行,根据机器硬件配置的不同,一般启动时间为20 秒至50 秒,具有很好的实用价值,真正实现了便捷、高效的移动办公需要。本系统成功启动图形桌面系统后的效果如图3 所示。

图3 Linux 微型桌面系统。

6 结论

本文在USB 接口的移动存储设备构建微型操作系统,具有小型便捷、速度快、空间占用率低、安全可靠的特点,研究具有很高的应用价值,人们可以参照构建过程中的关键性技术,在U 盘上制作出更多小型的专用系统:比如系统维护盘、网络防火墙、路由器、小型服务器、媒体播放器等以满足一些特定需求,同时可以将其研究应用到Live CD 上,在光盘上制作出相应的微型桌面系统。并且在使用过程中,整个系统只占了移动磁盘存储空间的小部分,而剩余的大部分空间可以另作他用,真正体现了资源的高效整合使用。

.dfma { position: relative; width: 1000px; margin: 0 auto; } .dfma a::after { position: absolute; left: 0; bottom: 0; width: 30px; line-height: 1.4; text-align: center; background-color: rgba(0, 0, 0, .5); color: #fff; font-size: 12px; content:"广告"; } .dfma img { display: block; }
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。