在linux系统中,哪些常用的服务需要构建?

在linux系统中,哪些常用的服务需要构建?,第1张

31 Telnet

协议是TCP/IP协议族中的一员,是Internet远程登陆服务的标准协议和主要方式。它为用户提供了在本地计算机上完成远程主机工作的能力。在终端使用者的电脑上使用telnet程序,用它连接到服务器。终端使用者可以在telnet程序中输入命令,这些命令会在服务器上运行,就像直接在服务器的控制台上输入一样。可以在本地就能控制服务器。要开始一个telnet会话,必须输入用户名和密码来登录服务器。Telnet是常用的远程控制Web服务器的方法。

在Linux的命令行窗口输入“telnet 1921681230”,如图出现登录界面,根据提示输入用户名和密码即可。

 

32 FTP

服务器(File Transfer Protocol Server)是在互联网上提供文件存储和访问服务的计算机,它们依照FTP协议提供服务。 FTP是File Transfer Protocol(文件传输协议)。顾名思义,就是专门用来传输文件的协议。简单地说,支持FTP协议的服务器就是FTP服务器。   

无论在Linux系统还是windows系统中,一般安装后都自带一个命令行的ftp命令程序,使用ftp可以登录远程的主机,并传递文件,这需要主机提供ftp服务和相应的权限;我们可以从PC机的命令行窗口登录开发板,并向开发板传递文件。

在Linux的命令行窗口输入命令ftp 1921681230即对方的IP地址,即可连接上指定地址的服务器,根据提示输入用户名和密码即可登录。

 

33 ssh 

为 Secure Shell 的缩写,由 IETF 的网络小组(Network Working Group)所制定;SSH 为建立在应用层基础上的安全协议。SSH 是目前较可靠,专为远程登录会话和其他网络服务提供安全性的协议。利用 SSH 协议可以有效防止远程管理过程中的信息泄露问题。SSH最初是UNIX系统上的一个程序,后来又迅速扩展到其他操作平台。SSH在正确使用时可弥补网络中的漏洞。SSH客户端适用于多种平台。几乎所有UNIX平台—包括HP-UX、Linux、AIX、Solaris、Digital UNIX、Irix,以及其他平台,都可运行SSH。

 

可以在PC上通过网络进入开发板上的字符终端进行操作,方法如下: 

1) 在开发板上连接以太网线开机(或者连接USB Wifi),然后在串口终端上用ifconfig 命令查看一下开发板的IP地址,如果没有连接串口终端,也可以在LCD上进入网络设置应用,设置一个IP地址,例如1921681230

2) 现在回到PC ,在PC Linux命令行下,假设开发板的IP地址是1921681230,则输入命令ssh root@1921681230,然后输入密码fa即可进入开发板的字符终端

 

34 NFS服务器

掌握NFS服务器的安装、配置和使用掌握NFS客户端的配置掌握挂载和卸载共享目录了解Windows文件共享的基本概念和Samba服务器的功能掌握Samba服务器的配置管理掌握Samba客户程序的使用了解TFTP掌握TFTP服务器的配置管理掌握TFTP客户端程序的使用

 

35 TFTP服务器

Ubuntu中TFTP服务器配置:apt-get install tftp-hpa tptpd-hpa下载TFTP服务器,sudo vim /etc/default/tftpd-hpa

内容如下:

TFTP_USERNAME=“tftp”

TFTP_DIRECTORY=”/home/linux/tftpboot”

TFTP_ADDRESS=”0000:69”

TFTP_OPTIOS=”--secure”

 

sudo service tftpd-hpa stop

sudo service tftpd-hpa start

sudo service tftpd-hpa status

sudo service tftpd-hpa restart

 

然后可以在别的主机使用命令tftp <服务器ip>

使用命令:get <filename> 上传本地文件到TFTP服务器,put<filename>下载TFTP服务器的文件到本地

 

NFS是SUN开发的,用于Unix机器之间的资源共享。目前被广泛应用于Linux系统之间的资源共享。

 

Samba服务器

主要用于在Windows和Unix之间共享资源。资源包括文件、打印机等等。目前被广泛应用于Windows与Linux之间实现资料共享。

 

配置文件smbconf。/etc/samba/smbconf

输入"sudo service smbd restart"重启samba服务-->回车-->服务重启成功访问共享名为myshare的共享目录

在"运行"窗口中输入"\\19216814"-->回车-->双击打开myshare-->回车-->输入用户名和密码-->回车-->访问成功。 

Linux网络安装全过程(安装fedora)

先来大概说一下网络安装linux的基本原理。我们是通过PXE(Pre-boot Execution Environment)(其实是intel设计的一个协议)来进行安装的,它可以使计算机通过网络启动。PXE协议分为server和client端,client就是我们即将要装linux的裸机。 linux下网络安装需具备3个条件:

1dhcp服务器:用于客户端引导时分配IP地址

2ftp、nfs、httpd服务器:用于保存操作系统的rpm包 3tftp服务器:用于客户端的tftp引导。 我的方案是DHCP+NFS+TFTP 方案介绍:

这种方案需要首先设置一个启动服务器和一个安装服务器,可以配置在同一台机器上,然后通过网络启动存放在启动服务器上的安装程序。安装程序会自动访问存放在安装服务器上的安装配置文件和安装介质来完成安装。 软硬件需求: · 一台机器作为启动和安装服务器(虚拟机A) · 待安装的机器,它的网卡必须带有PXE支持(虚拟机B) · 一个完好的局域网,机器已经连入同一网。 · 系统镜像文件

配置步骤:

一、DHCP服务器

1、 安装DHCP

[root@localhost ~]# rpm -qa|grep dhcp ;查看是否安装了 dhcp libdhcp6client-1022-1fc10i386 libdhcp-1998-1fc10i386

dhcp-400-37fc10i386 ;若没有此包,则需用yum install dhcp来安装 libdhcp4client-400-30fc10i386 dhcpv6-client-1022-1fc10i386 2、 配置DHCP

DHCP服务的配置文件是/etc/dhcpdconf,通过修改配置文件进行配置,分两步:一是加入黑体部分,二是修改配置地址。

注:初始安装时/etc/dhcpdconf配置文件为空,此时可以新建一个直接进行编辑。有个DHCP的配置例子为/usr/share/doc/dhcp-400/dhcpdconfsample。

[root@localhost /]# cd /etc

[root@localhost etc]# vim dhcpdconf # DHCP Server Configuration file

# see /usr/share/doc/dhcp/dhcpdconfsample ddns-update-style interim; ignore client-updates; allow booting; allow bootp;

必须与本机是同一网段

subnet 1921681860 netmask 2552552550 {

option routers

192168186135; 本机地址

#路由器地址

option subnet-mask

2552552550;

#子网掩码

option domain-name-servers

192168186135;

#DNS地址

option time-offset

-18000; # Eastern Standard Time

range dynamic-bootp 1921681862 192168186100;

filename "/linux-install/pxelinux0"; #

filename 后面是tftp目录下的文件,用来指定tftp根目录的启动文件。也可以直接写成

/pxelinux0,具体由自己设定

default-lease-time 21600;

#缺省租约时间

max-lease-time 43200;

#最大租约时间

}

[root@localhost ~]# ifconfig eth0 192 168 186135/24

配置地址

[root@localhost etc]# ifconfig ;查本机IP地址。

eth0

Link encap:Ethernet

HWaddr 00:0C:29:26:AC:57

inet addr:192168186135

Bcast:192168186255

Mask:2552552550

注意若要指定给某一特定主机分配地址,需再加入些东西,以下是一个例子

host MyP5 {

filename "pxelinux0";

server-name "bootserver";

hardware ethernet ae:32:20:00:b0:02;

fixed-address 19216818790;

为客户机(需要安装系统的机器)的 MAC 地址和所分配的IP地址。}

3、开启服务(开启成功则表示配置成功了)

[root@localhost etc]# service dhcpd start

(或者重启restart)

启动dhcpd:[确定]

使用

/etc/initd/dhcpd start

也可以(在/etc/initd下即可找到相应的服务service)

二、

NFS服务器

1、安装

NFS

[root@localhost /]# rpm -qa |grep nfs

nfs-utils-lib-114-1fc10i386

nfs-utils-114-1fc10i386

system-config-nfs-1341-1fc10noarch

查询是否已安装,否则使用

yum install nfs

进行安装。

2

、配置NFS

[root@localhost /]# mkdir /linuxos

(建立各个版本ISO文件的存放目录,并且将ISO文件拷贝到此目录下,NFS支持iso格式安装。)

[root@localhost /]# mkdir tftpboot

[root@localhost /]# cd tftpboot/

[root@localhost tftpboot]# mkdir linux-install

[root@localhost /]# vim /etc/exports ;配置文件

/mnt (ro,sync) ;(mnt为NFS的目录,用来存放操作系统。此处选/mnt是因为

其是挂载光盘的挂载点)

/tftpboot/linux-install (ro,sync) 3、启动NFS

[root@localhost tftpboot]# exportfs –a ;使用此命令使配置生效 [root@localhost /]# service nfs start(或restart)

启动 NFS 服务: [确定] 关掉 NFS 配额: [确定] 启动 NFS 守护进程: [确定] 启动 NFS mountd: [确定]

三、TFTP服务器

1、安装TFTP

[root@localhost /]# rpm -qa |grep tftp

tftp-049-1fc10i386 ;这个只是tftp客户端软件

tftp-server-049-1fc10i386 ;这个才是tftp服务器软件(必不可少) 若没有则需使用yum下载。 [root@localhost /]# yum install tftp

[root@localhost /]# yum install tftp-server 2、配置TFTP

[root@localhost initd]# vim /etc/xinetdd/tftp ;配置文件 service tftp {

disable = no

socket_type = dgram protocol = udp wait = yes user = root

server = /usr/sbin/intftpd

server_args = -s /tftpboot ;将 /tftpboot 定义为 tftp 服务的默认目录,您可以自行修改。 per_source = 11 cps = 100 2 flags = IPv4 }

3、保存之后重启 /etc/initd/xinetd 服务,即可开启 tftp 服务。(注意此服务service不识别)

[root@localhost /]# /etc/initd/xinetd restart

停止 xinetd: [确定] 启动 xinetd:

[确定] 4、 测试tftp (1)下载文件

PXE安装需要用到IP,UDP,DHCP,TFTP,最主要就是要求你所处的网络内有搭建好的用于PXE网络引导的DHCP服务器和TFTP服务器,你得确定你的设备所处的网络满足这些环境需求。

你开机时按F12能看到使用PXE的选项,选择这个选项,然后会有一系列自动操作,见图

在学习系统移植的相关知识,在学习和调试过程中,发现了很多问题,也解决了很多问题,但总是对于我们的开发结果有一种莫名其妙的感觉,纠其原因,主要对于我们的开发环境没有一个深刻的认识,有时候几个简单的命令就可以完成非常复杂的功能,可是我们有没有想过,为什么会有这样的效果?

如果没有去追问,只是机械地完成,并且看到实验效果,这样做其实并没有真正的掌握系统移植的本质。

在做每一个步骤的时候, 首先问问自己,为什么要这样做,然后再问问自己正在做什么? 搞明白这几个问题,我觉得就差不多了,以后不管更换什么平台,什么芯片,什么开发环境,你都不会迷糊,很快就会上手。对于嵌入式的学习方法,我个人方法就是:从宏观上把握(解决为什么的问题),微观上研究(解决正在做什么的问题),下面以自己学习的arm-cortex_a8开发板为目标,介绍下自己的学习方法和经验。

嵌入式Linux系统移植主要由四大部分组成:

一、搭建交叉开发环境

二、bootloader的选择和移植

三、kernel的配置、编译、和移植

四、根文件系统的制作

第一部分:搭建交叉开发环境

先介绍第一分部的内容:搭建交叉开发环境,首先必须得思考两个问题,什么是交叉环境 为什么需要搭建交叉环境?

先回答第一个问题,在嵌入式开发中,交叉开发是很重要的一个概念,开发的第一个环节就是搭建环境,第一步不能完成,后面的步骤从无谈起,这里所说的交叉开发环境主要指的是:在开发主机上(通常是我的pc机)开发出能够在目标机(通常是我们的开发板)上运行的程序。嵌入式比较特殊的是不能在目标机上开发程序(狭义上来说),因为对于一个原始的开发板,在没有任何程序的情况下它根本都跑不起来,为了让它能够跑起来,我们还必须要借助pc机进行烧录程序等相关工作,开发板才能跑起来,这里的pc机就是我们说的开发主机,想想如果没有开发主机,我们的目标机基本上就是无法开发,这也就是电子行业的一句名言:搞电子,说白了,就是玩电脑!

然后回答第二个问题,为什么需要交叉开发环境?主要原因有以下几点:

原因 1: 嵌入式系统的硬件资源有很多限制,比如cpu主频相对较低,内存容量较小等,想想让几百MHZ主频的MCU去编译一个Linux kernel会让我们等的不耐烦,相对来说,pc机的速度更快,硬件资源更加丰富,因此利用pc机进行开发会提高开发效率。

原因2: 嵌入式系统MCU体系结构和指令集不同,因此需要安装交叉编译工具进行编译,这样编译的目标程序才能够在相应的平台上比如:ARM、MIPS、 POWEPC上正常运行。

交叉开发环境的硬件组成主要由以下几大部分

1开发主机

2目标机(开发板)

3二者的链接介质,常用的主要有3种方式:(1)串口线 (2)USB线 (3)网线

对应的硬件介质,还必须要有相应的软件“介质”支持:

1对于串口,通常用的有串口调试助手,putty工具等,工具很多,功能都差不多,会用一两款就可以;

2对于USB线,当然必须要有USB的驱动才可以,一般芯片公司会提供,比如对于三星的芯片,USB下载主要由DNW软件来完成;

3对于网线,则必须要有网络协议支持才可以, 常用的服务主要两个

第一:tftp服务:

主要用于实现文件的下载,比如开发调试的过程中,主要用tftp把要测试的bootloader、kernel和文件系统直接下载到内存中运行,而不需要预先烧录到Flash芯片中,一方面,在测试的过程中,往往需要频繁的下载,如果每次把这些要测试的文件都烧录到Flash中然后再运行也可以,但是缺点是:过程比较麻烦,而且Flash的擦写次数是有限的;另外一方面:测试的目的就是把这些目标文件加载到内存中直接运行就可以了,而tftp就刚好能够实现这样的功能,因此,更没有必要把这些文件都烧录到Flash中去。

第二: nfs服务:

主要用于实现网络文件的挂载,实际上是实现网络文件的共享,在开发的过程中,通常在系统移植的最后一步会制作文件系统,那么这是可以把制作好的文件系统放置在我们开发主机PC的相应位置,开发板通过nfs服务进行挂载,从而测试我们制作的文件系统是否正确,在整个过程中并不需要把文件系统烧录到Flash中去,而且挂载是自动进行挂载的,bootload启动后,kernel运行起来后会根据我们设置的启动参数进行自动挂载,因此,对于开发测试来讲,这种方式非常的方便,能够提高开发效率。

另外,还有一个名字叫 samba 的服务也比较重要,主要用于文件的共享,这里说的共享和nfs的文件共享不是同一个概念,nfs的共享是实现网络文件的共享,而samba实现的是开发主机上 Windows主机和Linux虚拟机之间的文件共享,是一种跨平台的文件共享 ,方便的实现文件的传输。

以上这几种开发的工具在嵌入式开发中是必备的工具,对于嵌入式开发的效率提高做出了伟大的贡献,因此,要对这几个工具熟练使用,这样你的开发效率会提高很多。等测试完成以后,就会把相应的目标文件烧录到Flash中去,也就是等发布产品的时候才做的事情,因此对于开发人员来说,所有的工作永远是测试。

通过前面的工作,我们已经准备好了交叉开发环境的硬件部分和一部分软件,最后还缺少交叉编译器,读者可能会有疑问,为什么要用交叉编译器?前面已经讲过,交叉开发环境必然会用到交叉编译工具,通俗地讲就是在一种平台上编译出能运行在体系结构不同的另一种平台上的程序,开发主机PC平台(X86 CPU)上编译出能运行在以ARM为内核的CPU平台上的程序,编译得到的程序在X86 CPU平台上是不能运行的,必须放到ARM CPU平台上才能运行,虽然两个平台用的都是Linux系统。相对于交叉编译,平常做的编译叫本地编译,也就是在当前平台编译,编译得到的程序也是在本地执行。用来编译这种跨平台程序的编译器就叫交叉编译器,相对来说,用来做本地编译的工具就叫本地编译器。所以要生成在目标机上运行的程序,必须要用交叉编译工具链来完成。

这里又有一个问题,不就是一个交叉编译工具吗?为什么又叫交叉工具链呢?原因很简单,程序不能光编译一下就可以运行,还得进行汇编和链接等过程,同时还需要进行调试,对于一个很大工程,还需要进行工程管理等等,所以,这里 说的交叉编译工具是一个由 编译器、连接器和解释器 组成的综合开发环境,交叉编译工具链主要由binutils(主要包括汇编程序as和链接程序ld)、gcc(为GNU系统提供C编译器)和glibc(一些基本的C函数和其他函数的定义) 3个部分组成。有时为了减小libc库的大小,也可以用别的 c 库来代替 glibc,例如 uClibc、dietlibc 和 newlib。

那么,如何得到一个交叉工具链呢?是从网上下载一个“程序”然后安装就可以使用了吗?回答这个问题之前先思考这样一个问题,我们的交叉工具链顾名思义就是在PC机上编译出能够在我们目标开发平台比如ARM上运行的程序,这里就又有一个问题了,我们的ARM处理器型号非常多,难道有专门针对我们某一款的交叉工具链吗?若果有的话,可以想一想,这么多处理器平台,每个平台专门定制一个交叉工具链放在网络上,然后供大家去下载,想想可能需要找很久才能找到适合你的编译器,显然这种做法不太合理,且浪费资源!因此,要得到一个交叉工具链,就像我们移植一个Linux内核一样,我们只关心我们需要的东西,编译我们需要的东西在我们的平台上运行,不需要的东西我们不选择不编译,所以,交叉工具链的制作方法和系统移植有着很多相似的地方,也就是说,交叉开发工具是一个支持很多平台的工具集的集合(类似于Linux源码),然后我们只需从这些工具集中找出跟我们平台相关的工具就行了,那么如何才能找到跟我们的平台相关的工具,这就是涉及到一个如何制作交叉工具链的问题了。

通常构建交叉工具链有如下三种方法:

方法一 : 分步编译和安装交叉编译工具链所需要的库和源代码,最终生成交叉编译工具链。该方法相对比较困难,适合想深入学习构建交叉工具链的读者。如果只是想使用交叉工具链,建议使用下列的方法二构建交叉工具链。

方法二: 通过Crosstool-ng脚本工具来实现一次编译,生成交叉编译工具链,该方法相对于方法一要简单许多,并且出错的机会也非常少,建议大多数情况下使用该方法构建交叉编译工具链。

方法三 : 直接通过网上下载已经制作好的交叉编译工具链。该方法的优点不用多说,当然是简单省事,但与此同时该方法有一定的弊端就是局限性太大,因为毕竟是别人构建好的,也就是固定的,没有灵活性,所以构建所用的库以及编译器的版本也许并不适合你要编译的程序,同时也许会在使用时出现许多莫名其妙的错误,建议读者慎用此方法。

crosstool-ng是一个脚本工具,可以制作出适合不同平台的交叉编译工具链,在进行制作之前要安装一下软件:

$ sudo apt-get install g++ libncurses5-dev bison flex texinfo automake libtool patch gcj cvs cvsd gawk

crosstool脚本工具可以在http://ymorinis-a-geekorg/projects/crosstool下载到本地,然后解压,接下来就是进行安装配置了,这个配置优点类似内核的配置。主要的过程有以下几点:

1 设定源码包路径和交叉编译器的安装路径

2 修改交叉编译器针对的构架

3 增加编译时的并行进程数,以增加运行效率,加快编译,因为这个编译会比较慢。

4 关闭JAVA编译器 ,减少编译时间

5 编译

6 添加环境变量

7 刷新环境变量。

8 测试交叉工具链

到此,嵌入式Linux系统移植四大部分的第一部分工作全部完成,接下来可以进行后续的开发了。

第二部分:bootloader的选择和移植

01 Boot Loader 概念

就是在操作系统内核运行之前运行的一段小程序。通过这段小程序,我们可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核准备好正确的环境,他就是所谓的引导加载程序(Boot Loader)。

02 为什么系统移植之前要先移植BootLoader?

BootLoader的任务是引导操作系统,所谓引导操作系统,就是启动内核,让内核运行就是把内核加载到内存RAM中去运行,那先问两个问题:第一个问题,是谁把内核搬到内存中去运行?第二个问题:我们说的内存是SDRAM,大家都知道,这种内存和SRAM不同,最大的不同就是SRAM只要系统上电就可以运行,而SDRAM需要软件进行初始化才能运行,那么在把内核搬运到内存运行之前必须要先初始化内存吧,那么内存是由谁来初始化的呢?其实这两件事情都是由bootloader来干的,目的是为内核的运行准备好软硬件环境,没有bootloadr我们的系统当然不能跑起来。

03 bootloader的分类

首先更正一个错误的说法,很多人说bootloader就是U-boot,这种说法是错误的,确切来说是u-boot是bootloader的一种。也就是说bootloader具有很多种类,

由上图可以看出,不同的bootloader具有不同的使用范围,其中最令人瞩目的就是有一个叫U-Boot的bootloader,是一个通用的引导程序,而且同时支持X86、ARM和PowerPC等多种处理器架构。U-Boot,全称 Universal Boot Loader,是遵循GPL条款的开放源码项目,是由德国DENX小组开发的用于多种嵌入式CPU的bootloader程序,对于Linux的开发,德国的u-boot做出了巨大的贡献,而且是开源的。

u-boot具有以下特点:

① 开放源码;

② 支持多种嵌入式操作系统内核,如Linux、NetBSD, VxWorks, QNX, RTEMS, ARTOS, LynxOS;

③ 支持多个处理器系列,如PowerPC、ARM、x86、MIPS、XScale;

④ 较高的可靠性和稳定性;

⑤ 高度灵活的功能设置,适合U-Boot调试、操作系统不同引导要求、产品发布等;

⑥ 丰富的设备驱动源码,如串口、以太网、SDRAM、FLASH、LCD、NVRAM、EEPROM、RTC、键盘等;

⑦ 较为丰富的开发调试文档与强大的网络技术支持;

其实,把u-boot可以理解为是一个小型的操作系统。

04 u-boot的目录结构

board 目标板相关文件,主要包含SDRAM、FLASH驱动;

common 独立于处理器体系结构的通用代码,如内存大小探测与故障检测;

cpu 与处理器相关的文件。如mpc8xx子目录下含串口、网口、LCD驱动及中断初始化等文件;

driver 通用设备驱动,如CFI FLASH驱动(目前对INTEL FLASH支持较好)

doc U-Boot的说明文档;

examples可在U-Boot下运行的示例程序;如hello_worldc,timerc;

include U-Boot头文件;尤其configs子目录下与目标板相关的配置头文件是移植过程中经常要修改的文件;

lib_xxx 处理器体系相关的文件,如lib_ppc, lib_arm目录分别包含与PowerPC、ARM体系结构相关的文件;

net 与网络功能相关的文件目录,如bootp,nfs,tftp;

post 上电自检文件目录。尚有待于进一步完善;

rtc RTC驱动程序;

tools 用于创建U-Boot S-RECORD和BIN镜像文件的工具;

05 u-boot的工作模式

U-Boot的工作模式有 启动加载模式和下载模式 。启动加载模式是Bootloader的正常工作模式,嵌入式产品发布时,Bootloader必须工作在这种模式下,Bootloader将嵌入式操作系统从FLASH中加载到SDRAM中运行,整个过程是自动的。 下载模式 就是Bootloader通过某些通信手段将内核映像或根文件系统映像等从PC机中下载到目标板的SDRAM中运行,用户可以利用Bootloader提供的一些令接口来完成自己想要的操作,这种模式主要用于测试和开发。

06 u-boot的启动过程

大多数BootLoader都分为stage1和stage2两大部分,U-boot也不例外。依赖于cpu体系结构的代码(如设备初始化代码等)通常都放在stage1且可以用汇编语言来实现,而stage2则通常用C语言来实现,这样可以实现复杂的功能,而且有更好的可读性和移植性。

1、 stage1(starts代码结构)

U-boot的stage1代码通常放在starts文件中,它用汇编语言写成,其主要代码部分如下:

(1) 定义入口。由于一个可执行的image必须有一个入口点,并且只能有一个全局入口,通常这个入口放在rom(Flash)的0x0地址,因此,必须通知编译器以使其知道这个入口,该工作可通过修改连接器脚本来完成。

(2)设置异常向量(exception vector)。

(3)设置CPU的速度、时钟频率及中断控制寄存器。

(4)初始化内存控制器 。

(5)将rom中的程序复制到ram中。

(6)初始化堆栈 。

(7)转到ram中执行,该工作可使用指令ldrpc来完成。

2、 stage2(C语言代码部分)

lib_arm/boardc中的start armboot是C语言开始的函数,也是整个启动代码中C语言的主函数,同时还是整个u-boot(armboot)的主函数,该函数主要完成如下操作:

(1)调用一系列的初始化函数。

(2)初始化flash设备。

(3)初始化系统内存分配函数。

(4)如果目标系统拥有nand设备,则初始化nand设备。

(5)如果目标系统有显示设备,则初始化该类设备。

(6)初始化相关网络设备,填写ip,c地址等。

(7)进入命令循环(即整个boot的工作循环),接受用户从串口输入的命令,然后进行相应的工作。

07 基于cortex-a8的s5pc100bootloader启动过程分析

s5pc100支持两种启动方式,分别为USB启动方式和NandFlash启动方式:

1 S5PC100 USB启动过程

[1] A8 reset, 执行iROM中的程序

[2] iROM中的程序根据S5PC100的配置管脚(SW1开关4,拨到4对面),判断从哪里启动(USB)

[3] iROM中的程序会初始化USB,然后等待PC机下载程序

[4] 利用DNW程序,从PC机下载SDRAM的初始化程序到iRAM中运行,初始化SDRAM

[5] SDRAM初始化完毕,iROM中的程序继续接管A8, 然后等待PC下载程序(BootLoader)

[6] PC利用DNW下载BootLoader到SDRAM

[7] 在SDRAM中运行BootLoader

2 S5PC100 Nandflash启动过程

[1] A8 reset, 执行IROM中的程序

[2] iROM中的程序根据S5PC100的配置管脚(SW1开关4,拨到靠4那边),判断从哪里启动(Nandflash)

[3] iROM中的程序驱动Nandflash

[4] iROM中的程序会拷贝Nandflash前16k到iRAM

[5] 前16k的程序(BootLoader前半部分)初始化SDRAM,然后拷贝完整的BootLoader到SDRAM并运行

[6] BootLoader拷贝内核到SDRAM,并运行它

[7] 内核运行起来后,挂载rootfs,并且运行系统初始化脚本

08 u-boot移植(基于cortex_a8的s5pc100为例)

1建立自己的平台

(1)下载源码包201003版本,比较稳定

(2)解压后添加我们自己的平台信息,以smdkc100为参考版,移植自己s5pc100的开发板

(3)修改相应目录的文件名,和相应目录的Makefile,指定交叉工具链。

(4)编译

(5)针对我们的平台进行相应的移植,主要包括修改SDRAM的运行地址,从0x20000000

(6)“开关”相应的宏定义

(7)添加Nand和网卡的驱动代码

(8)优化go命令

(9)重新编译 make distclean(彻底删除中间文件和配置文件) make s5pc100_config(配置我们的开发板) make(编译出我们的u-bootbin镜像文件)

(10)设置环境变量,即启动参数,把编译好的u-boot下载到内存中运行,过程如下:

1 配置开发板网络

ip地址配置:

$setenv ipaddr 19216806 配置ip地址到内存的环境变量

$saveenv 保存环境变量的值到nandflash的参数区

网络测试:

在开发开发板上ping虚拟机:

$ ping 1921680157(虚拟机的ip地址)

如果网络测试失败,从下面几个方面检查网络:

1 网线连接好

2 开发板和虚拟机的ip地址是否配置在同一个网段

3 虚拟机网络一定要采用桥接(VM--Setting-->option)

4 连接开发板时,虚拟机需要设置成 静态ip地址

2 在开发板上,配置tftp服务器(虚拟机)的ip地址

$setenv serverip 1921680157(虚拟机的ip地址)

$saveenv

3 拷贝u-bootbin到/tftpboot(虚拟机上的目录)

4 通过tftp下载u-bootbin到开发板内存

$ tftp 20008000(内存地址即可) u-bootbin(要下载的文件名)

如果上面的命令无法正常下载:

1 serverip配置是否正确

2 tftp服务启动失败,重启tftp服务

#sudo service tftpd-hpa restart

5 烧写u-bootbin到nandflash的0地址

$nand erase 0(起始地址) 40000(大小) 擦出nandflash 0 - 256k的区域

$nand write 20008000((缓存u-bootbin的内存地址) 0(nandflash上u-boot的位置) 40000(烧写大小)

6 切换开发板的启动方式到nandflash

1 关闭开发板

2 把SW1的开关4拨到4的那边

3 启动开发板,它就从nandflash启动

要建立一个安全Linux服务器就首先要了解Linux环境下和网络服务相关的配置文件的含义及如何进行安全的配置。在Linux系统中,TCP/IP网络是通过若干个文本文件进行配置的,也许你需要编辑这些文件来完成联网工作,但是这些配置文件大都可以通过配置命令linuxconf(其中网络部分的配置可以通过netconf命令来实现)命令来实现。下面介绍基本的TCP/IP网络配置文件。

/etc/confmodules文件

该配置文件定义了各种需要在启动时加载的模块的参数信息。这里主要着重讨论关于网卡的配置。在使用Linux做网关的情况下,Linux服务器至少需要配置两块网卡。为了减少启动时可能出现的问题,Linux内核不会自动检测多个网卡。对于没有将网卡的驱动编译到内核而是作为模块动态载入的系统若需要安装多块网卡,应该在“confmodules”文件中进行相应的配置。

若设备驱动被编译为模块(内核的模块):对于PCI设备,模块将自动检测到所有已经安装到系统上的设备;对于ISA卡,则需要向模块提供IO地址,以使模块知道在何处寻找该卡,这些信息在“/etc/confmodules”中提供。

例如,我们有两块ISA总线的3c509卡,一个IO地址是0x300,另一个是0x320。编辑“confmodules”文件如下:

aliaseth03c509

aliaseth13c509

options3c509io=0x300,0x320

这是说明3c509的驱动程序应当分别以eth0或eth1的名称被加载(aliaseth0,eth1),并且它们应该以参数io=0x300,0x320被装载,来通知驱动程序到哪里去寻找网卡,其中0x是不可缺少的。

对于PCI卡,仅仅需要alias命令来使ethN和适当的驱动模块名关联,PCI卡的IO地址将会被自动的检测到。对于PCI卡,编辑“confmodules”文件如下:

aliaseth03c905

aliaseth13c905

若驱动已经被编译进了内核:系统启动时的PCI检测程序将会自动找到所有相关的网卡。ISA卡一般也能够被自动检测到,但是在某些情况下,ISA卡仍然需要做下面的配置工作:

在“/etc/liloconf”中增加配置信息,其方法是通过LILO程序将启动参数信息传递给内核。对于ISA卡,编辑“liloconf”文件,增加如下内容:

append="ether="0,0,eth0ether="0,0,eth1"

注:先不要在“liloconf”中加入启动参数,测试一下你的ISA卡,若失败再使用启动参数。

如果用传递启动参数的方法,eth0和eth1将按照启动时被发现的顺序来设置。

/etc/HOSTNAME文件

该文件包含了系统的主机名称,包括完全的域名,如:deepopenarchcom。

/etc/sysconfig/network-scripts/ifcfg-ethN文件

在RedHat中,系统网络设备的配置文件保存在“/etc/sysconfig/network-scripts”目录下,ifcfg-eth0包含第一块网卡的配置信息,ifcfg-eth1包含第二块网卡的配置信息。

下面是“/etc/sysconfig/network-scripts/ifcfg-eth0”文件的示例:

DEVICE=eth0

IPADDR=2081641861

NETMASK=2552552550

NETWORK=2081641860

BROADCAST=208164186255

ONBOOT=yes

BOOTPROTO=none

USERCTL=no

若希望手工修改网络地址或在新的接口上增加新的网络界面,可以通过修改对应的文件(ifcfg-ethN)或创建新的文件来实现。

DEVICE=name name表示物理设备的名字

IPADDR=addr addr表示赋给该卡的IP地址

NETMASK=mask mask表示网络掩码

NETWORK=addr addr表示网络地址

BROADCAST=addr addr表示广播地址

ONBOOT=yes/no 启动时是否激活该卡

none:无须启动协议

bootp:使用bootp协议

dhcp:使用dhcp协议

USERCTL=yes/no 是否允许非root用户控制该设备

/etc/resolvconf文件

该文件是由域名解析器(resolver,一个根据主机名解析IP地址的库)使用的配置文件,示例如下:

searchopenarchcom

nameserver2081641861

nameserver2081641862

“searchdomainnamecom”表示当提供了一个不包括完全域名的主机名时,在该主机名后添加domainnamecom的后缀;“nameserver”表示解析域名时使用该地址指定的主机为域名服务器。其中域名服务器是按照文件中出现的顺序来查询的。

/etc/hostconf文件

该文件指定如何解析主机名。Linux通过解析器库来获得主机名对应的IP地址。下面是一个“/etc/hostconf”的示例:

orderbind,hosts

multion

ospoofon

“orderbind,hosts”指定主机名查询顺序,这里规定先使用DNS来解析域名,然后再查询“/etc/hosts”文件(也可以相反)。

“multion”指定是否“/etc/hosts”文件中指定的主机可以有多个地址,拥有多个IP地址的主机一般称为多穴主机。

“nospoofon”指不允许对该服务器进行IP地址欺骗。IP欺骗是一种攻击系统安全的手段,通过把IP地址伪装成别的计算机,来取得其它计算机的信任。

/etc/sysconfig/network文件

该文件用来指定服务器上的网络配置信息,下面是一个示例:

NETWORK=yes

RORWARD_IPV4=yes

HOSTNAME=deepopenarchcom

GAREWAY=0000

GATEWAYDEV=

NETWORK=yes/no 网络是否被配置;

FORWARD_IPV4=yes/no 是否开启IP转发功能

HOSTNAME=hostnamehostname表示服务器的主机名

GAREWAY=gw-ip gw-ip表示网络网关的IP地址

GAREWAYDEV=gw-dev gw-dw表示网关的设备名,如:etho等

注意:为了和老的软件相兼容,“/etc/HOSTNAME”文件应该用和HOSTNAME=hostname相同的主机名。

/etc/hosts文件

当机器启动时,在可以查询DNS以前,机器需要查询一些主机名到IP地址的匹配。这些匹配信息存放在/etc/hosts文件中。在没有域名服务器情况下,系统上的所有网络程序都通过查询该文件来解析对应于某个主机名的IP地址。

下面是一个“/etc/hosts”文件的示例:

IPAddress Hostname Alias

127001 Localhost Gateopenarchcom

2081641861 gateopenarchcomGate

………… ………… ………

最左边一列是主机IP信息,中间一列是主机名。任何后面的列都是该主机的别名。一旦配置完机器的网络配置文件,应该重新启动网络以使修改生效。使用下面的命令来重新启动网络:/etc/rcd/initd/networkrestart

/etc/inetdconf文件

众所周知,作为服务器来说,服务端口开放越多,系统安全稳定性越难以保证。所以提供特定服务的服务器应该尽可能开放提供服务必不可少的端口,而将与服务器服务无关的服务关闭,比如:一台作为www和ftp服务器的机器,应该只开放80和25端口,而将其他无关的服务如:fingerauth等服务关掉,以减少系统漏洞。

而inetd,也叫作“超级服务器”,就是监视一些网络请求的守护进程,其根据网络请求来调用相应的服务进程来处理连接请求。inetdconf则是inetd的配置文件。inetdconf文件告诉inetd监听哪些网络端口,为每个端口启动哪个服务。在任何的网络环境中使用Linux系统,第一件要做的事就是了解一下服务器到底要提供哪些服务。不需要的那些服务应该被禁止掉,最好卸载掉,这样黑客就少了一些攻击系统的机会。查看“/etc/inetdconf”文件,了解一下inetd提供哪些服务。用加上注释的方法(在一行的开头加上#号),禁止任何不需要的服务,再给inetd进程发一个SIGHUP信号。

第一步:把文件的许可权限改成600。

[root@deep]#chmod600/etc/inetdconf

第二步:确信文件的所有者是root。

[root@deep]#stat/etc/inetdconf

第三步:编辑“inetdconf”文件(vi/etc/inetdconf),禁止所有不需要的服务,如:ftp、telnet、shell、login、exec、talk、ntalk、imap、pop-2、pop-3、finger、auth,等等。如果你觉得某些服务有用,可以不禁止这些服务。但是,把这些服务禁止掉,系统受攻击的可能性就会小很多。改变后的“inetdconf”文件的内容如下面所示:

#Tore-readthisfileafterchanges,justdoa'killall-HUPinetd'

#

#echostreamtcpnowaitrootinternal

#echodgramudpwaitrootinternal

#discardstreamtcpnowaitrootinternal

#discarddgramudpwaitrootinternal

#daytimestreamtcpnowaitrootinternal

#daytimedgramudpwaitrootinternal

#chargenstreamtcpnowaitrootinternal

#chargendgramudpwaitrootinternal

#timestreamtcpnowaitrootinternal

#timedgramudpwaitrootinternal

#

#Thesearestandardservices

#

#ftpstreamtcpnowaitroot/usr/sbin/tcpdinftpd-l-a

#telnetstreamtcpnowaitroot/usr/sbin/tcpdintelnetd

#

#Shell,login,exec,comsatandtalkareBSDprotocols

#

#shellstreamtcpnowaitroot/usr/sbin/tcpdinrshd

#loginstreamtcpnowaitroot/usr/sbin/tcpdinrlogind

#execstreamtcpnowaitroot/usr/sbin/tcpdinrexecd

#comsatdgramudpwaitroot/usr/sbin/tcpdincomsat

#talkdgramudpwaitroot/usr/sbin/tcpdintalkd

#ntalkdgramudpwaitroot/usr/sbin/tcpdinntalkd

#dtalkstreamtcpwaitnobody/usr/sbin/tcpdindtalkd

#

#Popandimapmailservicesetal

#

#pop-2streamtcpnowaitroot/usr/sbin/tcpdipop2d

#pop-3streamtcpnowaitroot/usr/sbin/tcpdipop3d

#imapstreamtcpnowaitroot/usr/sbin/tcpdimapd

#

#TheInternetUUCPservice

#

#uucpstreamtcpnowaituucp/usr/sbin/tcpd/usr/lib/uucp/uucico-l

#

#TftpserviceisprovidedprimarilyforbootingMostsites

#runthisonlyonmachinesactingas"bootservers"Donotuncomment

#thisunlessyouneedit

#

#tftpdgramudpwaitroot/usr/sbin/tcpdintftpd

#bootpsdgramudpwaitroot/usr/sbin/tcpdbootpd

#

#Finger,systatandnetstatgiveoutuserinformationwhichmaybe

#valuabletopotential"systemcrackers"Manysiteschoosetodisable

#someoralloftheseservicestoimprovesecurity

#

#fingerstreamtcpnowaitroot/usr/sbin/tcpdinfingerd

#cfingerstreamtcpnowaitroot/usr/sbin/tcpdincfingerd

#systatstreamtcpnowaitguest/usr/sbin/tcpd/bin/ps-auwwx

#netstatstreamtcpnowaitguest/usr/sbin/tcpd/bin/netstat-finet

#

#Authentication

#

#authstreamtcpnowaitnobody/usr/sbin/inidentdinidentd-l-e-o

#

#Endofinetdconf

注意:改变了“inetdconf”文件之后,别忘了给inetd进程发一个SIGHUP信号(killall–HUPinetd)。

[root@deep/root]#killall-HUPinetd

第四步:

为了保证“inetdconf”文件的安全,可以用chattr命令把它设成不可改变。把文件设成不可改变的只要用下面的命令:

[root@deep]#chattr+i/etc/inetdconf

这样可以避免“inetdconf”文件的任何改变(意外或是别的原因)。一个有“i”属性的文件是不能被改动的:不能删除或重命名,不能创建这个文件的链接,不能往这个文件里写数据。只有系统管理员才能设置和清除这个属性。如果要改变inetdconf文件,你必须先清除这个不允许改变的标志:

[root@deep]#chattr-i/etc/inetdconf

但是对于诸如sendmail,named,www等服务,由于它们不象finger,telnet等服务,在请求到来时由inet守护进程启动相应的进程提供服务,而是在系统启动时,作为守护进程运行的。而对于redhatlinux,提供了一个linuxconfig命令,可以通过它在图形界面下交互式地设置是否在启动时运行相关服务。也可以通过命令来设置是否启动时启动某个服务,如:[root@deep]#chkconfig–level35namedoff

具体命令可以参考manchkconfig的说明。

/etc/hostsallow文件

但是对于telnet、ftp等服务,如果将其一同关闭,那么对于管理员需要远程管理时,将非常不方便。Linux提供另外一种更为灵活和有效的方法来实现对服务请求用户的限制,从而可以在保证安全性的基础上,使可信任用户使用各种服务。Linux提供了一个叫TCPwrapper的程序。在大多数发布版本中该程序往往是缺省地被安装。利用TCPwrapper你可以限制访问前面提到的某些服务。而且TCPwrapper的记录文件记录了所有的企图访问你的系统的行为。通过last命令查看该程序的log,管理员可以获知谁曾经或者企图连接你的系统。

在/etc目录下,有两个文件:hostsdenyhostsallow通过配置这两个文件,你可以指定哪些机器可以使用这些服务,哪些不可以使用这些服务。

当服务请求到达服务器时,TCPwrapper就按照下列顺序查询这两个文件,直到遇到一个匹配为止:

1当在/etc/hostsallow里面有一项与请求服务的主机地址项匹配,那么就允许该主机获取该服务

2否则,如果在/etc/hostsdeny里面有一项与请求服务的主机地址项匹配,就禁止该主机使用该项服务。

3如果相应的配置文件不存在,访问控制软件就认为是一个空文件,所以可以通过删除或者移走配置文件实现对清除所有设置。在文件中,空白行或者以#开头的行被忽略,你可以通过在行前加#实现注释功能。

配置这两个文件是通过一种简单的访问控制语言来实现的,访问控制语句的基本格式为:

程序名列表:主机名/IP地址列表。

程序名列表指定一个或者多个提供相应服务的程序的名字,名字之间用逗号或者空格分割,可以在inetdconf文件里查看提供相应服务的程序名:如上面的文件示例中,telent所在行的最后一项就是所需的程序名:intelnetd。

主机名/IP地址列表指定允许或者禁止使用该服务的一个或者多个主机的标识,主机名之间用逗号或空格分隔。程序名和主机地址都可以使用通配符,实现方便的指定多项服务和多个主机。

Linux提供了下面灵活的方式指定进程或者主机列表:

1一个以""起始的域名串,如ammsaccn那么wwwammsaccn就和这一项匹配

2以""结尾的IP串如20237152那么IP地址包括20237152的主机都与这一项匹配。

3格式为nnnn/mmmm表示网络/掩码,如果请求服务的主机的IP地址与掩码的位与的结果等于nnnn那么该主机与该项匹配。

4ALL表示匹配所有可能性

5EXPECT表示除去后面所定义的主机。如:list_1EXCEPTlist_2表示list_1主机列表中除去List_2所列出的主机

6LOCAL表示匹配所有主机名中不包含""的主机

上面的几种方式只是Linux提供的方式中的几种,但是对于我们的一般应用来说是足够了。我们通过举几个例子来说明这个问题:

例一:我们只希望允许同一个局域网的机器使用服务器的ftp功能,而禁止广域网上面的ftp服务请求,本地局域网由20239154、20239153和20239152三个网段组成。

在hostsdeny文件中,我们定义禁止所有机器请求所有服务:

ALL:ALL

在hostsallow文件中,我们定义只允许局域网访问ftp功能:

inftpd-l–a:202391542023915320239152

这样,当非局域网的机器请求ftp服务时,就会被拒绝。而局域网的机器可以使用ftp服务。此外,应该定期检查/var/log目录下的纪录文件,发现对系统安全有威胁的登录事件。last命令可以有效的查看系统登录事件,发现问题所在。

最后tcpdchk是检查TCP_WAPPERS配置的程序。它检查TCP_WAPPERS的配置,并报告它可以发现的问题或潜在的问题。在所有的配置都完成了之后,请运行tcpdchk程序:

[root@deep]#tcpdchk

/etc/services文件

端口号和标准服务之间的对应关系在RFC1700“AssignedNumbers”中有详细的定义。“/etc/services”文件使得服务器和客户端的程序能够把服务的名字转成端口号,这张表在每一台主机上都存在,其文件名是“/etc/services”。只有“root”用户才有权限修改这个文件,而且在通常情况下这个文件是没有必要修改的,因为这个文件中已经包含了常用的服务所对应的端口号。为了提高安全性,我们可以给这个文件加上保护以避免没有经过授权的删除和改变。为了保护这个文件可以用下面的命令:

[root@deep]#chattr+i/etc/services

/etc/securetty文件

“/etc/securetty”文件允许你规定“root”用户可以从那个TTY设备登录。登录程序(通常是“/bin/login”)需要读取“/etc/securetty”文件。它的格式是:列出来的tty设备都是允许登录的,注释掉或是在这个文件中不存在的都是不允许root登录的。

注释掉(在这一行的开头加上#号)所有你想不让root登录的tty设备。

编辑securetty文件(vi/etc/securetty)象下面一样,注释掉一些行:

tty1

#tty2

#tty3

#tty4

#tty5

#tty6

#tty7

#tty8

使Control-Alt-Delete关机键无效

把“/etc/inittab”文件中的一行注释掉可以禁止用Control-Alt-Delete关闭计算机。如果服务器不是放在一个安全的地方,这非常重要。

编辑inittab文件(vi/etc/inittab)把这一行:

ca::ctrlaltdel:/sbin/shutdown-t3-rnow

改为:

#ca::ctrlaltdel:/sbin/shutdown-t3-rnow

用下面的命令使改变生效:

[root@deep]#/sbin/initq

改变“/etc/rcd/initd/”目录下的脚本文件的访问许可

/etc/rcd/initd/下的脚本主要包含了启动服务的脚本程序。一般用户没有什么必要知道脚本文件的内容。所以应该改变这些脚本文件的权限。

[root@deep]#chmod-R700/etc/rcd/initd/

这样只有root可以读、写和执行这个目录下的脚本。

/etc/rcd/rclocal文件

在默认情况下,当登录装有Linux系统的计算机时,系统会告诉你Linux发行版的名字、版本号、内核版本和服务器名称。这泄露了太多的系统信息。最好只显示一个“Login:”的提示信息。

第一步:

编辑“/ect/rcd/rclocal”文件,在下面这些行的前面加上“#”:

--

#Thiswilloverwrite/etc/issueateverybootSo,makeanychangesyou

#wanttomaketo/etc/issuehereoryouwilllosethemwhenyoureboot

#echo"">/etc/issue

#echo"$R">>/etc/issue

#echo"Kernel$(uname-r)on$a$(uname-m)">>/etc/issue

#

#cp-f/etc/issue/etc/issuenet

#echo>>/etc/issue

--

第二步:

删除“/etc”目录下的“issuenet”和“issue”文件:

[root@deep]#rm-f/etc/issue

[root@deep]#rm-f/etc/issuenet

注意:“/etc/issuenet”文件是用户从网络登录计算机时(例如:telnet、SSH),看到的登录提示。同样在“”目录下还有一个“issue”文件,是用户从本地登录时看到的提示。这两个文件都是文本文件,可以根据需要改变。但是,如果想删掉这两个文件,必须向上面介绍的那样把“/etc/rcd/rclocal”脚本中的那些行注释掉,否则每次重新启动的时候,系统又会重新创建这两个文件。

第一步:

我们要确认,LINUX下是不是安装了TFTP-SERVER

在LINUX下输入:

rpm -q tftp-server

如出现如下回复:

tftp-server-039-2 则表示tftp-server已安装

第二步:

修改TFTP启动脚本:

方法一:

需要修改ftptpd的启动脚本

vi /etc/xinetdd/tftp

加上 disable =no 此时即可启动tfpt服务

方法二:

直接输入: /sbin/chkconfig tftp on

此命令也是在启动脚本中加上disable=no

脚本修改后的效果如下:

Linux下,tftp服务器的启动

第三步:

启动TFTP服务

键入 service xinetd restart

这样我们的服务就启动OK了

键入 netstat -a | grep tftp

就可以查看是否安装并启动,得到

udp 0 0 :tftp :

表明安装 并启动成功

TFTP的默认根目录在/tftproot中

你装的客户端,如果是服务器端要装这个\x0d\yum install tftp-server\x0d\\x0d\并设置 /etc/xinetdd/tftp 中的 \x0d\disable = yes 改为 no \x0d\\x0d\tftp有分 tftp-server 和 tftp ,\x0d\tftp 就是客户端\x0d\tftp-server 是服务端

DABAN RP主题是一个优秀的主题,极致后台体验,无插件,集成会员系统
网站模板库 » 在linux系统中,哪些常用的服务需要构建?

0条评论

发表评论

提供最优质的资源集合

立即查看 了解详情