STREAMS Programming Guide

Kernel Data Structures

The following sections contain descriptions of the pointer relationships maintained by the kernel and the various data structures used in STREAMS drivers. When the kernel accesses a driver, it uses a sequence of pointers in various data structures. It looks first at the data structure relationship, and then the entry point interface for loading the driver into the kernel and accessing the driver from the application level.

The order of data structures the kernel uses to get to a driver is as follows:


Contains the revision number and a list of drivers to dynamically load. It is used by mod_install in the _init routine to load the module into the kernel. Points to a modldrv(9S) or modlstrmod(9S).


Contains information about the driver being loaded and points to the devops structure.


Points to an fmodsw(9S) structure (which points to a streamtab(9S)). Only used by STREAMS modules.


Contains list of entry points for a driver, such as attach, and info. Also points to a cb_ops(9S) structure.


Points to list of threadable entry points to driver, like open, close, read, write, ioctl. Also points to the streamtab.


Points to the read and write queue init structures.


Points to the entry points of the STREAMS portion of the driver, such as put, srv, open, close, as well as the mod_info structure. These entry points only process messages.

Each STREAMS driver or module contains the linkage connections for the various data structures which is a list of pointers to dev_ops(9S) structures. In each dev_ops(9S) structure is a pointer to the cb_ops(9S) structure. In the cb_ops(9S) structure contains a pointer to the streamtab struct. If the driver is not a STREAMS driver, streamtab is NULL. If the driver is a STREAMS driver, streamtab contains initialization routines for the driver.


The definition of modlinkage(9S) is:

struct modlinkage {
   int      ml_rev;           /* rev of loadable modules system */
   void     *ml_linkage[4];   /* NULL terminated list of linkage 
                               * structures */


The definition of modldrv(9S) is:

struct modldrv {
		struct mod_ops   *drv_modops;
		char             *drv_linkinfo;
		struct dev_ops   *drv_dev_ops;


The definition of modlstrmod(9S) is below. It does not point to dev_ops(9S) structures because modules can only be pushed onto an existing stream.

struct modlstrmod {
		struct mod_ops      *strmod_modops;
		char                *strmod_linkinfo;
		struct fmodsw       *strmod_fmodsw;


The dev_ops(9S) structure represents a specific class or type of device. Each dev_ops(9S) structure represents a unique device to the operating system. Each device has its own dev_ops(9S) structure, which in turn contains a cb_ops(9S) structure.

struct dev_ops  {
  int       devo_rev;                 /* Driver build version	*/
  int       devo_refcnt;              /* device reference count	*/
  int       (*devo_getinfo)(dev_info_t *dip, ddi_info_cmd_t infocmd, 
									 void *arg, void **result);
  int       (*devo_identify)(dev_info_t *dip);
  int       (*devo_probe)(dev_info_t *dip);
  int       (*devo_attach)(dev_info_t *dip, ddi_attach_cmd_t cmd);
  int       (*devo_detach)(dev_info_t *dip, ddi_detach_cmd_t cmd);
  int       (*devo_reset)(dev_info_t *dip, ddi_reset_cmd_t cmd);
  struct cb_ops      *devo_cb_ops;    /* cb_ops ptr for leaf driver*/
  struct bus_ops     *devo_bus_ops;   /* ptr for nexus drivers */


The cb_ops(9S) structure is the SunOS 5 version of the cdevsw and bdevsw tables of previous versions of UNIX System V. It contains character and block device information and the driver entry points for non-STREAMS drivers.

struct cb_ops  {
		int		*cb_open)(dev_t *devp, int flag, int otyp, 
						cred_t *credp);
		int		(*cb_close)(dev_t dev, int flag, int otyp, 
						cred_t *credp);
		int		(*cb_strategy)(struct buf *bp);
		int		(*cb_print)(dev_t dev, char *str);
		int		(*cb_dump)(dev_t dev, caddr_t addr,daddr_t blkno, 
						int nblk);
		int		(*cb_read)(dev_t dev, struct uio *uiop, cred_t *credp);
		int		(*cb_write)(dev_t dev, struct uio *uiop, cred_t *credp);
		int		(*cb_ioctl)(dev_t dev, int cmd, int arg, int mode,
						cred_t *credp, int *rvalp);
		int		(*cb_devmap)(dev_t dev, dev_info_t *dip, 
						ddi_devmap_data_t *dvdp, ddi_devmap_cmd_t cmd, 
						off_t offset, unsigned int len, unsigned int prot, 
						cred_t *credp);
		int		(*cb_mmap)(dev_t dev, off_t off, int prot);
		int		(*cb_segmap)(dev_t dev, off_t off, struct as *asp, 
						caddr_t *addrp, off_t len, unsigned int prot, 
						unsigned int maxprot, unsigned int flags, 
						cred_t *credp);
		int		(*cb_chpoll)(dev_t dev, short events, int anyyet, 
						short *reventsp, struct pollhead **phpp);
		int		(*cb_prop_op)(dev_t dev, dev_info_t *dip, 
						ddi_prop_op_t prop_op, int mod_flags, char *name, 
						caddr_t valuep, int *length);

     struct streamtab *cb_str;		/* streams information */

		 * The cb_flag fields are here to tell the system a bit about 
		 * the device. The bit definitions are in <sys/conf.h>.
     int		cb_flag;					/* driver compatibility flag */


The streamtab(9S) structure contains pointers to the structures that hold the routines that actually initialize the reading and writing for a module.

If streamtab is NULL, there are no STREAMS routines and the entire driver is treated as though it was a non-STREAMS driver. The streamtab(9S) indirectly identifies the appropriate open, close, put, service, and administration routines. These driver and module routines should generally be declared static.

struct streamtab {
		struct qinit     *st_rdinit;      /* defines read queue */
		struct qinit     *st_wrinit;      /* defines write queue */
		struct qinit     *st_muxrinit;    /* for multiplexing */
		struct qinit     *st_muxwinit;    /* drivers only */


The qinit(9S) structure (also shown in Appendix A) contains pointers to the STREAMS entry points. These routines are called by the module-loading code in the kernel.

struct qinit {
 	int         (*qi_putp)();            /* put procedure */
 	int         (*qi_srvp)();            /* service procedure */
 	int         (*qi_qopen)();           /* called on each open or push*/
 	int         (*qi_qclose)();          /* called on last close or pop*/
 	int         (*qi_qadmin)();          /* reserved for future use */
 	struct module_info     *qi_minfo;    /* info struct */
 	struct module_stat     *qi_mstat;    /* stats struct (opt)*/