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

全部博文(554)

文章存档

2012年(1)

2011年(1)

2009年(8)

2008年(544)

分类:

2008-04-11 15:14:44


设备属性
第4 章• 属性73
尽可能使用64 位版本的int 属性接口(如ddi_prop_update_int64(9F)),而不要使用32 位
版本(如ddi_prop_update_int(9F))。
prop_op() 入口点
向系统报告设备属性或驱动程序属性通常需要使用prop_op(9E) 入口点。如果驱动程序无需
创建或管理其自己的属性,则ddi_prop_op(9F) 函数可用于此入口点。
如果在驱动程序的cb_ops(9S) 结构中定义了ddi_prop_op(),则ddi_prop_op(9F) 可用作设备
驱动程序的prop_op(9E) 入口点。ddi_prop_op() 使叶设备可在设备的属性列表中搜索并获
取属性值。
如果驱动程序需要维护其值经常更改的属性,则应在cb_ops 结构中定义特定于驱动程序的
prop_op() 例程,而不是调用ddi_prop_op()。此方法可有效避免由于重复使用
ddi_prop_update() 而造成的效率低下。然后,驱动程序应在其软状态结构或驱动程序变量
中维护属性值的副本。
prop_op(9E) 入口点向系统报告特定驱动程序属性的值和设备属性的值。在许多情况
下,ddi_prop_op(9F) 例程在cb_ops(9S) 结构中可用作驱动程序的prop_op() 入口点。
ddi_prop_op() 会执行所有必需的处理过程。对于处理设备属性请求时不需要进行特殊处理
的驱动程序,ddi_prop_op() 即可满足要求。
但是,有时驱动程序必须提供prop_op() 入口点。例如,如果驱动程序维护其值经常更改的
属性,则针对每次更改使用ddi_prop_update(9F) 更新属性便不能满足要求。相反,驱动程
序应在实例的软状态下维护属性的阴影副本。然后,驱动程序可在值发生变化时更新阴影
副本,而无需使用任何ddi_prop_update() 例程。prop_op() 入口点必须拦截此属性的请
求,并使用ddi_prop_update() 例程之一更新属性的值,然后将请求传递到ddi_prop_op()
以处理属性请求。
在以下示例中,prop_op() 拦截temperature 属性的请求。属性发生变化时,驱动程序将更
新状态结构中的变量。但是,仅当发出请求时才会更新该属性。然后,驱动程序使用
ddi_prop_op() 处理该属性请求。如果属性请求不特定于某个设备,则驱动程序不会拦截该
请求。dev 参数的值等于DDI_DEV_T_ANY(通配符设备编号)时即是这种情况。
示例4–1 prop_op() 例程
static int
xx_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
int flags, char *name, caddr_t valuep, int *lengthp)
{
minor_t instance;
struct xxstate *xsp;
设备属性
74 编写设备驱动程序• 2006 年11 月
示例4–1 prop_op() 例程(续)
if (dev != DDI_DEV_T_ANY) {
return (ddi_prop_op(dev, dip, prop_op, flags, name,
valuep, lengthp));
}
instance = getminor(dev);
xsp = ddi_get_soft_state(statep, instance);
if (xsp == NULL)
return (DDI_PROP_NOTFOUND);
if (strcmp(name, "temperature") == 0) {
ddi_prop_update_int(dev, dip, name, temperature);
}
/* other cases */
}
设备属性
第4 章• 属性75
76
事件
系统经常需要对用户操作或系统请求之类的条件更改做出响应。例如,设备可能会在某个
组件开始过热时发出警告,或者可能在将DVD 插入驱动器后启动影片播放机。设备驱动程
序可以使用称为事件的特殊消息来通知系统发生了状态更改。本章提供以下有关事件的信
息:
 第77 页中的“事件介绍”
 第78 页中的“使用ddi_log_sysevent() 记录事件”
 第80 页中的“定义事件特性”
事件介绍
事件是指设备驱动程序向相关实体发送的消息,用以指示发生了状态更改。在Solaris OS
中,事件以用户定义的名称-值对结构的形式实现,这些结构使用nvlist* 函数进行管理。
(请参见nvlist_alloc(9F) 手册页。)事件由供应商、类以及子类组成。例如,可以定义
一个类用于监视环境条件。环境类可以具有子类,用来指示温度、风扇状态以及电源方面
的变化。
发生状态更改时,设备将通知驱动程序。驱动程序随后将使用ddi_log_sysevent(9F) 函数在
称为sysevent 的队列中记录此事件。sysevent 队列会将事件传递到用户级,以便通过
syseventd 守护进程或syseventconfd 守护进程进行处理。这些守护进程会将通知发送到订
阅了指定事件通知的所有应用程序。
用户级应用程序的设计者可以使用以下两种方法处理事件:
 应用程序可以使用libsysevent(3LIB) 中的例程向syseventd 守护进程订阅发生指定事件
时的通知。
 开发者可以编写单独的用户级应用程序来响应事件。此类型应用程序需要通过
syseventadm(1M) 进行注册。syseventconfd 遇到指定事件时,应用程序会根据实际情况
运行并处理此事件。
下图对此流程进行了说明。
5第5 章
77
图5–1事件检测
使用ddi_log_sysevent() 记录事件
设备驱动程序使用ddi_log_sysevent(9F) 接口生成和记录系统事件。
ddi_log_sysevent() 语法
ddi_log_sysevent() 使用以下语法:
int ddi_log_sysevent(dev_info_t *dip, char *vendor, char *class,
char *subclass, nvlist_t *attr-list, sysevent_id_t *eidp, int sleep-flag);
其中:
dip 指向相应驱动程序处理的dev_info 节点的指针。
vendor 指向定义驱动程序供应商的字符串的指针。第三方驱动程序应使用其公司的股
票代号或类似的持久标识符。Sun 提供的驱动程序会使用DDI_VENDOR_SUNW。
使用ddi_log_sysevent() 记录事件
78 编写设备驱动程序• 2006 年11 月
class 指向定义事件类的字符串的指针。class 是特定于驱动程序的值。表示影响设备
的一组环境条件的字符串可能即是一个类的示例。事件消费方必须能够理解该
值。
subclass 表示class 参数子集的特定于驱动程序的字符串。例如,在表示环境条件的类
中,事件子类可能是指设备的温度。事件消费方必须能够理解该值。
attr-list 指向列出与事件关联的名称-值特性的nvlist_t 结构的指针。名称-值特性是驱
动程序定义的,可以是指设备的特定特性或条件。
例如,可同时读取CD-ROM 和DVD 的设备。此设备可能具有一个名称为
disc_type 并且值等于cd_rom 或dvd 的特性。
与class 和subclass 一样,事件消费方必须能够解释名称-值对。
有关名称-值对以及nvlist_t 结构的更多信息,请参见第80 页中的“定义事
件特性” 以及nvlist_alloc(9F) 手册页。
如果事件没有任何特性,则此参数应设置为NULL。
eidp sysevent_id_t 结构的地址。sysevent_id_t 结构用于提供事件的唯一标
识。ddi_log_sysevent(9F) 将向此结构返回系统提供的事件序列号和时间标
记。有关sysevent_id_t 结构的更多信息,请参见ddi_log_sysevent(9F) 手册
页。
sleep-flag 指示资源不可用时调用者如何响应的标志。如果sleep-flag 设置为DDI_SLEEP,
则驱动程序会阻塞,直到资源可用为止。如果设置为DDI_SLEEP,则分配可能
会休眠,但是保证会成功。DDI_NOSLEEP 分配保证不会休眠,但是可能会在当
前无可用内存时返回NULL。
记录事件的样例代码
设备驱动程序可执行以下任务来记录事件:
 使用nvlist_alloc(9F) 为特性列表分配内存
 向特性列表添加名称-值对
 使用ddi_log_sysevent(9F) 函数在sysevent 队列中记录事件
 不再需要特性列表时调用nvlist_free(9F)
以下示例说明如何使用ddi_log_sysevent()。
示例5–1 调用ddi_log_sysevent()
char *vendor_name = "DDI_VENDOR_JGJG"
char *my_class = "JGJG_event";
char *my_subclass = "JGJG_alert";
使用ddi_log_sysevent() 记录事件
 

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