编写设备驱动程序

对请求进行排队

与同步数据传输不同,驱动程序不等待异步请求完成,而是向队列中添加请求。队列的开头可以是当前传输,也可以是保留活动请求的状态结构中的独立字段,如示例 16–5 中所示。

如果队列开始是空的,那么硬件不忙,并且 strategy(9E) 在返回之前开始传输。否则,如果在队列非空的情况下完成一个传输,则中断例程会开始一个新的传输。为方便起见,示例 16–5 仅在一个单独的例程中决定是否开始新的传输。

驱动程序可以使用 buf(9S) 结构中的 av_forwav_back 成员来管理传输请求列表。可以使用单个指针管理单链接表,也可以同时使用两个指针建立双链接表。设备硬件规格指定哪种类型的列表管理(如插入策略)用于优化设备的性能。传输列表是按设备提供的列表,因此列表的头和尾都存储在状态结构中。

以下示例提供了对驱动程序共享数据(如传输列表)有访问权限的多个线程。您必须标识共享数据,并且必须用互斥锁保护这些数据。有关互斥锁的更多详细信息,请参见第 3 章


示例 16–5 对块驱动程序的数据传输请求进行排队

static int
xxstrategy(struct buf *bp)
{
    struct xxstate *xsp;
    minor_t instance;
    instance = getminor(bp->b_edev);
    xsp = ddi_get_soft_state(statep, instance);
    /* ... */
    /* validate transfer request */
    /* ... */
    /*
     * Add the request to the end of the queue. Depending on the device, a sorting
     * algorithm, such as disksort(9F) can be used if it improves the
     * performance of the device.
     */
    mutex_enter(&xsp->mu);
    bp->av_forw = NULL;
    if (xsp->list_head) {
       /* Non-empty transfer list */
       xsp->list_tail->av_forw = bp;
       xsp->list_tail = bp;
    } else {
       /* Empty Transfer list */
       xsp->list_head = bp;
       xsp->list_tail = bp;
    }
    mutex_exit(&xsp->mu);
    /* Start the transfer if possible */
    (void) xxstart((caddr_t)xsp);
    return (0);
}