Go to main content

STREAMS Programming Guide

Exit Print View

Updated: November 2020
 
 

Kernel Data Structures

The following sections describe 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:

modlinkage

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 or modlstrmod. For more information, see the modlinkage(9S), modldrv(9S), and modlstrmod(9S) man pages.

modldrv

Contains information about the driver being loaded and points to the dev_ops structure. For more information, see the modldrv(9S) man page.

modlstrmod

Points to an fmodsw structure, which points to a streamtab. Only used by STREAMS modules. For more information, see the modlstrmod(9S), fmodsw(9S), and streamtab(9S) man pages.

dev_ops

Contains list of entry points for a driver, such as attach, and info. Also points to a cb_ops structure. For more information, see the dev_ops(9S) and cb_ops(9S) man pages.

cb_ops

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

streamtab

Points to the read and write queue init structures. For more information, see the streamtab(9S) man page.

qinit

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. For more information, see the qinit(9S) man page.

Each STREAMS driver or module contains the linkage connections for the various data structures which is a list of pointers to dev_ops structures. In each dev_ops structure is a pointer to the cb_ops structure. In the cb_ops 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. For more information, see the dev_ops(9S) and cb_ops(9S) man pages.

modlinkage Structure

The definition of modlinkage is:

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

For more information, see the modlinkage(9S) man page.

modldrv Structure

The definition of modldrv is:

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

For more information, see the modldrv(9S) man page.

modlstrmod Structure

The definition of modlstrmod is below. It does not point to dev_ops 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;
};

For more information, see the modlstrmod(9S)dev_ops(9S) man page.

dev_ops Structure

The dev_ops structure represents a specific class or type of device. Each dev_ops structure represents a unique device to the operating system. Each device has its own dev_ops structure, which in turn contains a cb_ops 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 */
};

For more information, see the dev_ops(9S) man page.

cb_ops Structure

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 */
};

For more information, see the cb_ops(9S) man page.

streamtab Structure

The streamtabstructure 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 indirectly identifies the appropriate open, close, put, service, and administration routines. These driver and module routines should 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 */
};

For more information, see the streamtab(9S) man page.

qinit Structure

The qinit structure 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)*/
};

For more information, see the qinit(9S) man page.