Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1299858
  • 博文数量: 554
  • 博客积分: 10425
  • 博客等级: 上将
  • 技术积分: 7555
  • 用 户 组: 普通用户
  • 注册时间: 2006-11-09 09:49
文章分类

全部博文(554)

文章存档

2012年(1)

2011年(1)

2009年(8)

2008年(544)

分类:

2008-04-15 11:46:11


13 • 使用DTrace 调试驱动程序111
/usr/src/uts/common/os/modsubr.c 中find_mbind() 的源代码发现我们搜
索的是一个散列表中的char 字符串。下面使用DTrace 显示搜索字符串和
散列表中的内容。
为了查看搜索字符串的内容,将strcmp() 跟踪函数添加到前面的
mod_getsysnum.d 脚本中:
fbt::strcmp:entry
{
printf("name:%s, hash:%s", stringof(arg0),
stringof(arg1));
}
下面是接下来尝试载入驱动程序的结果:
# ./mod_getsysnum.d
dtrace: script ’./mod_getsysnum.d’ matched 35751 probes
CPU FUNCTION
0 -> mod_getsysnum
0 -> find_mbind
0 -> nm_hash
0 <- nm_hash 41
0 -> strcmp
0 | strcmp:entry name:smbfs,
hash:timer_getoverrun
0 <- strcmp 4294967295
0 -> strcmp
0 | strcmp:entry name:smbfs,
hash:lwp_sema_post
0 <- strcmp 7
0 <- find_mbind 0
0 <- mod_getsysnum 4294967295
我们在散列表中查找smbfs,但没有找到。smbfs 如何进入该散列表中呢?
回去看find_mbind(),发现散列表变量sb_hashtab 是传递给失败的
nm_hash() 函数的。
快速查看源代码发现对sb_hashtab 的初始化是通过调用
read_binding_file() 实现的,该函数将config 文件、散列表及函数指针
作为其参数。在源代码浏览器中继续往下查看发现在文件
/usr/src/uts/common/os/modctl.c 中config 文件的内容定义为
/etc/name_to_sysnum。看来是忘了纳入与驱动程序对应的配置项。将以下
内容添加到/etc/name_to_sysnum 文件中,然后重新引导。
将smbfs 驱动程序从Linux 移植到Solaris OS
112 操作系统介绍:OpenSolaris 项目简明使用手册• 2006 年12 月
’smbfs 177’
(read_binding_file() is read once at boot time.)
重新引导之后,就可以成功装入驱动程序。
# modload /usr/kernel/fs/smbfs
使用modinfo 命令验证是否已装入驱动程序:
# modinfo | grep smbfs
160 feb21a58 351ac 177 1 smbfs (SMBFS syscall,client,comm)
160 feb21a58 351ac 24 1 smbfs (network filesystem)
160 feb21a58 351ac 25 1 smbfs (network filesystem version 2)
160 feb21a58 351ac 26 1 smbfs (network filesystem version 3)
注– 请注意,该驱动程序是采用nfs 模板创建而成的,因此输出是以上所
示。
下面来确定是否也可以卸载该模块:
# modunload -i 160
can’t unload the module: Device busy
这很可能是由于EBUSY errno 返回值造成的。不过现在既然已装入smbfs
驱动程序模块,我们可以访问所有的smbfs 函数:
# dtrace -l fbt:smbfs:: | wc -l
1002
太妙了!无需任何特殊编码,现在即可访问1002 条目,并返回驱动程序
中包含的事件。利用这些1002 函数句柄可以进行调试工作,而无需使用
特殊的“已调试代码”版本的驱动程序。我们可使用下列简单DTrace 脚
本监视调用modunload 时发生的所有smbfs 调用:
#!/usr/sbin/dtrace -s
#pragma D option flowindent
fbt:smbfs::entry
{
}
将smbfs 驱动程序从Linux 移植到Solaris OS
13 • 使用DTrace 调试驱动程序113
fbt:smbfs::return
{
trace(arg1);
}
可以看出modunload 并未访问smbfs 代码。因此,采用以下脚本使用
DTrace 跟踪modunload:
#!/usr/sbin/dtrace -s
#pragma D option flowindent
fbt::modunload:entry
{
self->follow = 1;
trace(execname);
trace(arg0);
}
fbt::modunload:return
{
self->follow = 0;
trace(arg1);
}
fbt:::entry
/self->follow/
{
}
fbt:::return
/self->follow/
{
trace(arg1);
}
下面是该脚本的输出:
# ./modunload.d
dtrace: script ’./modunload.d’ matched 36695 probes
CPU FUNCTION
0 -> modunload modunload 160
0 | modunload:entry
0 -> mod_hold_by_id
将smbfs 驱动程序从Linux 移植到Solaris OS
114 操作系统介绍:OpenSolaris 项目简明使用手册• 2006 年12 月
0 -> mod_circdep
0 <- mod_circdep 0
0 -> mod_hold_by_modctl
0 <- mod_hold_by_modctl 0
0 <- mod_hold_by_id 3602566648
0 -> moduninstall
0 <- moduninstall 16
0 -> mod_release_mod
0 -> mod_release
0 <- mod_release 3602566648
0 <- mod_release_mod 3602566648
0 <- modunload 16
发现EBUSY 返回值"16" 来自moduninstall。下面来看看moduninstall 的源
代码。moduninstall 在多个位置返回EBUSY,现在看看下列几种可能情况

1. if (mp->mod_prim || mp->mod_ref || mp->mod_nenabled != 0) return
(EBUSY);
2. if ( detach_driver(mp->mod_modname) != 0 ) return (EBUSY);
3. if ( kobj_lookup(mp->mod_mp, "_fini") == NULL )
4. A failed call to smbfs _fini() routine
我们无法直接了解到所有这些可能情况,但可以通过排除法来逐步确定。
下面使用以下脚本显示各种结构的内容以及返回moduninstall 中的值:
#!/usr/sbin/dtrace -s
#pragma D option flowindent
fbt::moduninstall:entry
{
self->follow = 1;
printf("mod_prim:%d\n",
((struct modctl *)arg0)->mod_prim);
printf("mod_ref:%d\n",
((struct modctl *)arg0)->mod_ref);
printf("mod_nenabled:%d\n",
((struct modctl *)arg0)->mod_nenabled);
printf("mod_loadflags:%d\n",
((struct modctl *)arg0)->mod_loadflags);
}
将smbfs 驱动程序从Linux 移植到Solaris OS
13 • 使用DTrace 调试驱动程序115
fbt::moduninstall:return
{
self->follow = 0;
trace(arg1);
}
fbt::kobj_lookup:entry
/self->follow/
{
}
fbt::kobj_lookup:return
/self->follow/
{
trace(arg1);
}
fbt::detach_driver:entry
/self->follow/
{
}
fbt::detach_driver:return
/self->follow/
{
trace(arg1);
}
运行该脚本生成的输出如下:
# ./moduninstall.d
dtrace: script ’./moduninstall.d’ matched 6 probes
CPU FUNCTION
0 -> moduninstall
mod_prim:0
mod_ref:0
mod_nenabled:0
mod_loadflags:1
0 -> detach_driver
0 <- detach_driver 0
0 -> kobj_lookup
0 <- kobj_lookup 4273103456
0 <- moduninstall 16
将smbfs 驱动程序从Linux 移植到Solaris OS
116 操作系统介绍:OpenSolaris 项目简明使用手册• 2006 年12 月
将此输出与代码对照可以得知,失败不是由于mp 结构值造成,也不是由
kobj_lookup() 的detach_driver() 返回值造成。进行排除后,由此断定是
执行status = (*func)(); 调用(它将调用smbfs _fini() 例程)返回的状
态造成。下面是smbfs _fini() 例程中的内容:
int _fini(void)
{
/* don’t allow module to be unloaded */
return (EBUSY);
}
将该返回值更改为"0" 并重新编译代码后,就可以装入和卸载驱动程序,
这样就达到了此练习的目标。至此,我们已在这些示例中专门使用了函数
边界跟踪提供程序。请注意,fbt 只是众多的DTrace 提供程序之一。
将smbfs 驱动程序从Linux 移植到Solaris OS
13 • 使用DTrace 调试驱动程序117
118
使用DTrace 观察区域中的进程
目的
本章旨在利用掌握的DTrace 知识观察区域中运行的进程。
14 1 4
119
其他资源
■ 《系统管理指南:Solaris Containers-资源管理和Solaris Zones》,Sun
Microsystems, Inc.,2005
■ 《Solaris Containers-ResourceManagement and Solaris ZonesDeveloper
Guide》,SunMicrosystems, Inc.,2005
使用DTrace 观察区域中的进程
120 操作系统介绍:OpenSolaris 项目简明使用手册• 2006 年12 月
全局区域和非全局区域
现在我们已掌握了一些调试应用程序的知识,下面来调试区域中运行的应
用程序。
每个OpenSolaris 系统都包含一个全局区域。全局区域具有双重功能。全
局区域既是系统的缺省区域,也是用于在系统范围内进行管理控制的区
域。
非全局区域根文件系统模型的类型有两种:稀疏根和完全根。稀疏根区域
模型用于优化对象共享。完全根区域模型用于提供最大的文件系统配置能
力。
非全局区域的调度类设置为系统的调度类。您还可以使用动态资源池功能
为区域设置调度类。如果将区域与pool.scheduler 属性设置为某一有效调
度类的池关联,则缺省情况下该区域中运行的进程会以此调度类运行。
多个区域可以共享一个资源池,或者为了能够保证服务,也可以将一个区
域绑定到某个特定的池。缺省情况下,所有区域(包括全局区域在内)均
占用分配给它们的一份(1) 公平份额调度器份额。区域占用的CPU 百分比
是其所占份额数与绑定到特定资源池的所有区域的总份额数的比例。
全局管理员使用zonecfg 命令通过为区域的虚拟平台和应用程序环境指定
各种参数来配置区域。然后由全局管理员安装区域,即使用管理命令
zoneadm 将软件包中的软件安装到为区域建立的文件系统分层结构中。全
局管理员可以使用zlogin 命令登录到已安装的区域。首次登录时,会完
成区域的内部配置。之后使用zoneadm 命令引导区域。
 
 

以上文章转自于 : http://developers.sun.com.cn/
阅读(826) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~