瑞星卡卡安全论坛技术交流区系统软件 =====Linux/Unix 应用宝典=====

1234   3  /  4  页   跳转

=====Linux/Unix 应用宝典=====

实现自动登录Linux
开机自动登录linux,并自动运行X window应用程序,有其特殊的应用背景,如基于linux平台的监控系统,linux启动后不需要身份验证,而直接运行监控程序等等。本文以Redhat7.2为平台,结合linux启动过程,介绍了如何避免身份验证自动登录,并直接进入X window自动运行应用程序。

一、linux启动的最后阶段的工作

linux 在启动过程的最后阶段(具体启动步骤略),init 会根据 /etc/inittab文件的最后一行x:5:respawn:/etc/X11/prefdm -nodaemon运行/etc/X11/prefdm脚本,(Red hat 7.2缺省时是这样的)。prefdm脚本的主要任务是完成X window的启动,可以有几种启动X window的方法,都包含在prefdm脚本中,几种主要方法有:

运行xdm启动X window;
运行gdm,进入gnome桌面环境;
运行kdm进入kde桌面环境;
自动登录进入linux;

prefdm脚本框架大致如下:


#!/bin/sh
PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin
. /etc/profile.d/lang.sh
# 第一步:查看是否为自动登录
if [ -f /etc/sysconfig/autologin -a -x /usr/sbin/autologin ]; then
if /usr/sbin/autologin; then
exit 0
fi
fi
# 第二步:如果不是自动登录方式,就会在/etc/sysconfig/desktop中搜寻用户偏爱的登录方式
......
# 可以是kdm、gdm以及xdm,并运行相应的kdm、gdm以及xdm。
......




二、自动登录的实现(autologin的实现)

在/etc/X11/prefdm脚本中,是否实现自动登录有一个条件测试开关,事实上,可以在这里注释掉测试开关,直接执行启动X window的操作。

自动登录实质上就是绕过身份验证,直接启动X window。X window的启动可以由xinit来完成。

Xinit用来启动X window系统服务器以及系统上的第一个客户程序,可以通过为xinit传递命令行参数的形式指定要启动的服务器及客户程序。如果不传递参数给xinit,它将在用户的根目录下寻找并运行 .xinitrc脚本来启动客户程序;在用户的根目录下寻找并运行 .xserverrc脚本来启动服务器。如果xinit在用户的根目录下找不到.xinitrc、.xserverrc,xinit将使用缺省的X :0。
实际上,用startx来启动X更为方便。对于运行单一会话的X window 系统,startx提供了更为良好的用户接口。同样,startx首先在用户的根目录下寻找 .xinitrc及.xserverrc脚本,如果找不到这两个脚本,startx将使用/etc/X11/xinit/xinitrc以及/etc/X11/xinit/xserverrc脚本。
startx脚本的最基本框架是:

a、 寻找.xinitrc,如果没有则使用xinitrc;
b、 寻找.xserverrc,如果没有则使用xserverrc;
c、 根据找到的脚本确定xinit的参数;

由此可看出,startx在不需要传递任何参数的情况下,可以完成启动X的任务,因此,可以如下修改/etc/X11/prefdm脚本来实现自动登录:


#!/bin/sh
PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin
. /etc/profile.d/lang.sh
# 第一步:查看是否为自动登录
#if [ -f /etc/sysconfig/autologin -a -x /usr/sbin/autologin ]; then
#注释掉上边的条件测试,直接运行startx
if /usr/X11R6/bin/startx; then
exit 0
fi
#fi




当然,应确保/etc/inittab中的启动级别为5。


重新启动系统,会发现系统不验证用户身份,直接进入X window,此时的用户身份为root。但是,如果原来root有自己的桌面、默认shell时,上述方法启动X不一定保证还能拥有原来的设置。为了在启动X后,在避免验证身份的同时,又不改变用户原来的设置,那么在运行startx之前,还有工作要做。


gototop
 

接上
三、自动登录后,保持用户原来的配置(桌面、shell以及其它的一些环境变量)。

观察原来/etc/X11/prefdm脚本的自动登录部分:


......
# 第一步:查看是否为自动登录
if [ -f /etc/sysconfig/autologin -a -x /usr/sbin/autologin ]; then
if /usr/sbin/autologin; then
exit 0
fi
fi
......




不难看出,脚本中保留了自动登录的接口:一个可执行文件/usr/sbin/autologin以及一个配置文件/etc/sysconfig/autologin。

1、/etc/sysconfig/autologin配置文件的实现:


#config for autologin
USER=root
EXEC=/usr/X11R6/bin/startx
说明,USER指定自动登录时的用户名;EXEC指定启动X要运行的程序。





2、/usr/sbin/autologin可执行文件的实现:


/*********************
****  autologin.c  ****
*********************/
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pwd.h>
int main(int argc, char **argv)
{
struct stat st;
FILE *f;
char *cfg;
struct passwd *pw;
uid_t uid;
gid_t gid;
char *dir, *shell;
char *user=NULL;
char *cmd=NULL;
user="root";
/*为了能说明问题又保持程序简洁,这里默认登录用户为root,实际上,
登陆用户名应该从/etc/sysconfig/autologin中得到,
程序实现时要注意过滤掉/etc/sysconfig/autologin中的无效用户名*/
cmd="/usr/X11R6/bin/startx";
/*同样,这里直接指定启动X window的程序,实际上,该程序应该从/etc/sysconfig/autologin中得到*/
pw = getpwnam(user);
//getpwnam返回包含用户信息的passwd结构(该结构在pwd.h中定义)。
if(pw) {
uid=pw->pw_uid;
gid=pw->pw_gid;dir=strdup(pw->pw_dir);
shell=strdup(pw->pw_shell);
}
//获得用户相关信息
else {
printf("ERROR: No such user %s!\n", user);
return 1;
}
chown("/dev/console", uid, gid);
chown("/dev/tty", uid, gid);
//为控制台和终端设置用户ID及组ID

//下面是设置用户相关ID
setregid(gid, gid);
setegid(gid);
setgid(gid);
setreuid(uid, uid);
seteuid(uid);
setuid(uid);
setenv("HOME", dir, 1);
setenv("SHELL", shell, 1);
setenv("USER", user, 1);
setenv("LOGNAME", user, 1);
//设置用户相关环境变量
chdir(dir);
//切换到用户根目录
user=NULL;
execvp(cmd, argv);
/*在配置完用户的相关信息后,执行启动X window操作。注意这里默认执行/usr/X11R6/bin/startx */
printf("ERROR: Couldn't exec %s: %s\n", cmd, strerror(errno));
return 2;
}




运行gcc -o autologin autologin.c,拷贝autologin可执行文件到/usr/sbin/autologin,拷贝autologin配置文件到/etc/sysconfig/autologin。 重新启动系统,会直接进入X window并保留用户原来所有的风格。


如果不需要自动登录的配置文件/etc/sysconfig/autologin,所有的操作都在/usr/sbin/autologin以默认的方式实现(比如,默认登录身份为root,默认执行操作为/usr/X11R6/bin/startx等),那么,/etc/X11/prefdm脚本的自动登录部分可简化如下:


......
# 第一步:查看是否为自动登录
if /usr/sbin/autologin; then
exit 0
fi
//第二步......
......




即在脚本中去掉条件测试开关,直接执行/usr/sbin/autologin,这时,只需要拷贝autologin可执行文件到/usr/sbin/autologin,不再需要拷贝autologin配置文件到/etc/sysconfig/autologin。

四、选择进入kde或者gnome,并自动启动X window应用程序

如果重新启动后系统进入了kde,而用户需要进入gnome,只需运行switchdesk gnome在重新启动系统即可,以后每次启动时会自动进入gnome;反之亦然。
一般系统自动登录的目的是启动X window 后自动运行某个X window程序。如果系统默认的启动级别为3,那么如果要在系统启动后自动运行某些应用程序,只需要在某些脚本中加入相应命令即可,不再详述。在X window启动后自动运行应用程序要复杂一些,幸好,kde和gnome都为此留下了自动启动接口。如果在kde桌面环境下自动启动应用程序,只需要把应用程序名字加入/root/.kde/Autostart/目录下即可(这里注意不同用户的根目录可能不同,如用户zyx的根目录可能为/home/zyx)。如果在gnome桌面环境下自动启动应用程序,只需把应用程序的名字加入/主菜单/程序/设置/会话/会话特性及启动程序的startup programs属性页中即可。
gototop
 

对光驱、软驱实现AutoMount
软件环境:Redhat Linux 6.0
目 的:在使用Linux的过程中,我们经常需要使用光盘和软盘,每次使用时都要mount,用完还要umount非常麻烦,可以使这些工作变得自动化。

实现方法:

1. 安装完Redhat Linux 6.0之后,运行ntsysv,选中服务后台程序autofs.autofs的两个配置文件在/etc/auto.misc 和 /etc/auto.master

2. /etc/auto.master定义了mount目录和mount所需的配置文件名及其空闲时自动umount的时间。 下面是默认配置。

[jephe@sh3 /etc]$ more auto.master
/misc /etc/auto.misc --timeout 60

3. 下面是我的/etc/auto.misc配置文件:

[jephe@sh3 /etc]$ more auto.misc
cdrom -fstype=iso9660,ro :/dev/cdrom
floppy -fstype=vfat :/dev/fd0
e2floppy -fstype=ext2 :/dev/fd0

注:
a.确保/dev/cdrom作为符号链接指向你的光驱所在的分区,作为我的情况:

[jephe@sh3 /dev]$ ls cdrom -l
lrwxrwxrwx 1 root root 3 Aug 26 08:44 cdrom -> hdd

b.当软盘为windows 95格化化的vfat分区类型时,设定了安装目录/misc/floppy
c.当软盘为Linux格式化过的ext2分区类型时,设定了安装目录/misc/e2floppy

4. 至此,若还未启动autofs,则运行/etc/rc.d/init.d/autofs start, 若对上述两个文件中做过任何更改,运行/etc/rc.d/init.d/autofs restart即可。

5. 放入一片光盘进入光驱后,不需任何动作,直接进入目录/misc/cdrom,autofs 将自动先为你mount光驱同样,若放入一张vfat格式的软盘,你可以
cd /misc/floppy,
若是ext2格式的软盘,则cd /misc/e2floppy. 在超过一分钟未使用它们,且当前目录不是自动mount目录/misc/cdrom,/misc/floppy,/misc/e2floppy,系统将自动umount它们。


gototop
 

Linux下面光盘刻录
在linux下刻盘分四部曲:

1.编译内核(依系统情况可以略过).
2.加载相应驱动模块.
3.制作iso9660文件系统的映象文件
4.刻盘

缺省情况下,你的linux内核或许不支持SCSI设备,而现在的刻录机却许多接在一个scsi卡上的.因此,在这种情况下,需要从新编译内核,让它支持SCSI设备,并且要根据SCSI卡所采用的芯片,将其编译到内核或编译成模块.此外,为方便测试将要刻录的映象文件,还应该编译时在块设备里面选择支持"LOOPBACK DEVICE SUPPORT".最后,还要选择"SCSI generic support",将其编译成模块,这专门是为支持这种连接在一块SCSI卡上的刻录机刻录时用的.

然后,重新启动系统,启动过程中会检测SCSI设备,因为检测的特别快,可能看不清. 没有关系,登录后用"dmesg"命令来看系统查到了什么东西,比如屏幕上打印了这么一块信息:

sym53c8xx: at PCI bus 0, device 9, function 0
sym53c8xx: setting PCI_COMMAND_PARITY...(fix-up)

sym53c8xx: 53c810a detected
sym53c810a-0: rev=0x23, base=0xe6000000, io_port=0xe400, irq=11
sym53c810a-0: ID 7, Fast-10, Parity Checking
sym53c810a-0: restart (scsi reset).
scsi0 : sym53c8xx - version 1.3c
scsi : 1 host.
Vendor: MATSHITA Model: CD-R CW-7502 Rev: 4.17
Type: CD-ROM ANSI SCSI revision: 02

当然了,这是在我的系统启动时打印的信息,如果你没有看到类似的信息,说明你没有把SCSI卡所用芯片编译到内核或在系统启动时没有把自动加载相应的驱动模块(通过配制/etc/conf.modules在启动时加载相应模块).这时候,你可以手工加载模块.当模块加载到系统中后,就应该出现以上类似的信息了.在我用的SCSI卡上采用的芯片BIOS是"SYMBIOS 53C810AE",因此在编译内核时选择了"SYM53C8XX SCSI SUPPORT",并把它编译成模块.下面简单介绍一下以上信息:

首先它显示在PCI插槽上发现了SCSI卡,紧接着,发现了SCSI卡上连接的设备,它的ID号是7,在scsi0上.

当找到设备后,剩下的事情就简单了,现在需要找的就是一些制作ISO映象程序刻录时用的软件.我用的软件是cdrecord,软件很不错,本身可以在SCSI卡上检测所连接设备,也支持multi-session刻录(允许你一次刻不完下次再刻).制作ISO映象文件用的是mkisofs这个程序,一般的linux都带这个包,在redhat中包的名字和文件的名字一样.

假如我有一个整理好待刻的目录,里面有一堆很好的收藏.我首先把用下面的命令作成一个ISO格式的映象文件(这并不是刻录,只是在硬盘上按1:1的比例将要刻的东西作并不是刻录,只是在硬盘上按1:1的比例将要刻的东西作成一个映象):

mkisofs -r -o cd_image my_private/

"-r"指明将所有的文件属性变成对所有人是可读属性的,"-o"是输出, my_private是要刻东西所在的目录.

作完映象文件后,可以检测它是否正确,此时要加载曾经编译的loop模块,将此映象文件作为一个文件系统"mount"上来.

mount -t iso9660 -o ro,loop=/dev/loop0 cd_image /mnt/cdrom

进入/mnt/cdrom就可以查看文件是否正确.主意的是,用mkisofs可以制作带光盘启动的映象,这要通过"-b"参数,"-b"后面紧接着的是可以启动的内核文件,它的大小是有限制的,必须是1.2或1.44或2.88MB,它的路径也是相对于my_private目录而言的.

最后一步,"天下无盘",你可别刻费了吆.:-) 现在就开始真正动手了.用下载来的刻录软件进行刻录.

这里只对cdrecord进行简略介绍,还有一些图形界面的刻录工具,各位就自己找吧.关于cdrecord可以在 http://hkt.linuxberg.com这个网站找到.用

cdrecord -scanbus

可以显示出下列类似信息:

Cdrecord release 1.6.1 Copyright (C) 1995-1998 J鲵g Schilling
scsibus0:
        0) *
        1) *
        2) *
        3) *
        3) *
        4) *
        5) *
        6) 'MATSHITA' 'CD-R CW-7502 ' '4.17' Removable CD-ROM

ID号为7的一个刻录机找到,下面开始了.

cdrecord -v speed=2 dev=6,0 cd_image

"speed=2"指明刻盘速度为2倍速, "dev=6,0"指明关于刻录设备的一些信息,完整的形式是"dev=devicename:scsibus,target,lun",我们这里只有一个接在SCSI卡上的设备, 因此只些了简略形式"dev=target,lun",其中devicename是CD-R所对应的设备名,SCSIBUS是SCSI总线号,TARGET就是刚才检测出来的第六项,LUN指的是SCSI设备的逻辑单元号,一般的SCSI设备只支持一个LUN.
gototop
 

安装完全解决方案
Qmail_setup-v1.5.tar.gz改进版本Qmail_setup-v1.5.2.tar.gz提供下载,全面支持MYSQL数据库,使得能容纳几十万的用户数据。包内还另付非常详细的设置说明,中英文皆有。
http://www.edge-china.com/~lhg/Qmail_setup-v1.5.2.tar.gz


该包目前有的功能
1、Qmail帐号与系统帐号的分离。
2、Qmail邮件列表功能。
3、Qmail自动回复功能。
4、邮件帐号WEB管理方式。
5、邮件的WEB使用方式,如:WEB发邮件,查看邮件。
6、能任意调整WEB的CGI以及HTML路径。
7、选择性安装apache。
8、SMTP服务的密码验证功能,能有效的防止别人利用自己的服务器发送匿名信。
9、选择性安装webmail。
10、对虚拟域的支持。
11、增加对Linux系统的支持,安装过程中自动的判断系统进行安装。
12、增加qmail的管理脚本,安装后可以运行qmail start|stop|restart来管理qmail。
13、全面支持Mysql数据库,只要在SQL设置区里打开数据库的支持,并设置好数据库密码,就可
以支持数据库了。

安装方法:
1、用编辑器编辑setup文件,设置变量,如:
DomainName,CGI路径,HTML路径。MAIL管理员密码等。
2、设置文件"setup"文件为755。
  chmod 755 install
3、运行setup进行安装。
  ./setup
4、等待安装完毕......

该包对以前版本的比较。
1、解决了以前版本不能用WEB修改密码的问题。
2、解决了SMTP发信无密码验证问题。
3、新加setup文件的高级设置,如果你觉得有些东西有必要修改就可以在高级设置里修改。
比如:对邮件用户邮件大小的限额、是否支持漫游,等高级设置。
4、因考虑到有些情况不必要用到webmail或想使用更好的WEBMAIL,所以增加了WEBMAIL安装
的可选择性。
5、解决了以前不支持Linux系统的问题,能自动判断FreeBSD和Linux系统来进行安装。
6、使用了最新版本的apache。
7、增加qmail的管理脚本,使得qmail的管理更加方便。
8、对数据库的支持,并且是可选择性的。
gototop
 

删除具有特殊文件名的文件
假设Linux系统中有一个文件名叫“-ee”,如果我们想对它进行操作,例如要删除它,按照一般的删除方法在命令行中输入rm -ee命令,界面会提示我们是“无效选项”(invalid option),原来由于文件名的第一个字符为“-”,Linux把文件名当作选项了,我们可以使用“--”符号来解决这个问题,输入“rm -- -ee”命令便可顺利删除名为“-ee”的文件。如果是其他特殊字符的话可以在特殊字符前加一个“”符号,或者用双引号把整个文件名括起来。
gototop
 

linux环境下的"蚂蚁"-wget使用简介
wget的使用形式是:
wget [参数列表] URL
首先来介绍一下wget的主要参数:
· -b:让wget在后台运行,记录文件写在当前目录下"wget-log"文件中;
· -t [nuber of times]:尝试次数,当wget无法与服务器建立连接时,尝试连接多少次
。比如"-t
120"表示尝试120次。当这一项为"0"的时候,指定尝试无穷多次直到连接成功为止,这个
设置非常有用,当对方服务器突然关机或者网络突然中断的时候,可以在恢复正常后继续
下载没有传完的文件;
· -c:断点续传,这也是个非常有用的设置,特别当下载比较大的文件的时候,如果中
途意外中断,那么连接恢复的时候会从上次没传完的地方接着传,而不是又从头开始,使
用这一项需要远程服务器也支持断点续传,一般来讲,基于UNIX/Linux的Web/FTP服务器
都支持断点续传;
· -T [number of seconds]:超时时间,指定多长时间远程服务器没有响应就中断连接
,开始下一次尝试。比如"-T
120"表示如果120秒以后远程服务器没有发过来数据,就重新尝试连接。如果网络速度比
较快,这个时间可以设置的短些,相反,可以设置的长一些,一般最多不超过900,通常
也不少于60,一般设置在120左右比较合适;
· -w [number of seconds]:在两次尝试之间等待多少秒,比如"-w 100"表示两次尝试
之间等待100秒;
· -Y on/off:通过/不通过代理服务器进行连接;
· -Q [byetes]:限制下载文件的总大小最多不能超过多少,比如"-Q2k"表示不能超过2K
字节,"-Q3m"表示最多不能超过3M字节,如果数字后面什么都不加,就表示是以字节为单
位,比如"-Q200"表示最多不能超过200字节;
· -nd:不下载目录结构,把从服务器所有指定目录下载的文件都堆到当前目录里;
· -x:与"-nd"设置刚好相反,创建完整的目录结构,例如"wget -nd
http://www.gnu.org"将创建在当前目录下创建"www.gnu.org"子目录,然后按照服务器
实际的目录结构一级一级建下去,直到所有的文件都传完为止;
· -nH:不创建以目标主机域名为目录名的目录,将目标主机的目录结构直接下到当前目
录下;
· --http-user=username
· --http-passwd=password:如果Web服务器需要指定用户名和口令,用这两项来设定;
· --proxy-user=username
· --proxy-passwd=password:如果代理服务器需要输入用户名和口令,使用这两个选项

· -r:在本机建立服务器端目录结构;
· -l [depth]:下载远程服务器目录结构的深度,例如"-l 5"下载目录深度小于或者等
于5以内的目录结构或者文件;
· -m:做站点镜像时的选项,如果你想做一个站点的镜像,使用这个选项,它将自动设
定其他合适的选项以便于站点镜像;
· -np:只下载目标站点指定目录及其子目录的内容。这也是一个非常有用的选项,我们
假设某个人的个人主页里面有一个指向这个站点其他人个人主页的连接,而我们只想下载
这个人的个人主页,如果不设置这个选项,甚至--有可能把整个站点给抓下来,这显然是
我们通常不希望的;
ü 如何设定wget所使用的代理服务器
wget可以使用用户设置文件".wgetrc"来读取很多设置,我们这里主要利用这个文件来是
设置代理服务器。使用者用什么用户登录,那么什么用户主目录下的".wgetrc"文件就起
作用。例如,"root"用户如果想使用".wgetrc"来设置代理服务器,"/root/.wgert"就起
作用,下面给出一个".wge
trc"文件的内容,读者可以参照这个例子来编写自己的"wgetrc"文件:
http-proxy = 111.111.111.111:8080
ftp-proxy = 111.111.111.111:8080
这两行的含义是,代理服务器IP地址为:111.111.111.111,端口号为:80。第一行指定
HTTP协议所使用的代理服务器,第二行指定FTP协议所使用的代理服务器。
gototop
 

Linux开机过程的分析
这篇文章的目的,在将linuxkernel的boot部份做一个介绍,因为笔者觉得很少有这样的文章介绍一个作业系统最最开始的一步--把kernel本身载入至内存中,同时进行一些机器相关(machinedependent)的初始化工作,由于linux刚好使用的是大家最熟悉的386,486系列PC,所以在说明其程序流程时,也刚好可以对其相关的PC硬体架构做探讨,可以说是一举两得,不过,我必须假设读者对于组合语言及PC最基础的架构,如寄存器,分段,分页,中断服务等有大概的认识。
   读者可在linuxsourcecode的/boot子目录下找到几个以.S作为副档名的组合语言档,本文要说明的即是其中的bootsect.S及setup.S两个档案,及尽量简单的说明其所牵涉的相关硬体部份。
bootsect.S
  这个程序是linuxkernel的第一个程序,包括了linux自己的bootstrap程序,但是在说明这个程序前,必须先说明一般IBMPC开机时的动作(此处的开机是指"打开PC的电源"):
  一般PC在电源一开时,是由内存中地址FFFF:0000开始执行(这个地址一定在ROMBIOS中,ROMBIOS一般是在FEOOOh到FFFFFh中),而此处的内容则是一个jump指令,jump到另一个位于ROMBIOS中的位置,开始执行一系列的动作,包括了检查RAM,keyboard,显示器,软硬磁盘等等,这些动作是由系统测试码(systemtestcode)来执行的,随着制作BIOS厂商的不同而会有些许差异,但都是大同小异,读者可自行观察自家机器开机时,萤幕上所显示的检查讯息。
  紧接着系统测试码之后,控制权会转移给ROM中的启动程序(ROMbootstraproutine),这个程序会将磁盘上的零道零扇区读入内存中(这就是一般所谓的bootsector,如果你曾接触过电脑病毒,就大概听过它的大名),至于被读到内存的哪里呢?--绝对位置07C0:0000(即07C00h处),这是IBM系列PC的特性。而位在linux开机磁盘的bootsector上的正是linux的bootsect程序,也就是说,bootsect是第一个被读入内存中并执行的程序。现在,我们可以开始来看看到底bootsect做了什么。

第一步
  首先,bootsect将它"自己"从被ROMBIOS载入的绝对地址0x7C00处搬到0x90000处,然后利用一个jmpi(jumpindirectly)的指令,跳到新位置的jmpi的下一行去执行,关键的assemblycode如下:
.
(搬移bootsect本身)
.
.
jmpigo,INITSEC
go:
.
.
.
  表示将跳到CS为0x9000,IP为offset"go"的位置(CS:IP=0x9000:offsetgo),其中INITSEC=0x9000定义于程序开头的部份,而go这个label则恰好是下一行指令所在的位置。
第二步
  接着,将其它segmentregisters包括DS,ES,SS都指向0x9000这个位置,与CS看齐。另外将SP及DX指向一任意位移地址(offset),这个地址等一下会用来存放磁盘参数表(diskpara-metertable)
  提到磁盘参数表,就必须提到BIOS中断1Eh。先简单的介绍一下BIOS的中断服务:80x86将内存最低的256*4byte保留给256个中断向量(每个interruptvector大小为4byte,所以一共有256*4=1024byte),而其中的第1Eh个向量指向"磁盘参数表",这个表会告诉电脑如何去读取磁盘机,而我们所要做的事是搬移磁盘参数表到刚才所设定的任意地址。
  接着,改变搬移来的参数表的参数,以符合我们的需要。再将中断向量1Eh指向我们所修改过的磁盘参数表,然后呼叫BIOSinterrupt的int13h(function0,即AH=0)重置磁盘控制卡及磁盘驱动器,之后磁盘机就会照我们的意思动作了。如果你曾trace过DOS的kernel,你会发现,上述的动作在DOS中也有类似的对应流程。
现在让我们来看看关键的程序码:.
.
.
push#0
popfs
movbx,#0x78
.
(使GS:SI=FS:BX,指向磁盘参数表,
再将GS:SI所指地址的内容搬移6个
word至ES:DI所指的地址)
.
.
  此段程序是将FS:BX调整成0000:0078,接着再将GS:SI的内容设成与FS:BX相同,此处0x78h即为int1Eh的起始位置(7*16+8=120,(1*16+14)*4=120)。调整ES:DI为刚才所设定的任意地址,从GS:SI搬移6个word(即12byte)到ES:DI所指的位置,显然磁盘参数表的长度就是6个word,(不过事实上,磁盘参数表的确实长度是11个byte)。关于磁盘参数表,有兴趣的读者可自行参阅讲述BIOSinterruptservices的技术手册,会有详细的说明。
  读者可以用debug自行观察自家机器上DOS的磁盘参数表的起始位置(即int1Eh的内容)。以下是笔者机器的情形(笔者使用的作业系统是MSDOS6.2):
C:>debug
-d0000:0000
0000:00008A101601F4067000-1600CB04F4067000......p.......p.
0000:0010F40670000301790E-43EB00F0EBEA00F0..p...y.C.......
0000:002004108E340C118E34-5700CB046F00CB04...4...4W...o...
0000:00308700CB0408079433-B700CB04F4067000.......3......p.
0000:00400C01790E4DF800F0-41F800F0BA165F06..y.M...A....._.
0000:005039E700F01B01790E-70118E341201790E9.....y.p..4..y.
0000:006000E000F085175F06-6EFE00F0EE067000......_.n.....p.
0000:007053FF00F0A4F000F0-220500003E4600C0S......."...>F..
^^^^^^^^
由上图中可知,在DOS中磁盘参数表的起始位置(int1Eh的内容)为0000:0522。接着观察DOS中位置0000:0522开始的11个byte,也就是磁盘参数表的内容
C:>debug
-d0000:0520l10
0000:05204D53DF022502121B-FF54F60F08000000MS..%....T......
^^^^^^^^^^^^^^^^^^^^^^
此11byte即为磁盘参数表的内容(分别是byte00h到0Ah)
  在程序中我们所更动的是第五个byte(byte04h),改为18h(在上图例子中为12h),这个byte的功能是定义磁轨上一个磁区的资料笔数。关键的程序码如下:
.
movb4(di),*18
.
 
第叁步
  接着利用BIOS中断服务int13h的第0号功能,重置磁盘控制器,使得刚才的设定发挥功能。
.
.
xorah,ah
xordl,dl
int0x13
.
.
第四步
  完成重置磁盘控制器之后,bootsect就从磁盘上读入紧邻着bootsect的setup程序,也就是以后将会介绍的setup.S,此读入动作是利用BIOS中断服务int13h的第2号功能。setup的image将会读入至程序所指定的内存绝对地址0x90200处,也就是在内存中紧邻着bootsect所在的位置。待setup的image读入内存后,利用BIOS中断服务int13h的第8号功能读取目前磁盘机的参数。
第五步
  再来,就要读入真正linux的kernel了,也就是你可以在linux的根目录下看到的"vmlinuz"。在读入前,将会先呼叫BIOS中断服务int10h的第3号功能,读取游标位置,之后再呼叫BIOS中断服务int10h的第13h号功能,在萤幕上输出字符串"Loading",这个字符串在bootlinux时都会首先被看到,相信大家应该觉得很眼熟吧。
  linux的kernel将会被读入至内存绝对地址0x10000处,键关的程序码如下:
.
.
movax,#SYSSEG
moves,ax
callread_it
callkill_motor
.
.
  其中SYSSEG于程序开头时定义为0x1000,先将ES内容设为0x1000,接着在read_it这个子程序便以ES为目的地的节地址,将kernel读入内存中,至于read_it子程序的详细内容笔者并不想一一介绍,不过聪明的读者们应该已经猜到,read_it一定又利用了BIOSint13h与磁盘有关的I/O中断服务了。
  至于kill_motor子程序,它的功能在于停止软盘机的马达(各位聪明的读者会不会觉得这个子程序的名称取得颇为传神呢?),其程序码如下:
.
.
kill_motor:
pushdx
movdx,#0x3f2
xoral,al
outb
popdx
ret
.
.
  首先利用DX指定要输出的port,而03f2这个port则是代表了软盘控制器(floppydiskcontroller)的所在,再利用outb将资料送出,而我们送出的资料,当然就是归零过的AL了。如此一来,软盘的马达就停止了。
第六步
  接下来做的事是检查rootdevice,之后就仿照一开始的方法,利用indirectjump跳至刚刚已读入的setup部份,程序码如下:
.
.
jmpi0,SETYPSEG
  其中SETUPSEG已在先前定义为0x9020,所以CS:IP会设定为9020:0000,即跳到绝对地址为0x90200,也就是setup的起点。而bootsect也大功告成了。
到此为止,内存的内容应该如下图所示:
比较
  把大家所熟知的MSDOS与linux的开机部份做个粗浅的比较,MSDOS由位于磁盘上bootsector的boot程序负责把IO.SYS载入内存中,而IO.SYS则负有把DOS的kernel--MSDOS.SYS载入内存的重责大任。而linux则是由位于bootsector的bootsect程序负责把setup及linux的kernel载入内存中,再将控制权交给setup。
至于setup.S就不讨论了。
gototop
 

在linux的电脑,安装windows2000
首先,你需要重新安装LILO。打开/etc/lilo.conf文件,找到boot=/dev/hda行,把hda改为linux所在分区(比如linux安在第一块硬盘的第二分区,那么就改成hda2,余类推),保存改动,执行lilo命令。用mkbootdisk命令制作一张启动盘(多做几张,以备不测)。在执行 dd if=/dev/hda2 of=/tmp/bootsect.lnx bs=512 count=1; mcopy /tmp/bootsect.lnx a: (软区里要有一张用DOS格过的软盘),取出软盘,插入win98启动盘。重新启动计算机,用win98启动盘进入DOS,执行fdisk/mbr命令。取出软盘,重新启动计算机,应该显示缺少系统盘。插入win2000光盘,重启机子,安装吧。安好后,将bootsect.lnx文件拷到C盘跟目录下,编辑c:\boot.ini文件(是隐藏的和只读的,需要去掉该属性),增加一行 c:\bootsect.lnx="LINUX" 保存,重启机子,应该能选择进哪个系统了吧。
gototop
 
gototop
 
1234   3  /  4  页   跳转
页面顶部
Powered by Discuz!NT