Linux中pselect实例,linux select pselect poll epoll用法

66b52468c121889b900d4956032f1009.png

8种机械键盘轴体对比

本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?

#include

#include

#include

#include

void FD_CLR(int fd, fd_set *set);

int FD_ISSET(int fd, fd_set *set);

void FD_SET(int fd, fd_set *set);

void FD_ZERO(fd_set *set);

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

监控fd状态(timeout 是到期前剩余时间)

int pselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec *timeout, const sigset_t *sigmask);

除了监测fd状态,pselect精度更准,且监测signal(另外pselect的timeout参数是const的)

monitor multiple file descriptors, waiting until one or more of the file descriptors become “ready” for some class of I/O operation

poll & ppoll#include

int poll(struct pollfd *fds, nfds_t nfds, int timeout);

fds: 监听事件的item数组

nfds: 数组成员数

timeout: 超时时间(unit:milliseconds, -1 mean infinite, 0 mean immediately)

return: success: > 0 带有revents事件的数组个数; = 0 time out 或者没有fd 事件

error: -1, errno is set

int ppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts, const sigset_t *sigmask);

fds: 监听事件的item数组

nfds: 数组成员数

timeout_ts: 超时时间(unit:seconds+nanoseconds, -1:indefinitely, 0:immediately)

sigmask: 监测的signal (遇到这些signal,ppoll也会返回) (NULL:indefinitely)

return: success: > 0 带有revents事件的数组个数; = 0 time out 或者没有fd 事件

error: -1, errno is set

performs a similar task to select(2): it waits for one of a set of file descriptors to become ready to perform I/O.

结构体struct pollfd {

int fd; /* in, file descriptor */

short events; /* in, requested events 请求需要监测的事件类型 */

short revents; /* out, returned events 发生的事件类型 */

};

The bits that may be set/returned in events and revents are defined in :

POLLIN 可读

POLLPRI 紧急数据可读

POLLOUT 可读(不会block)

POLLRDHUP 对端关闭, 本段hangup, 只针对stream socket fd

POLLERR 错误状态 (output only,即只会出现在revents中)

POLLHUP Hang up (output only,即只会出现在revents中)

POLLNVAL 无效请求 (output only,即只会出现在revents中)

epoll

The epoll API performs a similar task to poll(2): monitoring multiple file descriptors to see if I/O is possible on any of them.

The epoll API can be used either as an edge-trig‐gered or a level-triggered interface and scales well to large numbers of watched file descriptors.

模式 and

LT(Level-triggered) 一般

ET(edge-triggered) 事件发生时就触发

epoll_create

creates an epoll instance and returns a file descriptor referring to that instance, The more recent epoll_create1 extends the functionality.#include

int epoll_create(int size);

int epoll_create1(int flags);

epoll_ctl

register particular file descriptors interested.#include

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

epfd: return by epoll_create

op:

EPOLL_CTL_ADD Register the target file descriptor fd on the epoll instance

EPOLL_CTL_MOD Change the event event associated with the target file descriptor fd.

EPOLL_CTL_DEL Remove (deregister) the target file descriptor fd from the epoll

fd: 需要监听的描述符fd

event:需要监听的指定fd上的事件

typedef union epoll_data {

void *ptr;

int fd;

uint32_t u32;

uint64_t u64;

} epoll_data_t;

struct epoll_event {

uint32_t events; // EPOLLIN EPOLLOUT EPOLLRDHUP EPOLLPRI EPOLLERR

EPOLLHUP EPOLLET EPOLLONESHOT

epoll_data_t data; // User data variable

};

return:

success 0

error -1 errno

epoll_wait

waits for I/O events, blocking the calling thread if no events are currently available.#include

int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);

int epoll_pwait(int epfd, struct epoll_event *events, int maxevents, int timeout, const sigset_t *sigmask);

epfd: return by epoll_create

events:out, 监听到的事件数组

maxevents: in, 需要监听到事件个数,>0

timeout: time out值, (-1 mean infinite, 0 mean immediately)

sigmask: 监测的signal

return: the number of file descriptors ready for the requested I/O.

附(epoll 使用示例)

功能: 使用epoll 实现tcp server#include

#include

#include

#include

#include

#include

#include

#include

#include

using namespace std;

#define MAXLINE 5

#define OPEN_MAX 100

#define LISTENQ 20

#define SERV_PORT 5000

#define INFTIM 1000

void setnonblocking(int sock)

{

int opts;

opts=fcntl(sock,F_GETFL);

if(opts<0)

{

perror("fcntl(sock,GETFL)");

exit(1);

}

opts = opts|O_NONBLOCK;

if(fcntl(sock,F_SETFL,opts)<0)

{

perror("fcntl(sock,SETFL,opts)");

exit(1);

}

}

int main(int argc, char* argv[])

{

int i, maxi, listenfd, connfd, sockfd, epfd, nfds, portnumber;

ssize_t n;

char line[MAXLINE];

socklen_t clilen;

if (2 == argc ) {

if( (portnumber = atoi(argv[1])) < 0 ) {

fprintf(stderr,"Usage:%s portnumber/a/n", argv[0]);

return 1;

}

}

else {

fprintf(stderr,"Usage:%s portnumber/a/n",argv[0]);

return 1;

}

//声明epoll_event结构体的变量,ev用于注册事件,数组用于回传要处理的事件

struct epoll_event ev, events[20];

epfd = epoll_create(256); //生成用于处理accept的epoll专用的文件描述符

if (epollfd == -1) {

perror("epoll_create");

exit(EXIT_FAILURE);

}

// set up server listen socket

listenfd = socket(AF_INET, SOCK_STREAM, 0);

//setnonblocking(listenfd); //把socket设置为非阻塞方式

ev.events=EPOLLIN | EPOLLET; //设置要处理的事件类型及事件触发模式

ev.data.fd=listenfd; //设置与要处理的事件相关的文件描述符

//注册epoll事件

if (epoll_ctl(epfd, EPOLL_CTL_ADD, listenfd, &ev) == -1) {

perror("epoll_ctl: listen_sock");

exit(EXIT_FAILURE);

}

// bind server listen socket

struct sockaddr_in serveraddr;

bzero(&serveraddr, sizeof(serveraddr));

serveraddr.sin_family = AF_INET;

char *local_addr="127.0.0.1";

inet_aton(local_addr, &(serveraddr.sin_addr));

serveraddr.sin_port = htons(portnumber);

bind(listenfd, (sockaddr *)&serveraddr, sizeof(serveraddr));

listen(listenfd, LISTENQ);

maxi = 0;

struct sockaddr_in clientaddr;

for ( ; ; ) {

nfds = epoll_wait(epfd,events,20,500); //等待epoll事件的发生

//处理所发生的所有事件

for(i=0; i

{

if(events[i].data.fd==listenfd)//如果新监测到一个SOCKET用户连接到了绑定的SOCKET端口,建立新的连接。

{

connfd = accept(listenfd,(sockaddr *)&clientaddr, &clilen);

if(connfd<0){

perror("connfd<0");

exit(1);

}

//setnonblocking(connfd);

char *str = inet_ntoa(clientaddr.sin_addr);

cout << "accapt a connection from " << str << endl;

//设置用于读操作的文件描述符

ev.data.fd=connfd;

//设置用于注测的读操作事件

ev.events=EPOLLIN|EPOLLET;

//ev.events=EPOLLIN;

//注册ev

epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev);

}

else if(events[i].events&EPOLLIN)//如果是已经连接的用户,并且收到数据,那么进行读入。

{

cout << "EPOLLIN" << endl;

if ( (sockfd = events[i].data.fd) < 0)

continue;

if ( (n = read(sockfd, line, MAXLINE)) < 0) {

if (errno == ECONNRESET) {

close(sockfd);

events[i].data.fd = -1;

} else

std::cout<

} else if (n == 0) {

close(sockfd);

events[i].data.fd = -1;

}

line[n] = '/0';

cout << "read " << line << endl;

//设置用于写操作的文件描述符

ev.data.fd=sockfd;

//设置用于注测的写操作事件

ev.events=EPOLLOUT|EPOLLET;

//修改sockfd上要处理的事件为EPOLLOUT

//epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);

}

else if(events[i].events&EPOLLOUT) // 如果有数据发送

{

sockfd = events[i].data.fd;

write(sockfd, line, n);

//设置用于读操作的文件描述符

ev.data.fd=sockfd;

//设置用于注测的读操作事件

ev.events=EPOLLIN|EPOLLET;

//修改sockfd上要处理的事件为EPOLIN

epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);

}

}

}

return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值