
if(intr_flag)
{
handle_intr();
}
if((nready = pselect(...,&zeromask)) < 0)
{
if(errno == EINTR)
{
if(intr_flag)
{
handle_intr();
}
}
}
在测试intr_flag变量之前,我们阻塞SIGINT,当pselect调用时,它先以空集(zeromask)替代进程的信号掩码,再检测描述符,并或许进入睡眠。然而当pselect函数返回时,进程的信号掩码又被重置为newmask,即SIGINT被阻塞。
//-------------------------------------10.poll函数-----------------------------------------
#include <poll.h>
int poll(struct pollfd* fdarray, unsigned long nfds, timeout);
// ret:若有就绪描述符则为其数目,若超时则为0,若出错则为-1
struct pollfd
{
int fd; // descripter to check
short events; // events of interest on fd
short revents; // events that occurred on fd
};
要测试的条件由events成员指定,函数在相应的revents成员中返回该表述符的状况,从而导致使用值-结果参数。
如果我们不再关心某个特定表述符,那么可以把与它对应的poolfd结构的fd成员修改成一个负值,poll函数将忽略这种的pollfd结构的events成员,返回时将它的reevnets成员的值置为0.
不像select和pselect,现在分配一个pollfd结构的字段并把字符中的元素的树木通知内核成了调用者的责任,内核不再需要明白类似fd_set的固定FD_SETSIZE大小的数据种类来维护用户信息了。
服务器使用poll的举例:
/* include fig01 */
#include "unp.h"
#include <limits.h> /* for OPEN_MAX */
int
main(int argc, char **argv)
{
int i, maxi, listenfd, connfd, sockfd;
int nready;
ssize_t n;
char buf[MAXLINE];
socklen_t clilen;
struct pollfd client[OPEN_MAX];
struct sockaddr_in cliaddr, servaddr;
listenfd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
Listen(listenfd, LISTENQ);
client[0].fd = listenfd;
client[0].events = POLLRDNORM;
for (i = 1; i < OPEN_MAX; i++)
client[i].fd = -1; /* -1 indicates available entry */
maxi = 0; /* max index into client[] array */
/* end fig01 */
/* include fig02 */
for ( ; ; ) {
nready = Poll(client, maxi+1, INFTIM);
if (client[0].revents & POLLRDNORM) { /* new client connection */
clilen = sizeof(cliaddr);
connfd = Accept(listenfd, (SA *) &cliaddr, &clilen);
#ifdef NOTDEF
printf("new client: %s\n", Sock_ntop((SA *) &cliaddr, clilen));
#endif
for (i = 1; i < OPEN_MAX; i++)
if (client[i].fd < 0) {
client[i].fd = connfd; /* save descriptor */
break;
}
if (i == OPEN_MAX)
err_quit("too many clients");
client[i].events = POLLRDNORM;
if (i > maxi)
maxi = i; /* max index in client[] array */
if (--nready <= 0)
continue; /* no more readable descriptors */
}
for (i = 1; i <= maxi; i++) { /* check all clients for data */
if ( (sockfd = client[i].fd) < 0)
continue;
if (client[i].revents & (POLLRDNORM | POLLERR)) {
if ( (n = read(sockfd, buf, MAXLINE)) < 0) {
if (errno == ECONNRESET) {
/*4connection reset by client */
#ifdef NOTDEF
printf("client[%d] aborted connection\n", i);
#endif
Close(sockfd);
client[i].fd = -1;
} else
err_sys("read error");
} else if (n == 0) {
/*4connection closed by client */
#ifdef NOTDEF
printf("client[%d] closed connection\n", i);
#endif
Close(sockfd);
client[i].fd = -1;
} else
Writen(sockfd, buf, n);
if (--nready <= 0)
break; /* no more readable descriptors */
}
}
}
}
/* end fig02 */
因为确认一个进程任何时刻才能开启的最大描述符数量并不容易,方法之一时以参数_SC_OPEN_MAXd调用sysconf函数,然后动态分配一个合适大小的pollfd数组,然而sysconf也或许返回indeterminate(不确定),意味着我们一直不得不猜测一个值,所以只好直接用POSIX的OPEN_MAX常值了。
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-124075-3.html
杨洋加油
”“那当初是谁追我追的死去活来最后做了我女朋友