apue和unp的学习之旅08——I/O复用(3)

电脑杂谈  发布时间:2019-09-25 07:02:54  来源:网络整理

unp和apue阅读顺序_unp和apue阅读顺序_unp文件夹

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

相关阅读
    发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

    • 杨丽停
      杨丽停

      ”“那当初是谁追我追的死去活来最后做了我女朋友

    • 周安王姬骄
      周安王姬骄

      杨洋加油

    热点图片
    拼命载入中...