JavaScript is required to for searching.
Skip Navigation Links
Exit Print View
STREAMS Programming Guide     Oracle Solaris 11.1 Information Library
search filter icon
search icon

Document Information

Preface

Part I Application Programming Interface

1.  Overview of STREAMS

2.  STREAMS Application-Level Components

3.  STREAMS Application-Level Mechanisms

4.  Application Access to the STREAMS Driver and Module Interfaces

5.  STREAMS Administration

6.  Pipes and Queues

Part II Kernel Interface

7.  STREAMS Framework - Kernel Level

8.  STREAMS Kernel-Level Mechanisms

9.  STREAMS Drivers

10.  STREAMS Modules

11.  Configuring STREAMS Drivers and Modules

Kernel Data Structures

modlinkage

modldrv

modlstrmod

dev_ops

cb_ops

streamtab

qinit

STREAMS Driver Entry Points

pts Example

STREAMS Module Configuration

Compilation

Kernel Loading

Checking the Module Type

Tunable Parameters

STREAMS Administrative Driver

Application Interface

STREAMS Anchors

Anchors and Data Flow

Using Anchors

12.  Multithreaded STREAMS

13.  STREAMS Multiplex Drivers

Part III Advanced Topics

14.  Debugging STREAMS-based Applications

Part IV Appendixes

A.  Message Types

B.  Kernel Utility Interface Summary

C.  STREAMS-Based Terminal Subsystem

D.  STREAMS FAQ

Glossary

Index

STREAMS Driver Entry Points

As described in Chapter 9, STREAMS Drivers and as seen in the previous data structures, there are four STREAMS driver entry points:

load kernel module

_init(9E), _fini(9E), _info(9E)

dev_ops

attach(9E), getinfo(9E)

cb_ops

open(9E), close(9E), read(9E), write(9E), ioctl(9E)

streamtab

put(9E), srv(9E)

pts Example

The following real example was taken from the Oracle Solaris operating environment. The driver pts(7D) is the pseudo terminal slave driver.

Example 11-1 Stream Pseudo Terminal Module

/*
 * Slave Stream Pseudo Terminal Module
 */

#include <sys/types.h>
#include <sys/param.h>
#include <sys/stream.h>
#include <sys/stropts.h>
#include <sys/stat.h>
#include <sys/errno.h>
#include <sys/debug.h>
#include <sys/cmn_err.h>
#include <sys/modctl.h>
#include <sys/conf.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>

static int ptsopen (queue_t*, dev_t*, int, int, cred_t);
static int ptsclose (queue_t*, int, cred_t*);
static int ptswput (queue_t*, mblk_t*);
static int ptsrsrv (queue_t*);
static int ptswsrv (queue_t*);

static int pts_devinfo(dev_info_t *dip, ddi_info_cmd_t infocmd,
      void *arg,void **result);

static struct module_info pts_info = {
        0xface,
        "pts",
        0,
        512,
        512,
        128
};

static struct qinit ptsrint = {
        NULL,
        ptsrsrv,
        ptsopen,
        ptsclose,
        NULL,
        &pts_info,
        NULL
};

static struct qinit ptswint = {
        ptswput,
        ptswsrv,
        NULL,
        NULL,
        NULL,
        &pts_info,
        NULL
};

static struct streamtab ptsinfo = {
        &ptsrint,
        &ptswint,
        NULL,
        NULL
};

static int pts_identify(dev_info_t *devi);
static int pts_attach(dev_info_t *devi, ddi_attach_cmd_t cmd);
static int pts_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
static dev_info_t *pts_dip;                /* private copy of devinfo ptr */

extern kmutex_t pt_lock;
extern pt_cnt;
static struct cb_ops cb_pts_ops = {
   nulldev,       /* cb_open */ 
   nulldev,       /* cb_close */ 
   nodev,         /* cb_strategy */
   nodev,         /* cb_print */
   nodev,         /* cb_dump */
   nodev,         /* cb_read */
   nodev,         /* cb_write */
   nodev,         /* cb_ioctl */
   nodev,         /* cb_devmap */
   nodev,         /* cb_mmap */
   nodev,         /* cb_segmap */
   nochpoll,      /* cb_chpoll */
   ddi_prop_op,   /* cb_prop_op */
   &ptsinfo,      /* cb_stream */
   D_MP           /* cb_flag */
};

static struct dev_ops pts_ops = {
   DEVO_REV,      /* devo_rev */
   0,             /* devo_refcnt */   
   pts_devinfo,   /* devo_getinfo */ 
   pts_identify,  /* devo_identify */
   nulldev,       /* devo_probe */
   pts_attach,    /* devo_attach */
   pts_detach,    /* devo_detach */
   nodev,         /* devo_reset */
   &cb_pts_ops,   /* devo_cb_ops */
   (struct bus_ops*) NULL   /* devo_bus_ops */
};

/*
 * Module linkage information for the kernel.
 */

static struct modldrv modldrv = {
            &mod_driverops,         /* Type of module: a pseudo driver */
            "Slave Stream Pseudo Terminal driver'pts'",
            &pts_ops,                /* driver ops */
};

static struct modlinkage modlinkage = {
        MODREV_1,
        (void *)&modldrv,
        NULL
};

int
_init(void)
{
        return (mod_install(&modlinkage));
}

int
_fini(void)
{
        return (mod_remove(&modlinkage));
}

int
_info(struct modinfo *modinfop)
{
        return (mod_info(&modlinkage, modinfop));
}

static int
pts_identify(dev_info_t *devi)
{
        if (strcmp(ddi_get_name(devi), "pts") == 0)
            return (DDI_IDENTIFIED);
        else
            return (DDI_NOT_IDENTIFIED);
}

static int
pts_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
{
        int i;
        char name[5];

        if (cmd != DDI_ATTACH)
            return (DDI_FAILURE);
    
        for (i = 0; i < pt_cnt; i++) {
            (void) sprintf(name, "%d", i);
            if (ddi_create_minor_node(devi, name, S_IFCHR, i, NULL, 0) 
                        == DDI_FAILURE) {
                ddi_remove_minor_node(devi, NULL);
                return (DDI_FAILURE);
            }
        }
        return (DDI_SUCCESS);
}

static int
pts_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
{
        ddi_remove_minor_node(devi, NULL);
        return (DDI_SUCCESS);
}

static int
pts_devinfo (dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
                     void **result)
{
        int error;

        switch (infocmd)   {
            case DDI_INFO_DEVT2DEVINFO:
                if (pts_dip == NULL) {
                    error = DDI_FAILURE;
                } else {
                    *result = (void *) pts_dip;
                    error = DDI_SUCCESS;
                }
                break;
            case DDI_INFO_DEVT2INSTANCE:
                *result = (void *) 0;
                error = DDI_SUCCESS;
                break;
            default:
                error = DDI_FAILURE;
        }
        return (error);
}

/* the open, close, wput, rsrv, and wsrv routines are presented
 * here solely for the sake of showing how they interact with the
 * configuration data structures and routines. Therefore, the 
 * bulk of their code is not included.
 */
static int
ptsopen(rqp, devp, oflag, sflag, credp)
        queue_t *rqp;     /* pointer to the read side queue */
        dev_t   *devp;            /* pointer to stream tail's dev */
        int     oflag;             /* the user open(2) supplied flags */
        int     sflag;             /* open state flag */
        cred_t  *credp;        /* credentials */
{
        qprocson(rqp);
        return (0);
}

static int
ptsclose(rqp, flag, credp)
        queue_t        *rqp;
        int            flag;
        cred_t        *credp;
{
        qprocsoff(rqp);
        return (0);
}

static int
ptswput(qp, mp)
        queue_t        *qp;
        mblk_t        *mp;
{
        return (0);
}

static int
ptsrsrv(qp)
        queue_t *qp;
{
        return (0);
}

static int
ptswsrv(qp)
        queue_t     *qp;
{
        return (0);
}