A    STREAMS モジュール例

spass モジュールは,プットされたすべてのメッセージを putnext() プロシージャに引き渡す,簡単な STREAMS モジュールです。 spass モジュールは,サービス・プロシージャが処理するために,putnext() に対する呼び出しを遅延させます。 このモジュールには,フロー制御コードが組み込まれており,読み取り側および書き込み側の両方が,1 つのサービス・プロシージャを共用しています。

spass モジュールのコードは,次のとおりです。


#include <sys/stream.h>
#include <sys/stropts.h>
#include <sys/sysconfig.h>
 
static  int     spass_close();
static  int     spass_open();
static  int     spass_rput();
static  int     spass_srv();
static  int     spass_wput();
 
static struct module_info minfo =  {
        0, "spass", 0, INFPSZ, 2048, 128
};
 
static struct qinit rinit = {
        spass_rput, spass_srv, spass_open, spass_close, NULL, &minfo
};
 
static struct qinit winit = {
        spass_wput, spass_srv, NULL, NULL, NULL, &minfo
};
 
struct streamtab spassinfo = { &rinit, &winit };
 
cfg_subsys_attr_t bufcall_attributes[]  = {
    {, 0, 0, 0, 0, 0, 0}    /* must be the last element */
};
 
int
spass_configure(op, indata, indata_size, outdata, outdata_size)
        cfg_op_t        op;
        caddr_t         indata;
        ulong           indata_size;
        caddr_t         outdata;
        ulong           outdata_size;
{
     struct streamadm        sa;
     dev_t                   devno = NODEV;
 
     if (op != CFG_OP_CONFIGURE)
             return EINVAL;
 
        sa.sa_version           = OSF_STREAMS_10;
        sa.sa_flags             = STR_IS_MODULE | STR_SYSV4_OPEN;
        sa.sa_ttys              = 0;
        sa.sa_sync_level        = SQLVL_QUEUE;
        sa.sa_sync_info         = 0;
        strcpy(sa.sa_name,      "spass");
        if ( (devno = strmod_add(devno, &spassinfo, &sa)) == NODEV ) {
                return ENODEV;
	}
 
        return 0;
}
 
/* Called when module is popped or the Stream is closed */
static int
spass_close (q, credp)
        queue_t * q;
        cred_t * credp;
{
        return 0;
}
 
/* Called when module is pushed */
static int
spass_open (q, devp, flag, sflag, credp)
        queue_t * q;
        int     * devp;
        int     flag;
        int     sflag;
        cred_t * credp;
{
        return 0;
}
 
/*
* Called to process a message coming upstream.  All messages
* but flow control messages are put on the read side service
* queue for later processing.
*/
static int
spass_rput (q, mp)
        queue_t * q;
        mblk_t * mp;
{
        switch (mp->b_datap->db_type) {
        case M_FLUSH:
                if (*mp->b_rptr & FLUSHR)
                        flushq(q, 0);
                putnext(q, mp);
                break;
        default:
                putq(q, mp);
                break;
        }
        return 0;
}
 
/*
* Shared by both read and write sides to process messages put
* on the read or write service queues.  When called from the
* write side, sends all messages on the write side queue
* downstream until flow control kicks in or all messages are
* processed.  When called from the read side sends all messages
* on its read side service queue upstreams until flow control
* kicks in or all messages are processed.
*/
static int
spass_srv (q)
        queue_t * q;
{
        mblk_t *        mp;
 
        while (mp = getq(q)) {
                if (!canput(q->q_next))
                     return putbq(q, mp);
                putnext(q, mp);
        }
        return 0;
}
 
/*
* Called to process a message coming downstream.  All messages but
* flow control messages are put on the write side service queue for
* later processing.
*/
static int
spass_wput (q, mp)
        queue_t * q;
        mblk_t *        mp;
{
        switch (mp->b_datap->db_type) {
        case M_FLUSH:
                if (*mp->b_rptr & FLUSHW)
                        flushq(q, 0);
                putnext(q, mp);
                break;
        default:
                putq(q, mp);
                break;
        }
        return 0;
}