select
#include <sys/select.h>
int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, struct timeval* timeout);
sucess return 就绪的文件描述符总数
failed return -1 and set errno
如果在等待期间收到新号
return -1 and set errno to EINTR
- nfds指定被监听的文件描述符总数,通常设置为select监听的所有文件描述符+ 1
- readfds、writefds、exceptfds分别指向可读、可写和异常等时间对应的文件描述符集合
FD_ZERO(fd_set* fdset); 将fd_set变量的所有位初始化为0。
FD_SET(int fd, fd_set* fdset); 在参数fd_set指向的变量中注册文件描述符fd的信息。
FD_CLR(int fd, fd_set* fdset); 参数fd_set指向的变量中清除文件描述符fd的信息。
FD_ISSET(int fd, fd_set* fdset); 若参数fd_set指向的变量中包含文件描述符fd的信息,则返回真。
for (i=0; i<5;i++)
{
memset(&client,0,sizeof (client));
addrlen = sizeof(client);
fds[i] = accept(sockfd,(struct sockaddr*)&client,&addrlen);
if(fds[i] > max)
max = fds[i];
}
while(1){
FD_ZERO(&rset);
for (i = 0; i< 5; i++ ) {
FD_SET(fds[i],&rset);
}
puts("round again" );
select(max+1,&rset,NULL,NULL,NULL);
for(i=0;i<5;i+1) {
if (FD_ISSET(fds[i],&rset)){
memset(buffer ,0, MAXBUF);
read(fds[i],buffer,MAXBUF);
puts(buffer);
}
}
- 设置client_fds[] client_fds
- 通过client_fds设置rset(将对应位设置为1)
- 将rset传入select,select返回后将未发生就绪事件的rset位置0
- 在用户态找到就绪事件的fd并处理事件(使用FD_ISSET)
- 将client_fds[]重置入rset中
poll
epoll
创建一个epoll句柄(epoll_create )
#include <sys/epoll.h>
int epoll_create (int __size);
return epollfd;
注册事件
int epoll_ctl (int __epfd, int __op, int __fd, struct epoll_event *__event);
sucess return 0
failed return -1 and set errno
op(operation?)
- EPOLL_CTL_ADD 1 /* Add a file descriptor to the interface. */
- EPOLL_CTL_DEL 2 /* Remove a file descriptor from the interface. */
- EPOLL_CTL_MOD 3 /* Change file descriptor epoll_event structure. */
等待描述符就绪
int epoll_wait(int__epfd,struct epoll_event *__events,int _maxevents,int __timeout);
return 就绪的文件描述符个数
struct epoll_event {
uint32_t events; //epoLL事件
epoll_data_t data; //用户数据
} __EPOLL_PACKED;
typedef union epoll_data {
void *ptr; 可以用改指针指向自定义的参数
int fd; 可以用改成员指向epoll所监控的文件描述符
uint32_t u32;
uint64_t u64;
} epoll_data_t;
网友评论