Sun Microsystems, Inc.
spacerspacer
spacer www.sun.com docs.sun.com |
spacer
black dot
 
 
2.  STREAMS Application-Level Components Stream Construction Example Inserting Modules  Previous   Contents   Next 
   
 

Module and Driver Control

The next step in this example is to pass the commands and corresponding strings to the character conversion module. This can be accomplished by calling ioctl(2) to invoke the character conversion module.

Example 2-3 uses the conventional I_STR ioctl(2), an indirect way of passing commands and data pointers. Example 2-4 shows the data structure for I_STR.

Instead of I_STR, some systems support transparent ioctls in which calls can be made directly. For example, a module calls I_PUSH. Both modules and drivers can process ioctls without requiring user programs to first encapsulate them with I_STR (that is, the ioctls in the examples would look like ioctl(fd,DELETE,"AEIOU");). This style of call works only for modules and drivers that have been converted to use the new facilities that also accept the I_STR form.


Example 2-3 Processing ioctl(2)

/* change all uppercase vowels to lowercase */
strioctl.ic_cmd = XCASE;
strioctl.ic_timout = 0; /* default timeout (15 sec) */
strioctl.ic_dp = "AEIOU";
strioctl.ic_len = strlen(strioctl.ic_dp);
if (ioctl(fd, I_STR, &strioctl) < 0) {
   perror("ioctl I_STR failed");
   exit(3);
}
/* delete all instances of the chars 'x' and 'X' */
strioctl.ic_cmd = DELETE;
strioctl.ic_dp = "xX";
strioctl.ic_len = strlen(strioctl.ic_dp);
if (ioctl(fd, I_STR, &strioctl) < 0) {
   perror("ioctl I_STR failed");
   exit(4);
}

In Example 2-3, the module changes all uppercase vowels to lowercase, and deletes all instances of either uppercase or lowercase "x". ioctl(2) requests are issued indirectly, using I_STR ioctl(2) (see streamio(7I)). The argument to I_STR must be a pointer to a strioctl structure, which specifies the request to be made to a module or driver. This structure is described in streamio(7I) and has the format shown in the following example.


Example 2-4 strioctl Structure

struct strioctl {
	int         ic_cmd;             /* ioctl request */
	int         ic_timout;          /* ACK/NAK timeout */
	int         ic_len;             /* length of data argument */
	char        *ic_dp;             /* ptr to data argument */
};

where:

ic_cmd

Identifies the command intended for a module or driver.

ic_timout

Specifies the number of seconds an I_STR request should wait for an acknowledgement before timing out.

ic_len

The number of bytes of data to accompany the request.

ic_dp

Points to the data. In the example, two separate commands are sent to the character-conversion module:

  • The first command sets ic_cmd to the command XCASE and sends as data the string "AEIOU." It converts all uppercase vowels in data passing through the module to lowercase.

  • The second command sets ic_cmd to the command DELETE and sends as data the string "xX." It deletes all occurrences of the characters "x" and "X" from data passing through the module.

For each command, the value of ic_timout is set to zero, which specifies the system default timeout value of 15 seconds. ic_dp points to the beginning of the data for each command; ic_len is set to the length of the data.

I_STR is intercepted by the stream head, which packages it into a message using information contained in the strioctl structure, then sends the message downstream. Any module that cannot process the command in ic_cmd passes the message further downstream. The request is processed by the module or driver closest to the stream head that understands the command specified by ic_cmd. ioctl(2) blocks up to ic_timout seconds, waiting for the target module or driver to respond with either a positive or negative acknowledgement message. If an acknowledgement is not received in ic_timout seconds, ioctl(2) fails.


Note - Only one ioctl(2) can be active on a stream at one time, regardless of whether it is issued with I_STR. Further requests will block until the active ioctl(2) is acknowledged and the system call concludes.


The strioctl structure is also used to retrieve the results, if any, of an I_STR request. If data is returned by the target module or driver, ic_dp must point to a buffer large enough to hold that data, and ic_len is set on return to indicate the amount of data returned. The remainder of this example is identical to Example 1-1 in Chapter 1, Overview of STREAMS.


Example 2-5 Process Input

while ((count = read(fd, buf, BUFLEN)) > 0) {
			if (write(fd, buf, count) != count) {
				perror("write failed");
				break;
			}
	}
	exit(0);
}

Notice that the character-conversion processing was realized with no change to the communications driver.

exit(2) dismantles the stream before terminating the process. The character conversion module is removed from the stream automatically when it is closed. Alternatively, remove modules from a stream using I_POP ioctl(2) which is described in streamio(7I). This call removes the topmost module on the stream, and enables a user process to alter the configuration of a stream dynamically by popping modules as needed.

Several other ioctl(2) requests support STREAMS operations, such as determining if a given module is on a stream, or flushing the data on a stream. streamio(7I) describes these requests.

 
 
 
  Previous   Contents   Next