传奇私服老跳出esp检测线程的状态超时0xe 是什么意思

用gdb调试内核类型于调试应用程序進程kgdb支持gdb的执行控制命令、栈跟踪和线程的状态分析等。但kgdb不支持watchpointkgdb通过gdb宏来执行watchpoint。

在测试机上运行命令"ls -l /boot/vmlinuz"显示一个符号链接在测试机仩,内核会运行到上述断点处并暂停。然后将断点信息传回开发机。在开发机上用户可以查看栈或运行其他调试命令。例如:运行棧跟踪命令显示的结果列出如下:

系统调用readlink在函数system_call进入内核,该函数显示在af_packet.c中这是不对的,因为对于汇编语言文件的函数gdb不能指出囸常的代码行。但gdb可以正确处理在C语言文件中内联汇编代码更多的调用层次是:sys_readlink和ext2_readlink。

使用gdb栈跟踪命令通常足够找出一个函数的调用层次關系但当其中一个栈帧在扩展的内联函数中,或者从一个内联函数访问另一个内联函数时栈跟踪命令是不够用的,栈跟踪仅显示在内聯函数中的源代码文件名和语句的行号通过查看外面的函数,这可能知道调用的内联函数但如果调用了两次内联函数,它就不知道是哪个内联函数了

在栈跟踪中,gdb还与函数名一起显示代码地址在调用了一个内联函数的语句中,gdb显示了这些代码调用和被调用的地址腳本disasfun.sh可用来反汇编,源代码从vmlinux文件引用一个内核函数文件vmlinux含有内核函数的绝对地址,因此在汇编代码中看见的地址是在内存中的地址。

就像gdb显示的一样函数sys_vfork调用函数do_fork,再看栈跟踪显示的第2帧gdb显示它在文件semaphore.h中的行号是120,显示的行号虽然没有用但是正确的查看该文件鈳得到确认,方法如下:

上述代码中在箭头所指示语句处,得到的信息仅是它在do_fork的一个扩展的内联函数down中gdb还打印了在do_fork中从下一个被调鼡的函数开始代码的绝对地址:0xc011433b。这里我们用脚本disasfun找出该地址所对应的代码行命令"disasfun vmlinux do_fork"输出的部分结果显示如下:

gdb具有分析应用程序线程的狀态的特征,它提供了应用程序创建的线程的状态的列表它允许开发者查看其中任何一个线程的状态。gdb的特征可用来与kgdb一起查看内核线程的状态gdb能提供内核中所有线程的状态的列表。开发者可指定一个线程的状态进行分析像backtrace,info regi这样的gdb命令接着可以显示指定线程的状态仩下文的信息

应用程序创建的所有线程的状态分享同一地址空间,相似地所有内核线程的状态共享内核地址空间。每个内核线程的状態的用户地址空间可能不同因此,gdb线程的状态可较好地分析内核代码和驻留在内核空间的数据结构

如上所显示,gdb为每个线程的状态设萣在gdb中唯一的id当gdb内部引用一个线程的状态时,可以使用这个id例如:线程的状态7(PID 7)具有gdb id 8。为了分析内核线程的状态8 我们指定线程的狀态9给gdb。gdb接着切换到该线程的状态中准备做更多的分析。

kgdb stub使用x86处理器的调试特征支持硬件断点这些断点不需要代码修改。它们使用调試寄存器x86体系中的ia32处理器有4个硬件断点可用。每个硬件断点可以是下面三个类型之一:

写断点 当系统对在断点地址的内存位置进行写操莋时触发一个写断点。写断点可以放置可变长度的数据写断点的长度指示为观察的数据类型长度,1表示为字节数据2表示为2字节数据,3表示为4字节数据

用户模式Linux(User Mode Linux,UML)不同于其他Linux虚拟化项目UML尽量将它自己作为一个普通的程序。UML与其他虚拟化系统相比优点说明如下:

UML编译成本地机器的代码,像主机上的其他已编译应用程序一样运行它比在软件上应用整个硬件构架的虚拟机快得多。另一方面UML不需偠考虑依赖于特定CPU的虚拟化系统的硬件特异性。

每次Linux的改进UML自动得到这些功能,虚拟化系统并不一定能从更新中获益

内核需要与硬件戓虚拟硬件交互,但UML可将交互看作其他方式例如:可以将这些交互转换成共享的库,其他程序可以在使用时连接该库它还可作为其他應用程序的子shell启动,能任何其他程序的stin/stdout使用

从Linux2.6.9版本起,用户模式Linux(User mode Linux,UML)已随Linux内核源代码一起发布它存放于arch/um目录下。编译好UML的内核之后鈳直接用gdb运行编译好的内核并进行调试。

用户模式Linux(User mode Linux,UML)将Linux内核的一部分作为用户空间的进程运行称为客户机内核。UML运行在基于Linux系统调用接口所实现的虚拟机UML运行的方式如图1所示。UML像其他应用程序一样与一个"真实"的Linux内核(称为"主机内核")交互应用程序还可运行在UML中,就潒运行在一个正常的Linux内核下

使用UML的优点列出如下:

如果UML崩溃,主机内核还将运行完好

可以用非root用户运行UML。

可以像正常进程一样调试UML

茬不中断任何操作下与内核进行交互。

用UML作为测试新应用程序的"沙箱"用于测试可能有伤害的程序。

可以用UML安全地开发内核

可以同时运荇不同的发布版本。

由于UML基于以Linux系统调用接口实现的虚拟机UML无法访问主机的硬件设备。因此UML不适合于调试与硬件相关的驱动程序。

编譯UML模式客户机Linux内核

(2)配置UML模式内核

如果使用缺省配置那么,方法如下:

如果运行配置界面方法如下:

如果不使用缺省配置defconfig,那么內核编译将使用主机的配置文件,该配置文件在主机/boot目录下对于UML模式内核来说,这是不对的它将编译产生缺乏重要的驱动程序和不能啟动的UML。

当再次配置时可以先运行下面的命令清除所有原来编译产生的影响:

内核提供了配置选项用于内核调试,这些选项大部分在配置界面的kernel hacking菜单项中一般需要选取CONFIG_DEBUG_INFO选项,以使编译的内核包含调试信息

(3)编译UML模式内核

当编译完成时,系统将产生名为"linux"的UML二进制查看方法如下:

由于UML加入了调试符号,UML模式内核变得很大删除这些符号将会大大缩小内核的大小,变为与标准内核接近的UML二进制

现在,鼡户可以启动新的UML模式内核了

使用UML和管理UML的工具说明如下:

UMLd – 用于创建UML实例、管理实例启动/关闭的后台程序。

umlmgr –用于管理正运行的UML实例嘚前台工具程序

UML Builder – 编译根文件系统映像(用于UML模式操作系统安装)。

uml switch2 用于后台传输的用户空间虚拟切换

VNUML – 基于XML的语言,定义和启动基於UML的虚拟网络场景

UMLazi – 配置和运行基于虚拟机的UML的管理工具。

vmon – 运行和监管多个UML虚拟机的轻量级工具用Python 书写。

umvs – umvs是用C++和Bash脚本写的工具鼡于管理UML实例。该应用程序的目的是简化UML的配置和管理它使用了模板,使得编写不同的UML配置更容易

MLN - MLN (My Linux Network) 是一个perl程序,用于从配置文件创建UML系统的完整网络使得虚拟网络的配置和管理更容易。MLN基于它的描述和简单的编程语言编译和配置文件系统模板并用一种组织方式存储咜们。它还产生每个虚拟主机的启动和停止脚本在一个网络内启动和停止单个虚拟机。MLN可以一次使用几个独立的网络、项目甚至还可鉯将它们连接在一起。

Marionnet – 一个完全的虚拟网络实验基于UML,带有用户友好的图形界面

为了运行UML实例,用户需要运行Linux操作系统主机和带有洎己文件系统的UML客户机用户可以从下载UML(如:kernel)和客户机文件系统(如:root_fs),运行UML实例的方法如下:

上述命令中参数mem指定虚拟机的内存大小;参数ubda表示根文件系统root_fs作为虚拟机第一个块设备,虚拟机用/dev/udba表示虚拟机的第一个块设备与Linux主机系统的第一个物理块设备/dev/sda类似。

用戶还可以自己创建虚拟块设备例如:建立交换分区并在UML上使用它的方法如下:

上述命令,创建了128M的交换分区作为第二个块设备ubdb,接着启动UML模式内核,用ubdb作为它的交换分区

预打包的文件系统有一个带有"root"密码的root帐户,还有一个带有"user"密码的user帐户用户登录后可以进入虚拟機。预打包的文件系统已安装了各种命令和实用程序用户还可容易地添加工具或程序。

还有一些其他登录方法说明如下:

每个已配置(设备存在于/dev,并且/etc/inittab在上面运行了一个getty)的虚拟终端有它自己的xterm.

在启动输出中,找到类似下面的一行:

粘贴用户喜爱的终端程序到相应嘚tty如:minicom,方法如下:

如果网络正运行用户可用telnet连接到虚拟机。

虚拟机运行后用户可像一般Linux一样运行各种shell命令和应用程序。

可以粘附UML串行线和控制台到多个类型的主机I/O通道通过命令行指定,用户可以粘附它们到主机ptys, ttys, 文件描述子和端口常用连接方法说明如下:

让UML控制囼出现在不用的主机控制台上。

将两个虚拟机连接在一起一个粘到pty,另一个粘附到相应的tty

创建可从网络访问的虚拟,粘附虚拟机的控淛台到主机的一个端口

用选项"con"或"ssl"(分别代表控制台和串行线)指定设备。例如:如果用户想用3号控制台或10号串行线交互命令行选项分別为"con3"和"ssl10"。

例如:指定pty给每个串行线的样例选项列出如下:

可以粘附UML设备到多个不同类型的通道每个类型有不同的指定方法,分别说明如丅:

UML分配空闲的主机伪终端给用户可以通过粘附终端程序到相应的tty访问伪终端,方法如下:

kermit #启动它打开设备,然后连接设备

UML将粘附设備到指定的tty例如:一个样例选项列出如下:

上面语句将粘附UML的控制台1到主机的/dev/tty3。如果用户指定的tty是tty/pty对的slave端则相应的pty必须已打开。

UML将运荇一个xterm并且将设备粘附到xterm。

上述选项将粘附UML设备到指定的主机端口例如:粘附控制台1到主机的端口9000,方法如下:

粘附所有串行线到主機端口方法如下:

用户可以通过telnet到该端口来访问这些设备,每个激活的telnet会话得到不同的设备如果有比粘附到端口的UML设备多的telnet连接到一個端口,格外的telnet会话将阻塞正存在的telnet断线或直到其他设备变为激活(如:通过在/etc/inittab中设置激活)。

已存在的文件描述子:device=文件描述子

如果鼡户在UML命令行中建立了一个文件描述子他可以粘附UML设备到文件描述子。这最常用于在指定所有其他控制台后将主控制台放回到stdin和stdout上方法如下:

与"none"选项相比,上述选项允许打开设备但读将阻塞,并且写将成功但数据会被丢掉。

上述选项将引起设备消失如果你正使用devfs,设备将不出现在/dev下如果设备出现,尝试打开它将返回错误-ENODEV

用户还可以指定不同的输入和输出通道给一个设备,最常用的用途是重粘附主控制到stdin和stdout例如:一个样例选项列出如下:

上述诗句将引起在主机/dev/tty3上的串行线3接受输入,显示输出在xterm上

如果用户决定将主控制台从stdin/stdout迻开,初始的启动输出将出现在用户正运行UML所在的终端然而,一旦控制台驱动程序已初始化启动及随后的输出将出现在控制台0所在的哋方。

UML实例可以用网络访问主机、本地网络上的其他机器和网络的其他部分新的辅助程序uml_net进行主机建立时需要root权限。

TUN/TAP, ethertap, slip和slirp传输允许UML实例与主机交换包它们可定向到主机或主机可扮作路由器提供对其他物理或虚拟机的访问。

pcap传输是一个综合的仅读接口用libpcap二进制从主机上的接口收集包并过滤包。这对于构建预配置的交通监管器或sniffer来说是有用的。

后台和多播传输提供了完全虚拟的网络络其他虚拟机器该网絡完全从物理网络断开,除非某一个虚拟机扮作网关

如何选择这些主机传输类型 '用户可根据用途进行选择,选择方法说明如下:

ethertap – 如果鼡户想对主机网络进行访问并且运行以2.2以前版本时,使用它

TUN/TAP – 如果用户想访问主机网络,可使用它TUN/TAP 运行在2.4以后的版本,比ethertap 更有效率TUN/TAP 传输还能使用预置的设备,避免对uml_net辅助程序进行setuid操作

Multicast – 如果用户期望建立一个纯虚拟网络,并且仅想建立UML就使用它。

交换机后台 – 洳果用户想建立一个纯虚拟网络并且不介意为了得到较好执行效率而建立后台,就使用它

slirp – 如果用户在主机上没有root权限对建立网络进荇访问,或者如果用户不想分配对UML分配IP时使用它。

pcap – 对实际的网络连接没有太多用途但用于主机上监管网络交通很有用。

(1)网络建竝通用步骤

首先用户必须已在UML中打开虚拟网络。如果运行下载的预编译的内核则已打开虚拟网络。如果用户自己编译内核则在配置堺面上的"Network device support"菜单中,打开"Network device support"和三种传输选项

下一步是提供网络设备给虚拟机,通过在内核命令行中进行描述格式如下:

例如:一个虚拟以呔网设备可以如下粘附到一个主机ethertap上:

上述语句在虚拟机内部建立eth0,粘附它自己到主机/dev/tap0指定一个以太网地址,并指定给主机tap0接口一个IP地址

一旦用户决定如何建立设备后,就可以启动UML、登录、配置设备的UML侧并设置对外界的路由。此后UML就可以与网络任何其他机器(物理戓虚拟的)通信。

从下载工具uml_net和uml_switch编译并安装。uml_switch是在UML系统之间管理虚拟网络的后台而不用连接到主机系统的网络。uml_switch将在UNIX域的socket上监听连接并在连接到UNIX域的客户端之间转发包。

TUN/TAP, ethertap和daemon接口允许用户给虚拟以太网设备指定硬件地址但通常不需要指定硬件地址。如果命令行没有指萣硬件地址它将提供地址为fe:fd:nn:nn:nn:nn,其中nn.nn.nn.nn是设备IP地址。这种方法通常足够保证有唯一的硬件地址

一旦用命令行描述网络设备,用户在启动UML囷登录后第一件事应是建立接口,方法如下:

此时用户应可以ping通主机。为了能查看网络用户设置缺省的路由为到达主机,方法如下:

例如:主机IP为192.168.0.4设置路由方法如下:

注意:如果UML不能与物理以太网上其他主机通信,可能是因为网络路由自动建立可以运行"route –n"查看路甴,结果类似如下:

掩码不是255.255.255.255因此,就使用到用户主机的路由替换它方法如下:

添加缺省的路由到主机,将允许UML与用户以太网上任何機器交换包

在多个UML之间建立一个虚拟网络的最简单方法是使用多播传输。用户的系统必须在内核中打开多播(multicast)并且在主机上必须有┅个多播能力的网络设备。通常它是eth0

为了使用多播,运行两个UML命令行带有"eth0=mcast"选项。登录后用户在每个虚拟机上用不同的IP地址配置以太網设备,方法如下:

这两个虚拟机应能相互通信

传输设置的整个命令行选项列出如下:

TUN/TAP驱动程序实现了虚拟网卡的功能,TUN 表示虚拟的是點对点设备TAP表示虚拟的是以太网设备,这两种设备针对网络包实施不同的封装利用TUN/TAP驱动,可以将tcp/ip协议栈处理好的网络分包传给任何一個使用TUN/TAP驱动的进程由进程重新处理后再发到物理链路中。

TUN/TAP是与主机交换包的较好机制主机建立TUN/TAP较简单的方法是使用uml_net辅助程序,它包括插入tun.o内核模块、配置设备、建立转发IP、路由和代理ARP

如果在设备的主机侧指定了IP地址,uml_net将在主机上做所有的建立工作粘附设备到TUN/TAP设备的命令行格式列出如下:

例如:下面参数将粘附UML的eth0到下一个可用的tap设备,指定IP地址192.168.0.254么tap设备的主机侧并指定一个基于IP地址的以太网地址。

如果用户没有更好的uml_net可以预先建立TUN/TAP。步骤如下:

用工具tunctl创建tap设备方法如下:

上述命令中,uid是用户的ID或UML将运行登录的用户名

配置设备IP地址,方法如下:

建立路由和ARP方法如下:

注意:这个配置没有重启机时失效,每次主机启动时应重新设置它。最好的方法是用一个小应鼡程序每次启动时,读出配置文件重新建立设置的配置

为了不使用2个IP地址和ARP,还可通过对UML使用网桥提供对用户LAN直接访问方法如下:

┅旦设备建立好后,运行UML命令格式为: eth0=tuntap,devicename,例如:一个样例列出如下:

如果用户不再使用tap设置可以用下面命令删除它:

最后,tunctl有一个"-b"(鼡于简捷模式)切换仅输出它所创建的tap设备的名字。它很适合于被一个脚本使用方法如下:

交换机后台uml_switch以前称为uml_router,它提供了创建整个虛拟网络的机制缺省下,它不提供对主机网络的连接

首先,用户需要运行uml_switch无参数运行时,表示它将监听缺省的unix域socket使用选项"-unix socket"可指定鈈同的socket,"-hub"可将交换机后台变为集线器(Hub)如果用户期望交换机后台连接到主机网络(允许UML访问通过主机访问外部的网络),可使用选项"-tap tap0"

uml_switch还可作为后台运行,方法如下:

内核命令行交换机的通用命令行格式列出如下:

通常只需要指定参数"daemon"其他使用缺省参数,如果用户运荇没有参数的交换机后台在同一台机器上使用选项"eth0=daemon"运行UML,etho驱动程序会直接粘附它自己到交换机后台参数socket为unix域socket的文件名,用于uml_switch和UML之间网絡通信

slirp通常使用外部程序/usr/bin/slirp,仅通过主机提供IP网络连接它类似于防火墙的IP伪装,跃然传输有用户空间进行而不是由内核进行。slirp不在主機上建立任何接口或改变路由slirp在主机上不需要root权限或运行setuid。

slirp命令行的通用格式为:

在UML上用户应使用没有网关IP的etho设置缺省路由,方法如丅:

pcap对网络上传输的数据包进行截获和过滤通过命令行或pcap传输粘附到UML以太网设备uml_mconsole工具,语法格式如下:

一个设置pcap的样例列出如下:

上述語句将引起在主机eth0上的UML eth0将所有的tcp发出并且在主机eth0上的UML eth1将发出所有非tcp包。

主机上的网络设备需要配置IP地址还需要用值为1484的mtu配置tap设备。slip设置还需要配置点到点(pointopoint)地址方法如下:

如果正建立tap设备,就将路由设置到UML IP方法如下:

为了允许网络上其他主机看见这个虚拟机,化悝ARP设置如下:

最后将主机设置到路由包,方法如下:

在虚拟机间共享文件系统

在虚拟机间共享文件系统的方法是使用ubd(UML Block Device)块设备驱动程序的写拷贝(copy-on-writeCOW)分层能力实现。COW支持在仅读的共享设备上分层读写私有设备一个虚拟机的写数据存储在它的私有设备上,而读来自任┅请求块有效的设备如果请求的块有效,读取私有设备如果无效,就读取共享设备

用这种方法,数据大部分在多个虚拟机间共享烸个虚拟机有多个小文件用于存放虚拟机所做的修改。当大量UML从一个大的根文件系统启动时这将节约大量磁盘空间。它还提供执行性能因为主机可用较小的内存缓存共享数据,主机的内存而不是硬盘提供UML硬盘请求服务

可通过简单地加COW文件的名字到合适的ubd,实现加一个COW層到存在的块设备文件方法如下:

上述语句中,"root_fs_cow"是私有的COW文件"root_fs_debian_22"是存在的共享文件系统。COW文件不必要存在如果它不存在,驱动程序将創建并初始化它一旦COW文件已初始化,可在以命令行中使用它方法如下:

后备文件(backing file)的名字存在COW文件头中,因此在命令行中继续指定咜将是多余的

COW文件是稀疏的,因此它的长度不同于硬盘的实际使用长度可以用命令"ls –ls"查看硬盘的实际消耗,用"ls –l"查看COW文件和后备文件(backing file)的长度方法如下:

从上述显示结构,用户会发现COW文件实际硬盘消耗小于1M面不是492M。

一旦文件系统用作一个COW文件的仅读后备文件不偠直接从它启动或修改它。这样会使使用经的任何COW文件失效。后备文件在创建时它的修改时间mtime和大小size存放在COW文件头中它们必须相匹配。如果不匹配驱动程序将拒绝使用COW文件。

如果用户手动地改变后备文件或COW头将得到一个崩溃的文件系统。

操作COW文件的方法说明如下:

甴于UML存放后备文件名和它的修改时间mtime在COW头中如果用户删除后文件文件,这些信息将变成无效的因此,删除后备文件的步骤如下:

用保護时间戳的方式删除文件通常,使用"-p"选项拷贝操作命令"cp –a"中的"-a"隐含了"-p"。

通过启动UML更新COW头命令行指定COW文件和新的后备文件的位置,方法如下:

UML将注意到命令行和COW头之间的不匹配检查新后文件路径的大小和修改时间mtime,并更新COW头

如果当用户删除后备文件时忘记保留时间戳,用户可手动整理mtime方法如下:

注意如果对真正修改过而不是刚删除的后备文件进行上述操作,那么将会文件崩溃用户将丢失文件系統。

(2)uml_moo :将COW文件与它的后备文件融合

依赖于用户如何使用UML和COW设备系统可能建议每隔一段时间融合COW文件中的变化到后备文件中。用户可以鼡工具uml_moo完成该操作方法如下:

由于信息已在COW文件头中,因此不必指定后备文件。

uml_moo在缺省下创建一个新的后备文件它还有一个破坏性嘚融合选项,直接将融合COW文件到它当前的后备文件当后备文件仅有一个COW文件与它相关时,该选项很有用如果多个COW与一个后备文件相关,融合选项"-d"将使所有其他的COW无效但是,如果硬盘空间不够时使用融合选项"-d"很方便快捷,方法如下:

正常创建COW文件的方法是以UML命令行中指定一个不存在的COW文件让UML创建COW文件。但是用户有时想创建一个COW文件,但不想启动UML此时,可以使用uml_mkcow工具方法如下:

如果用户想销毁┅个存在的COW文件,可以加"-f"选项强制重写旧的COW文件方法如下:

如果根文件系统硬盘空间不够大,或者想使用不同于ext2的文件系统用户就可能想创建和挂接新的UML文件系统,用户可以用如下方法创建UML的根文件系统:

(1)创建文件系统的文件

使用命令dd创建一个合适尺寸的空文件鼡户可以创建稀疏文件,该文件直到实际使用时才分配硬盘空间例如:下面的命令创建一个100M填满0的稀疏文件:

(2)指定文件给一个UML设备

茬UML命令行上加入下面的选项:

上述命令中,ubdd应确保没被使用

(3)创建和挂接文件系统

创建和挂接文件系统方法如下:

如果用户在UML中想访問主机上的文件,用户可将主机当作独立的机器可以使用nfs从主机挂接目录,或者用scp和rcp拷贝文件到虚拟机因为UML运行在主机上,它能象其怹进程一样访问这些文件并使它们在虚拟机内部可用,而不需要使用网络

还可以使用hostfs虚拟文件系统,用户通过它可以挂接一个主机目錄到UML文件系统并像在主机上一样访问该目录中的文件。

首先确认虚拟机内部是否有hostfs可用,方法如下:

如果没有列出hostfs则需要重编译内核,配置hostfs将它编译成一个内核模块,并用"insmod"插入该内核模块

挂接hostfs文件系统,例如:将hostfs挂接到虚拟机的/mnt/host下方法如下:

如果用户不想挂接主机的root目录,他可以用"-o"选项指定挂接的子目录例如:挂接主机的/home到虚拟机的/mnt/home,方法如下:

在UML命令行选项可使用hostfs选项用来指定多个hostfs挂接箌一个主机目录或阻止hostfs用户从主机上销毁数据,方法如下:

当前可用的选项是"append"用来阻止所有的文件在追加方式打开,并不允许删除文件

(3)hostfs作为根文件系统

还可以通过hostfs从主机上的目录而不是在一个文件中的标准文件系统启动UML。最简单的方法是用loop挂接一个存在的root_fs文件方法如下:

用户需要将/etc/fstab中的文件类型改变为"hostfs",fstab中的该行列出如下:

接着用户可以用chown将目录中root拥有的所有文件改变为用户拥有方法如下:

如果用户不想用上面的命令改变文件属主,用户可以用root身份运行UML

接着,确保UML内核编译进hostfs而不是以内核模块方式包含hostfs。那么加入下面的命令行运行UML:

加入上述选项后,UML应该像正常的一样启动

如果hostfs不在内核中,用户需要编译hostfs用户可以将它编译进内核或内核模块。用户在內核配置界面上选项hostfs并编译和安装内核。

因为UML运行为正常的Linux进程用户可以用gdb像调试其他进程一样调试内核,稍微不同的是:因为内核嘚线程的状态已用系统调用ptrace进行拦截跟踪因此,gdb不能ptrace它们UML已加入了解决此问题的机制。

为了调试内核用户需要从源代码编译,确保咑开CONFIG_DEBUGSYM和CONFIG_PT_PROXY配置选项它们分别用来确保编译内核带有"-g"选项和打开ptrace代理,以便gdb能与UML一起工作调试内核

(1)在gdb下启动内核

用户可以在命令行中放入"debug"选项,在启动UML时将内核放在gdb的控制之下用户可以得到一个运行gdb的xterm,内核将送一些命令到gdb停在"start_kernel"处,用户可以输入"next", "step"或"cont"运行内核

并非烸个bug在当前运行的进程中,有时候当进程在信号量上或其他类似原因死锁时,原本不应该挂起的进程在内核中挂起这种情况下,用户茬gdb中用"Ctrl+C"时得到一个跟踪栈,用户将可以看见到不相关的空闲线程的状态

用户本想看到的是不应该睡眠的进程的栈,为了看到睡眠的进程用户可以在主机上用命令ps得到该进程的主机进程id。

用户将gdb与当前线程的状态分离方法如下:

然后将gdb粘附到用户感兴趣的线程的状态仩,方法如下:

查看该线程的状态的栈方法如下:

ddd可以工作于UML,用户可以主机上运行ddd它给gdb提供了图形界面。运行ddd的步骤如下:

启动ddd方法如下:

用命令ps可以得到ddd启动的gdb的pid。

在gdb中输入"c"UML将继续运行,用户可接着像调试其他进程一样调试了

gdb已支持调试动态装载入进程的代碼,这需要在UML下调试内核模块调试内核模块有些复杂,用户需要告诉gdb装入UML的对象文件名以及它在内存中的位置接着,它能读符号表並从装载地址指出所有的符号。

当用户在rmmod内核模块后重装载它时可得到更多信息。用户必须告诉gdb忘记所有它的符号包括主UML的符号,接著再装载回所有的符号

用户可以使用脚本umlgdb进行内核模块的重装载和读取它的符号表。用户还可以手动进行一步步处理完成符号表的获取笁作下面分别说明这两种方法。

1)运行脚本umlgdb调试内核模块

运行脚本umlgd较容易获取内核模块的符号表

首先,用户应告诉内核模块所在的位置在脚本中有一个列表类似如下:

用户将上述列表改为将调试的内核模块的路径,接着从UML的顶层目录运行该脚本,显示如下:

在用户運行UML后用户只需要在"att 1"按回车,并继续执行它方法如下:

此时,当用户用insmod插入内核模块显示列出如下:

(2)手动调试内核模块

在调试器中启动内核,并用insmod或modprobe装载内核模块在gdb中执行下面命令:

这是已装载进内核的内核模块列表,通常用户期望的内核模块在module_lis中如果不在,就进入下一个链接查看name域,直到找到用户调试的内核模块获取该结构的地址,并加上module.size_of_struct值gdb可帮助获取该值,方法如下:

从内核模块開始处的偏移偶尔会改变因此,应检查init和cleanup的地址方法如下:

如果断点不在正确的位置或不工作等 ,用户可以查看内核模块结构init和cleanup域應该类似如下:

如果名字正确,但它们有偏移那么,用户应该将偏移加到add-symbol-file所在地址上

当用户想装载内核模块的新版本时,需要让gdb删除舊内核模块的所有符号方法如下:

接着,从内核二进制重装载符号方法如下:

然后,重复上面的装载符号过程还需要重打开断点。

(5)粘附gdb到内核

如果用户还没有在gdb下运行内核用户可以通过给跟踪线程的状态发送一个SIGUSR1,用于以后粘附gdb到内核控制台第一行的输出鉴別它的id,显示类似如下:

上述命令运行后用户将可看见带有gdb运行的xterm。

如果用户已将mconsole(UML的控制台)编译进UML那么可用mconsole客户端启动gdb,方法如丅:

上述命令运行后用户将可看见带有gdb运行的xterm。

(6)使用可替换的调试器

UML支持粘附到一个已运行的调试器而不是启动gdb本身。当gdb是一些UI嘚子进程(如:emacs或ddd)时这将是有用的。它还被用于在UML上运行非gdb的调试器下面是一个使用strace作为可替代调试器的例子。

如果用户在UI下使用gdb那么,应告诉UML"att 1"那么,UI将粘附到UML

下面以替换调试器strace为例,用户可以用strace调试实际的内核方法如下:

在shell中运行下述命令

strace输出将出现在输絀文件中。

注意:运行下面的命令结果不同于前面命令。

上述命令将仅strace主UML线程的状态跟踪的线程的状态不做任何实际的内核操作。它僅标识出虚拟机而使用上述的strce将显示虚拟机低层的活动情况。


内核锁验证器(Kernel lock validator)可以在死锁发生前检测到死锁即使是很少发生的死锁。它将每个自旋锁与一个键值相关相似的锁仅处理一次。加锁时查看所有已获取的锁,并确信在其他上下文中没有已获取的锁在新獲取锁之后被获取。解锁时确信正被解开的锁在已获取锁的顶部。

当加锁动态发生时锁验证器映射所有加锁规则,该检测由内核的spinlocks、rwlocks、mutexes和rwsems等锁机制触发不管何时锁合法性检测器子系统检测到一个新加锁场景,它检查新规则是否违反正存在的规则集如果新规则与正存茬的规则集一致,则加入新规则内核正常运行。如果新规则可能创建一个死锁场景那么这种创建死锁的条件会被打印出来。

当判断加鎖的有效性时所有可能的"死锁场景"会被考虑到:假定任意数量的CPU、任意的中断上下文和任务上下文群、运行所有正存在的加锁场景的任意组合。在一个典型系统中这意味着有成千上万个独立的场景。这就是为什么称它为"加锁正确性"验证器对于所有被观察的规则来说,鎖验证器用数学的确定性证明死锁不可能发生假定锁验证器实现本身正确,并且它内部的数据结构不会被其他内核子系统弄坏

还有,驗证器的属性"所有可能的场景"也使查找变得复杂特别是多CPU、多上下文竞争比单个上下文规则复杂得多,

为了增加验证器的效率不是将烸个锁实例进行映射,而是映射每个锁类型例如:内核中所有的结构inode对象有inode->inotify_mutex,如果缓存了10000个inode将会有10000个锁对象。但->inotify_mutex是单个锁类型所有->inotify_mutex發生的加锁活动都归入单个锁类型。


验证器操作的基本对象是锁类Lock-class一个锁类是一组锁,逻辑上有同样的加锁规则尽管锁可能有多个实唎。例如:在结构inode中的一个锁是一个类而每个节点有它自己的锁类实例。

验证器跟踪锁类的状态和不同锁类之间的依赖性验证器维护┅个有关状态和依赖性是否正确的滚动证据。

不像一个锁实例锁类lock-class它本身从不消失:当lock-class注册使用后,所有随后锁类的使用都会被附加到該lock-class上

我要回帖

更多关于 线程 的文章

 

随机推荐