VxWorks Reference Manual : Libraries
pipeDrv - pipe I/O driver
pipeDrv( ) - initialize the pipe driver
pipeDevCreate( ) - create a pipe device
The pipe driver provides a mechanism that lets tasks communicate with each other through the standard I/O interface. Pipes can be read and written with normal read( ) and write( ) calls. The pipe driver is initialized with pipeDrv( ). Pipe devices are created with pipeDevCreate( ).
The pipe driver uses the VxWorks message queue facility to do the actual buffering and delivering of messages. The pipe driver simply provides access to the message queue facility through the I/O system. The main differences between using pipes and using message queues directly are:
- pipes are named (with I/O device names).
- pipes use the standard I/O functions -- open( ), close( ), read( ), write( ) -- while message queues use the functions msgQSend( ) and msgQReceive( ).
- pipes respond to standard ioctl( ) functions.
- pipes can be used in a select( ) call.
- message queues have more flexible options for timeouts and message priorities.
- pipes are less efficient than message queues because of the additional overhead of the I/O system.
Before using the driver, it must be initialized and installed by calling pipeDrv( ). This routine must be called before any pipes are created. It is called automatically by the root task, usrRoot( ), in usrConfig.c when the configuration macro INCLUDE_PIPES is defined.
Before a pipe can be used, it must be created with pipeDevCreate( ). For example, to create a device pipe "/pipe/demo" with up to 10 messages of size 100 bytes, the proper call is:
pipeDevCreate ("/pipe/demo", 10, 100);
Once a pipe has been created it can be opened, closed, read, and written just like any other I/O device. Often the data that is read and written to a pipe is a structure of some type. Thus, the following example writes to a pipe and reads back the same data:
{ int fd; struct msg outMsg; struct msg inMsg; int len; fd = open ("/pipe/demo", O_RDWR); write (fd, &outMsg, sizeof (struct msg)); len = read (fd, &inMsg, sizeof (struct msg)); close (fd); }The data written to a pipe is kept as a single message and will be read all at once in a single read. If read( ) is called with a buffer that is smaller than the message being read, the remainder of the message will be discarded. Thus, pipe I/O is "message oriented" rather than "stream oriented." In this respect, VxWorks pipes differ significantly from UNIX pipes which are stream oriented and do not preserve message boundaries.
Interrupt service routines (ISR) can write to pipes, providing one of several ways in which ISRs can communicate with tasks. For example, an interrupt service routine may handle the time-critical interrupt response and then send a message on a pipe to a task that will continue with the less critical aspects. However, the use of pipes to communicate from an ISR to a task is now discouraged in favor of the direct message queue facility, which offers lower overhead (see the manual entry for msgQLib for more information).
An important feature of pipes is their ability to be used in a select( ) call. The select( ) routine allows a task to wait for input from any of a selected set of I/O devices. A task can use select( ) to wait for input from any combination of pipes, sockets, or serial devices. See the manual entry for select( ).
Pipe devices respond to the following ioctl( ) functions. These functions are defined in the header file ioLib.h.
- FIOGETNAME
- Gets the file name of fd and copies it to the buffer referenced by nameBuf:
status = ioctl (fd, FIOGETNAME, &nameBuf);- FIONREAD
- Copies to nBytesUnread the number of bytes remaining in the first message in the pipe:
status = ioctl (fd, FIONREAD, &nBytesUnread);- FIONMSGS
- Copies to nMessages the number of discrete messages remaining in the pipe:
status = ioctl (fd, FIONMSGS, &nMessages);- FIOFLUSH
- Discards all messages in the pipe and releases the memory block that contained them:
status = ioctl (fd, FIOFLUSH, 0);
ioLib.h, pipeDrv.h
pipeDrv, select( ), msgQLib, VxWorks Programmer's Guide: I/O System
pipeDrv( ) - initialize the pipe driver
STATUS pipeDrv (void)
This routine initializes and installs the driver. It must be called before any pipes are created. It is called automatically by the root task, usrRoot( ), in usrConfig.c when the configuration macro INCLUDE_PIPES is defined.
OK, or ERROR if the driver installation fails.
pipeDevCreate( ) - create a pipe device
STATUS pipeDevCreate ( char * name, /* name of pipe to be created */ int nMessages, /* max. number of messages in pipe */ int nBytes /* size of each message */ )
This routine creates a pipe device. It allocates memory for the necessary structures and initializes the device. The pipe device will have a maximum of nMessages messages of up to nBytes each in the pipe at once. When the pipe is full, a task attempting to write to the pipe will be suspended until a message has been read. Messages are lost if written to a full pipe at interrupt level.
OK, or ERROR if the call fails.