ioctl can be used to get or set the write mode.
ioctl can use: I_GWROPT to get the write mode.
ioctl can also use: I_SWROPT to set the write mode.
Current two write modes:
1) SNDZERO: a zero-length write to a pipe or FIFO will cause a zero-length message to be sent downstream
2) SNDPIPE: causes SIGPIPE to be sent to the calling process that calls either write or putmsg after an error has occured on a stream.
System Definition:
ubuntu@ip-172-31-23-227:~$ less /usr/include/x86_64-linux-gnu/bits/stropts.h
......
#define I_SWROPT (__SID |19) /* Set the write mode. */
#define I_GWROPT (__SID |20) /* Return the current write mode setting. */
......
/* Possible mode for `I_SWROPT'. */
#define SNDZERO 0x001 /* Send a zero-length message downstream when a
`write' of 0 bytes occurs. */
#ifdef __USE_GNU
# define SNDPIPE 0x002 /* Send SIGPIPE on write and putmsg if
sd_werror is set. */
#endif
......
2. getmsg, getpmsg
System Definition:
ubuntu@ip-172-31-23-227:~$ less /usr/include/stropts.h
......
/* Receive next message from a STREAMS file.
This function is a cancellation point and therefore not marked with
__THROW. */
extern int getmsg (int __fildes, struct strbuf *__restrict __ctlptr,
struct strbuf *__restrict __dataptr,
int *__restrict __flagsp);
/* Receive next message from a STREAMS file, with *FLAGSP allowing to
control which message.
This function is a cancellation point and therefore not marked with
__THROW. */
extern int getpmsg (int __fildes, struct strbuf *__restrict __ctlptr,
struct strbuf *__restrict __dataptr,
int *__restrict __bandp, int *__restrict __flagsp);
......
Rules for getmsg:
1) If the integer pointed to by flagptr is 0, getmsg returns the next message on the stream head's read queue. After receiving the message, if the message is high-priority message, the integer pointed to by flagptr is set to RS_HIPRI.
2) If we want to only get the high-priority message, before calling, we need to set the integer pointed to by flagptr to RS_HIPRI.
Rules for getpmsg:
1) We can set the integer pointed to by flagptr to MSG_HIPRI to receive only high-priority messages. We can set the integer to MSG_BAND and then set the integer pointed to by bandptr to a nonzero priority value to receive only messages from that band, or higher priority.
2) If we only want to receive the first available message, we can set the integer pointed to by flagptr to MSG_ANY; on return, the integer will be overwritten with either MSG_HIPRI or MSG_BAND, depending on the type of message received. If the received message was not a high-priority message, the integer pointed to by bandptr will contain the message's priority band.
Rule for ctlptr, dataptr:
1) If ctlptr->maxlen is -1, the control portion of the message will remain on the stream head's read queue, and we will not process it.
2) If dataptr->maxlen is -1, the data portion of the message is not processed and remains the on the stream head's read queue.
3. stream read mode:
We can use ioctl to change the stream read mode. We need to use "I_GRDOPT" as second argument to get the stream read mode, we also need to use "I_SRDOPT" as the second argument to set up the stream read mode.
The read mode is a combination of message read mode and protocol read mode:
1) message read mode:
RNORM: normal, byte-stream mode, either the requested number of bytes have been read or there is no more data.
RMSGN: message-nondiscard mode. either the requested number of bytes have been read or a message boundary is encountered. If it reads the partial message, the rest of the data in the message is left on the stream for subsequent read.
RMSGD: message-discard mode. If a partial message is used, the remainder of the message is discarded.
2) control information read mode:
RPROTNORM: Protocol-normal mode
RPROTDAT: protocol-data mode, read returns the control portion as data
RPROTDIS: protocol-discard mode: read discards the control information but returns any data in the message.
Only one of read mode and one of control mode can be set at a time, default mode is: RNORM | RPROTNORM
System Definition:
ubuntu@ip-172-31-23-227:~$ less /usr/include/x86_64-linux-gnu/bits/stropts.h
......
/* Options for `I_SRDOPT'. */
#define RNORM 0x0000 /* Byte-STREAM mode, the default. */
#define RMSGD 0x0001 /* Message-discard mode. */
#define RMSGN 0x0002 /* Message-nondiscard mode. */
#define RPROTDAT 0x0004 /* Deliver the control part of a message as
data. */
#define RPROTDIS 0x0008 /* Discard the control part of a message,
delivering any data part. */
#define RPROTNORM 0x0010 /* Fail `read' with EBADMSG if a message
containing a control part is at the front
of the STREAM head read queue. */
......
4. Example:
read.c:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<stropts.h>
#define BUFFSIZE 4096
int main(int argc, char* argv[])
{
int n, flag;
char ctlbuf[BUFFSIZE], datbuf[BUFFSIZE];
struct strbuf ctl, dat;
// Setup the buffer
ctl.buf = ctlbuf;
ctl.maxlen = BUFFSIZE;
dat.buf = datbuf;
dat.maxlen = BUFFSIZE;
// Read the data from standard input stream
for(;;) {
flag = 0;
if((n = getmsg(STDIN_FILENO, &ctl, &dat, &flag)) < 0) {
printf("getmsg error!\n");
exit(1);
}
fprintf(stderr, "flag = %d, ctl.len = %d, dat.len = %d\n", flag, ctl.len, dat.len);
if(dat.len == 0) exit(0);
else if(dat.len > 0)
if(write(STDOUT_FILENO, dat.buf, dat.len) != dat.len) {
printf("write error!\n");
exit(2);
}
}
exit(0);
}
shell:
getmsg is not implemented on linux OS. under solaris, the expected output:
$echo hello, world | ./read.out
flag = 0, ctl.len = -1, dat.len = 13
hello, world
flag = 0, ctl.len = 0, dat.len = 0
$./read.out
this is line 1
flag = 0, ctl.len = -1, dat.len = 15
this is line 1
and line 2
flag = 0, ctl.len = -1, dat.len = 11
and line 2
^D
flag = 0, ctl.len = -1, dat.len = 0
No comments:
Post a Comment