STREAMS(流)是系统 V 提供的构造内核设备驱动程序和网络协议包的一种通用方法。流在用户进程和设备驱动程序之间提供了一条全双工通路,下面是流在用户进程和设备驱动程序之间的流图:写到流首的数据将顺流而下传送,由设备驱动程序读到的数据则逆流向上传送;
STREAMS 的所有输入和输出都是基于消息,流首和用户进程使用 read、write、ioctl、getmsg、getpmsg、putmsg 和 putpmsg 交换信息。在流首、各处理模块和设备驱动程序之间,消息可顺流而下,也可逆流而上。
在用户进程和流首之间,消息由以下几部分组成:消息类型、控制信息和数据;其中控制信息和数据由以下结构指定:
struct strbuf { int maxlen; /* size of buffer */ int len; /* number of bytes currently in buffer */ char *buf; /* pointer to buffer */ };
在我们所使用的函数(read,write,getmsg,getpmsg,putmsg 和 putpmsg)中,只涉及三种消息类型,他们是:
流中的消息都有一个排队优先级:
普通信消息是优先级波段为 0 的消息,优先级波段可在 1~255 之间,波段愈高,优先级也愈高,在任何时刻流首只有一个高优先级消息排队,若在流首读队列已有一个高优先级消息,则另外的高优先级消息会被丢弃。
putmsg 和 putpmsg 函数
putmsg 和 putpmsg 函数用于 STREAMS 消息写至流中,这两个函数的区别是后者允许对消息指定一个优先级波段。
/* 流 */ /* * 函数功能:将STREAMS消息写至流; * 返回值:若成功则返回0,若出错则返回-1; * 函数原型: */ #include <stropts.h> int putmsg(int filedes, const struct strbuf *ctlptr, const struct strbuf *datptr, int flags); int putpmsg(int filedes, const struct strbuf *ctlptr, const struct strbuf *datptr, int band, int flags); /* * 说明: * 对流使用write函数等价于不带任何控制信息、flags为0的putmsg函数; * 这两函数可以产生三种不同优先级的消息:普通、优先级波段和高优先级; */
ioctl 函数如下:
/* Perform the I/O control operation specified by REQUEST on FD. One argument may follow; its presence and type depend on REQUEST. Return value depends on REQUEST. Usually -1 indicates error. */ int ioctl (int __fd, unsigned long int __request, ...) ;ioctl 的第二个参数request说明执行哪一个操作。所有request都以I_开始。第三个参数的作用与request有关,有时它是一个整型值,有时它是指向一个整型或一个数据结构的指针。
/* * 函数功能:判断描述符是否引入一个流; * 返回值:若为STREAMS设备则返回1,否则返回0; * 函数原型: */ #include <stropts.h> int isastream(int filedes); /* * 说明: * 该函数是通过ioctl函数来进行的,可有如下实现: */ #include <stropts.h> #include <unistd.h> int isastream(int fd) { return(ioctl(fd, I_CANPUT, 0) != -1); }
可以使用两个 ioctl 命令取得和设置一个流的写模式,如果将 request 设置为 I_GWPORT,第三个参数设置为指向一个整型变量的指针,则该流的当前写模式在该整型变量中返回。如果将 request 设置为 I_SWPORT,第三个参数是一个整型值,则其值成为该流新的写模式,我们可以先获取当前写模式值,然后修改它,则进行设置。目前只定义了两个写模式值。
读STREAMS设备有两个潜在的问题:
在读模式中还可指定另外三个变量,以便设置在读到流中包含协议控制信息的消息时read的处理方法:任一时刻,智能设置一种消息读模式和一种协议读模式,默认读模式是:(RNORM | RPROTNORM)。
/* * 函数功能:将从流读STREAMS消息; * 返回值:若成功则返回非负值,若出错则返回-1; * 函数原型: */ #include <stropts.h> int getmsg(int filedes, const struct strbuf *ctlptr, const struct strbuf *datptr, int *flagptr); int getpmsg(int filedes, const struct strbuf *ctlptr, const struct strbuf *datptr, int *bandptr, int *flagptr); /* * 说明: * 如果flagptr指向的整型单元的值是0,则getmsg返回流首读队列中的下一个消息; * 如果下一个消息是最高优先级消息,则在返回时,flagptr所指向的整型单元设置为RS_HIPRI; * 如果只希望接收高优先级消息,则在调用getmsg之前必须将flagptr所指向的整型单元设置为RS_HIPRI; * getmsg可以设置待接收消息的优先级波段; */
《UNIX高级环境编程》