Standards / Extensions | C or C++ | Dependencies |
---|---|---|
XPG4.2 |
both |
#define _XOPEN_SOURCE_EXTENDED 1
#define _OPEN_MSGQ_EXT
#include <sys/types.h>
#include <sys/time.h>
#include <sys/msg.h>
int select(int nmsgsfds, fd_set *__restrict__ readlist,
fd_set *__restrict__ writelist, fd_set *__restrict__ exceptlist,
struct timeval *__restrict__ timeout);
#define _POSIX_C_SOURCE 200112L
#include <sys/select.h>
int pselect(int nmsgsfds, fd_set *__restrict__ readlist,
fd_set *__restrict__ writelist, fd_set *__restrict__ exceptlist,
const struct timespec *__restrict__ timeout,
const sigset *__restrict__ sigmask);
#define _OE_SOCKETS
#define _OPEN_MSGQ_EXT
#include <sys/types.h>
#include <sys/time.h>
#include <sys/msg.h>
int select(int nmsgsfds, fd_set *readlist,
fd_set *writelist, fd_set *exceptlist,
struct timeval *timeout);
_OPEN_MSGQ_EXT must be defined if message queues are to be monitored (X/Open sockets only).
The pselect() and select() functions monitor activity on a set of sockets and/or a set of message queue identifiers until a timeout occurs, to see if any of the sockets and message queues have read, write, or exception processing conditions pending. This call also works with regular file descriptors, pipes, and terminals.
The select() function is equivalent to the pselect() function, except as follows:
This parameter is divided into two parts. The first half (the high-order 16 bits) gives the number of elements of an array that contains message queue identifiers. This number must not exceed the value 32767.
The second half (the low-order 16 bits) gives the number of bits within a bit set that correspond to the file or socket descriptors to check. This value should equal the greatest descriptor number to check + 1.
If either half of the nmsgsfds parameter is equal to a value of 0, the corresponding bit sets or arrays are assumed not to be present.
If _OPEN_MSGQ_EXT is not defined, only file or socket descriptors may be monitored. In this case nmsgsfds must be less than or equal to FD_SETSIZE (defined to be 2048 in sys/time.h), and greater than or equal to zero. Also, FD_SETSIZE may not be defined by your program.
The bit set used to specify file or socket descriptors is fixed in size with 1 bit for every possible file or socket. Use the nmsgsfds parameter to force pselect() or select() to check only a subset of the allocated bit set.
If your application allocates sockets 3, 4, 5, 6, and 7 and you want to check all of your allocations, the second half of nmsgsfds should be set to 8, the highest descriptor you specified + 1. If your application checks sockets 3 and 4, the second half of nmsgsfds should be set to 5.
To select on descriptor numbers between 2048 and 65534, either the _OPEN_MSGQ_EXT or _OPEN_SYS_HIGH_DESCRIPTORS feature test macro must be defined, and a bit set larger than the default size must be used. Note that when you are also selecting on message queues, as is possible when _OPEN_MSGQ_EXT is defined, the largest descriptor number is restricted to 2047. To select on descriptor numbers between 65535 and 524287, feature test macro _OPEN_SYS_HIGH_DESCRIPTORS must be defined and feature test macro _OPEN_MSGQ_EXT must not be defined. In addition, the process' MAXFILEPROC limit must be greater than 65536. With this feature, any number of sockets can be selected on (without message queues). FD_SETSIZE may also be redefined in this case, though it is recommended that the application explicitly allocate the larger bit set using malloc().
struct sellist {
fd_set fdset; /* file/socket descriptor bit set */
int msgids[max_size]; /* array of message queue identifiers */
};
If you use a sellist structure, the highest descriptor you can monitor is 2047.
The description of the type fd_set is given below. Each integer of the msgids array specifies a message queue identifier whose status is to be checked. Elements with a value of -1 are acceptable and will be ignored. The value contained in the first half of nmsgsfds determines exactly how many elements of the array are to be checked.
If timeout is not a NULL pointer, it specifies a maximum interval to wait for the selection to complete. The maximum timeout value is 31 days. If timeout is a NULL pointer, the pselect() and select() call blocks until a socket or message becomes ready. To poll the sockets and return immediately, timeout should be a non-NULL pointer to a zero-valued timeval structure or timespec structure.
If sigmask is not a null pointer, then the pselect() function will replace the signal mask of the caller by the set of signals pointed to by sigmask before examining the descriptors, and will restore the signal mask of the calling thread before returning.
To allow you to test more than one socket at a time, the sockets to test are placed into a bit set of type fd_set. A bit set is a string of bits such that if x is an element of the set, the bit representing x is set to 1. If x is not an element of the set, the bit representing x is set to 0. For example, if socket 33 is an element of a bit set, then bit 33 is set to 1. If socket 33 is not an element of a bit set, then bit 33 is set to 0.
The application program must make sure that the parameters readlist, writelist, and exceptlist point to bit strings that are as large as the bit string size in parameter nmsgsfds z/OS UNIX services will try to access bits 0 through n-1 (where n = the value of the second halfword of nmsgsfds), for each of the bit strings. If the bit strings are too short, you will receive unpredictable results when you run your application program.
A socket is ready for reading when incoming data is buffered for it or when a connection request is pending. To test whether any sockets are ready for reading, use either FD_ZERO() or memset(), if the function was dynamically allocated, to initialize the fdset bit set in readlist and invoke FD_SET() for each socket to test.
A socket is ready for writing if there is buffer space for outgoing data. A socket is ready for reading if there is data on the socket to be received. For a nonblocking stream socket in the process of connecting the connect() will return with a -1. The program needs to check the errno. If the errno is EINPROGRESS, the socket is selected for write when the connect() completes. In the situation where the errno is not EINPROGRESS, the socket will still be selected for write which indicates that there is a pending error on the socket. Acall to write(), send(), or sendto() does not block provided that the amount of data is less than the amount of buffer space. If a socket is selected for write, the amount of available buffer space is guaranteed to be at least as large as the size returned from using SO_SNDBUF with getsockopt(). To test whether any sockets are ready for writing, initialize the fdset bit set in writelist with either FD_ZERO() or memset(), if dynamically allocated, and use FD_SET() for each socket to test.
A message queue is ready for reading when any time it has a message on it. It is considered ready for writing when any time it is not full. A message queue is full when it has either reached its number of messages limit or its number of bytes limit. An exception condition exists when a message queue is deleted while a select() caller is waiting on the queue.
The programmer can pass NULL for any of the readlist, writelist, and exceptlist parameters. However, when they are not NULL, they must all point to the same type of structures. For example, suppose the readlist points to a sellist. If the writelist is not NULL, it must point to a sellist also. Now, let us say the writelist is not NULL. If the programmer wants to check a set of file descriptors for read status only, the appropriate bits in the bit set in the sellist structure pointed to by the writelist must be set to 0. If the programmer wants to check a set of message queues for write status only, the appropriate elements in the array in the sellist structure pointed to by the readlist must be set to -1. Regular files are always ready for reading and writing.
Because the sets of sockets passed to pselect() and select() are bit sets, the pselect() and select() call must test each bit in each bit set before polling the socket for its status. The pselect() and select() call tests only sockets in the range 0 to n-1 (where n = the value of the second halfword of nmsgsfds).
Special behavior for C++: To use this function with C++, you must use the _XOPEN_SOURCE_EXTENDED 1 feature test macro.
The value -1 indicates the error code should be checked for an error. The value zero indicates an expired time limit.
When the return value is greater than 0, then it is similar to nmsgsfds in that the high-order 16 bits give the number of message queues, and the low-order 16 bits give the number of descriptors. These values indicate the sum total that meet each of the read, write, and exception criteria. Note that a descriptor or a message queue may be counted multiple times if it meets more than one given criterion. Should the return value for message queues exceed the value 32767, only 32767 will be reported. This is to ensure that the return value does not appear to be negative. Should the return value for file/socket descriptors be greater than 65535, only 65535 will be reported.
#define _XOPEN_SOURCE_EXTENDED 1
#define _OPEN_MSGQ_EXT
#include <sys/types.h>
#include <sys/time.h>
#include <sys/msg.h>
struct sellist {
fd_set fdset;
int msgids[2];
};
/*
* sock_msg_stats(sr, sw, se, mr, mw, me) - Print the status of
* sockets sr, sw, and se, and of message queue ids mr, mw,
* and me.
*/
int sock_msg_stats(sr, sw, se, mr, mw, me)
int sr, sw, se, mr, mw, me;
{
struct sellist *reading, *writing, *excepting;
struct sellist read, write, except;
struct timeval timeout;
int rc, max_sock, sock_size, nmsgsfds;
int msgids[1]; /* we only check 1 message queue */
/* What's the maximum socket number? */
max_sock = MAX( sr, sw );
max_sock = MAX( max_sock, se );
/* initialize the static bit sets */
FD_ZERO( &read.fdset ); reading = &read;
FD_ZERO( &write.fdset ); writing = &write;
FD_ZERO( &except.fdset ); excepting = &except;
/* add sr, sw, and se to the appropriate bit set */
FD_SET( sr, &reading->fdset );
FD_SET( sw, &writing->fdset );
FD_SET( se, &excepting->fdset );
/* initialize the message id arrays */
reading->msgids[0] = mr;
writing->msgids[0] = mw;
excepting->msgids[0] = me;
/* set the nmsgsfds parameter */
_SET_FDS_MSGS( nmsgsfds, 1, max_sock+1 );
/* make select poll by sending a 0 timeval */
memset( &timeout, 0, sizeof(timeout) );
/* poll */
rc = select( nmsgsfds, reading, writing, excepting, &timeout);
if ( rc < 0 ) {
/* an error occurred during the SELECT() */
perror( "select" );
}
else if ( rc == 0 ) {
/* no sockets or messages were ready in our little poll */
printf( "nobody is home.\n" );
} else
if (_NFDS(rc) > 0) {
/* at least one of the sockets is ready */
printf("sr is %s\n",
FD_ISSET(sr,&reading->fdset) ? "READY" : "NOT READY");
printf("sw is %s\n",
FD_ISSET(sw,&writing->fdset) ? "READY" : "NOT READY");
printf("se is %s\n",
FD_ISSET(se,&excepting->fdset) ? "READY": "NOT READY");
} else
if (_NMSGS(rc) > 0) {
/* at least one message queue is ready */
printf("mr is %s\n",
reading->msgids[0] == -1 ? "NOT READY" : "READY");
printf("mw is %s\n",
writing->msgids[0] == -1 ? "NOT READY" : "READY");
printf("me is %s\n",
excepting->msgids[0] == -1 ? "NOT READY" : "READY");
}
}
CELEBP72
⁄* CELEBP72
This example demonstrates the use of pselect()
Expected output:
Parent: Issuing pselect
This is the child
Child: Sending signal to the parent at:
This is the signal handler
Signal received: 14 (14 is SIGALRM)
The pselect call was made at:
The SIGALRM was caught at:
TEST PASSED!
*⁄
#define _POSIX_C_SOURCE 200112L
#include <sys⁄select.h>
#include <stdio.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
time_t t1,t2;
void incatchr(int signum){
double diff=0;
time(&t2);
printf("\n\nThis is the signal handler\n");
printf("Signal received: %d (14 is SIGALRM) \n",signum);
printf("The pselect call was made at: \t%s\n",ctime(&t1));
printf("The SIGALRM was caught at: \t%s\n",ctime(&t2));
diff = difftime(t2,t1);
if(diff < 10) {
printf("TEST FAILED!\n\n");
}
else{
printf("TEST PASSED!\n\n");
}
}
int main(void){
int fd[1], rc, nfds=3, fd1, fd2, fd3;
pid_t cpid, ppid;
fd_set fdsread;
struct sigaction action, info;
sigset_t pselect_set;
struct timespec t;
time_t t3;
t.tv_sec=10;
t.tv_nsec=0;
FD_ZERO(&fdsread);
action.sa_handler = incatchr;
action.sa_flags = 0;
sigaction(SIGALRM,&action,&info);
sigemptyset(&pselect_set);
sigaddset(&pselect_set, SIGALRM);
fd1 = open(".⁄testchd.txt",O_RDWR|O_CREAT);
fd2 = open(".⁄testchd2.txt",O_RDWR|O_CREAT);
if((rc=pipe(fd)) != 0){
printf("Error in pipe\n");
return(-1);
}
FD_SET(fd[0],&fdsread);
if ((cpid = fork()) < 0){
printf("Fork error\n");
return(-1);
}
else{
if (cpid == 0){
fd3 = open(".⁄testchd.txt",O_RDWR|O_CREAT);
printf("This is the child\n");
sleep(2);
ppid= getppid();
time(&t3);
printf("Child: Sending signal to the parent at: ");
printf("%s",ctime(&t3));
kill(ppid,SIGALRM);
sleep(3);
_exit(0);
}
else{
printf("Parent: Issuing pselect\n\n");
time(&t1);
if (pselect(nfds,&fdsread,NULL,NULL,&t,&pselect_set) == -1)
printf("Error in pselect\n");
}
close(fd[0]);
}
return 0;
}