目录
一:select()、pselect()函数
select()、pselect()函数与recv()和send()等直接操作文件描述符不同,它是对需要操作的文件描述符进行一个查询和监控的一个作用。
1.函数原型:
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
//select
int select(int nfds, fd_set *readfds, fd_set *writefds, \
fd_set *exceptfds, struct timeval *timeout);
struct timespec {
long tv_sec;
long tv_usec; //微秒
}
//pselect
int pselect(int nfds, fd_set *readfds, fd_set *writefds, \
fd_set *exceptfds, const struct timeval *timeout, \
const sigset_t *sigmask);
struct timespec {
long tv_sec;
long tv_nsec; //纳秒
}
2.参数简介:
- nfds:一个整形变量,需要注意的是它会比描述符集合中的最大值+1。
- readfds:这个文件描述符集合会监视文件集合中的任何文件是否有数据可读,当select函数返回时,readfds将清除其中不可读的文件描述符,只留下可读的文件描述符,即可被函数recv()、read()等进行读数据的操作。
- writefds:这个文件描述符集合会监视文件集合中的任何文件是否有数据可写,当select函数返回时,writefds将清除其中不可写的文件描述符,只留下可写的文件描述符,即可被函数send()、write()等进行写数据的操作。
- exceptfds:这个文件描述符集合会监视文件集合中的任何文件是否发生错误,当然, 它也有另一个用途, 就是能够监视外带的数据OOB,将外数据使用MSG_OOB标志发送到套接字上,当select函数返回时,readfds将清除其中的其他文件描述符, 只留下可读OOB数据。
- timeout:设置超时时间,等待期间会一直阻塞,设置为0时, 会立即返回。
- sigmask:信号掩码。
3.返回值:
- 返回值为0:超时返回为0
- 返回值为大于0:监视的文件集中有文件描述符符合要求。
- 返回值为-1:表示发生错误,错误值由errno指定。
值 | 含义 | 值 | 含义 |
EBADF | 参数s不是合法描述符 | EINVAL | 传递了不合法参数 |
EINTR | 接收到中断信号 | ENOMEM | 没有足够内存 |
函数select()和pselect()允许监视多个文件描述符,当一个或者多个监视的文件描述符准备就绪,可以进行IO操作的时候返回。当所有的文件集合均为NULL,则表示等待一段时间。
通常使用4个宏操作文件描述符的集合。
FD_ZERO():清理文件描述符集合。
FD_SET():向某个文件描述符集合中加入文件描述符。
FD_CLR():从某个文件描述符的集合中取出某个文件描述符。
FD_ISSET():测试某个文件描述符是否为某个集合中一员。
4.select()实例
#include <stdio.h>
#include <sys/time.h>
#include <sys/tpyes.h>
#include <unistd.h>
int main(void)
{
fd_set rd;
struct timeval tv;
int err;
FD_ZERO(&rd);
FD_SET(0, &rd); /*添加标准输入*/
tv.tv_sec = 5;
tv.tv_usec = 0;
err = selec(0+1, &rd, NULL, NULL, &tv);
if (err == -1)
peeror("select()");
else if (err)
printf("Data is avaliable now!\n");
else
printf("time out \n");
return 0;
}
5.pselect()函数
基本上与select()使用一致,最大的区别是pselect()能够多一个信号处理, 同时pselect设置后无法无法修改延时的值,select()后面可以改变timeout的值。
6.pselect()实例
int child_events = 0;
void child_sig_handler (int x) {
child_events++;
signal(SIGCHLD, child_sig_handler);
}
int main(int argc, char *argv[])
{
sigset_t sigmask, orig_sigmask;
sigmptyset(&sigmask); /*清空信号*/
sigaddset(&sigmask, SIGCHLD);
/*设定信号SIG_BLOCK的掩码sigmask, 并将原始的掩码保持至orig_sigmask*/
sigprocmask(SIG_BLOCK,&sigmask,&orig_sigmask);
signal(SIGCHLD, child_sig_handler);
while(1) {
for(; child_events > 0; child_events--) {
/*处理动作*/
}
r = pselect(nfds, &rd, &wr, &er, 0, &orig_sigmask);
/*其他操作*/
}
return 0;
}
二:poll()函数与ppoll()函数
除了select函数进行文件描述符的监视, 还有一组函数也有相似的功能,就是poll()与ppoll()函数。
1.poll()函数原型
#include <poll.h>
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
int ppoll(struct pollfd *fds, nfds_t nfds, const stuct timespec *timeout,\
const sigset_t *sigmask);
struct pollfd {
int fd; /*文件描述符*/
short events; /*请求的事件*/
short revents; /*返回的事件*/
};
2.参数说明:
- fds:指向结构pollfd数组的指针,监视的文件描述符和条件放在里面。
- nfds:比监视的最大描述符大1的值。
- timeout:超时时间,单位毫秒,为负值时, 表示永远等待。
3.返回值说明:
- 返回值为0:超时返回为0
- 返回值为大于0:监视的文件集中有文件描述符符合要求。
- 返回值为-1:表示发生错误,错误值由errno指定。
值 | 含义 | 值 | 含义 |
EBADF | 参数s不是合法描述符 | EINVAL | 传递了不合法参数 |
EINTR | 接收到中断信号 | ENOMEM | 没有足够内存 |
值 | 含义 | 值 | 含义 |
POLLIN | 有数据到来,文件描述符可读 | POLLNVAL | 非法请求 |
POLLRPI | 有紧急数据可读,列如外带数据 | POLLRDNORM | 与POLLIN相同 |
POLLOUT | 文件可写 | POLLRDBAND | 优先数据可读 |
POLLRDHUP | 流式套接字半关闭 | POLLWRNORM | 与POLLOUT相同 |
POLLERR | 错误发生 | POLLWRBAND | 优先数据可写 |
POLLHUP | 关闭 |
区别基本与select()和pseletc()相同;
具体实例参考上面的select()和pselect();
fcntl(s, F_SETFL, NONBLOCK); 设置为非阻塞。