本文共 3777 字,大约阅读时间需要 12 分钟。
grep可以实现,grep可以进行模糊查找和精确查找,可以只输内容,也可以同时输出行号:
grep -n "gq" ./gq.txt ;模糊搜索,输出包含字符串的行内容和行号grep -nw "gq" ./gq.txt ;精准搜索,输出字符串的行内容以及行号
select系统调用是可以,监听用户所感兴趣的文件描述符上的可读、可写、异常事件,然后阻塞给出反馈文件描述符,用户根据select反馈的文件描述符来判断是否发生了感兴趣文件描述符上的可读】可写、异常事件等。
select系统调用的原型如下:
/* According to POSIX.1-2001, POSIX.1-2008 */#include/* According to earlier standards */#include #include #include int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);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);
参数:
其中用于设置监听文件描述符集合函数就是:
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); //清空集合中的所有文件描述符
关于select中监听的文件描述符的就绪条件,在网络编程中的情况如下:
设定非阻塞IO的方法:
对于给定描述符,有两种方法指定非阻塞IO:
poll与select类似,也是轮询文件描述符集合,测试其中是否有就绪的文件描述符,其函数原型如下:
#includeint poll(struct pollfd *fds, nfds_t nfds, int timeout);struct pollfd { int fd; /* file descriptor */ short events; /* requested events */ short revents; /* returned events */};
参数:
poll支持的事件如下:
在读文件的时候还要考虑被文件中断时候的情况,可以采用do-while的形式来写代码
epoll是通过一组函数来实现IO复用的,epoll的简介如下:
epoll可以打开的文件描述符是系统所能够打开的文件描述符的最大上限。
epoll中的文件描述符采用通知机制,每个fd都可以注册一个callback函数,只有活跃的fd才会调用callback函数,所以epoll是异步的,select和poll可以理解为同步。
而且epoll是通过共享内存mmap来实现内核空间与用户空间的交互的,相比于select和poll的内存拷贝就很高效。
epoll的内部实现不是维护一个文件描述符表的,而是红黑树如下:
将每个文件描述符挂载在红黑树的结点上,还可以挂载回调函数。
就绪的事件会放在一个就绪链表中,所以epoll的实现依靠两种数据结构:红黑树+就绪链表
Linux中epoll的相关函数有三个:
最后一个参数是属性,每个红黑树节点上不仅仅有文件描述符,还有对应的回调函数
wait可以阻塞也可以设置为非阻塞(超时时间),注意event与events的区别
wait返回的是就绪的事件数量,根据返回的数量进行遍历就绪事件,判断用户等待的事件是否发生。通过事件的结构体成员即可查询事件
最重要的就是epoll_wait()函数:
还有epoll的工作模式:
先看一下整体对比的区别:
下面列出三者之间的关系:
下面通过事件集、最大支持文件描述符数量、工作模式、实现方式等四个方面来比较三者的异同:
首先,三个系统调用都是通过结构体变量来告诉内核,要监听哪些文件描述符上的哪些事件,并且使用相应类型的结构体来获取内核处理的结果,也就是就绪的文件描述符事件集合。
poll和epoll可以使用nfds和maxevents参数来指定最多监听的文件描述符和事件,这两个数值的大小取决于系统能够打开的最大值。但是select允许打开的文件描述符通常是有限的,虽然可以修改这个限制,但是可能导致不可预期后果。
select和poll都只能工作在低效的LT模式,epol可以工作在高效的ET模式,并且epoll还支持EPOLLONESHOT事件,该事件可以进一步减少可读、可写、异常事件被触发的次数。
从实现原理上来说, select和poll采用的都是轮询的方式,即每次调用都要扫描整个注册文件描述符集合,并将其中就绪的文件描述符返回给用户程序,因此它们检测就绪事件的算法的时间复杂度是O(n)。epoll_wait不同,它采用的是回调的方式。内核检测到就绪的文件描述符时,将触发回调函数,回调函数就将该文件描述符上对应的事件插入内核就绪事件队列。内核最后在适当的时机将该就绪事件队列中的内容拷贝到用户空间。因此 epoll_wai无须轮询整个文件描述符集合来检测哪些事件已经就绪,所以其算法时间复杂度是O(1)。
但是,当活动连接比较多的时候, epoll_wait f的效率未必比 select和pol高,因为此时回调函数被触发得过于频繁。所以 epoll_wait适用于连接数量多,但活动连接较少的情况。转载地址:http://uxwzi.baihongyu.com/