快捷搜索:  汽车  科技

java怎么自动生成uml图(编程之美IO多路复用)

java怎么自动生成uml图(编程之美IO多路复用)另外,在客户端众多的情况下,无论是select还是poll函数在执行一段时间后效率都是直线下降的,因为实际中处于就绪状态的客户端毕竟是少数。前面刚说了没有绝对完美的东西,poll也存在着几个比较影响人心情的问题:poll函数相比select函数有个质的飞跃——对文件描述符的个数不在限制,虽然没有解决开销大的问题,不过十全十美的东西确实也不存在对吧,这个道理放在程序开发上也是如此。poll函数和select函数没有本质上的区别。poll将用户传入的数组拷贝到内核,通过查询每个fd对应的设备状态,如果设备就绪则在设备等待队列中加入一项并继续遍历,如果遍历完所有fd后没有发现就绪设备,就把当前进程挂起,直到设备就绪或者超时,被唤醒后重新对fd进行新的遍历。至于poll为什么没有了对文件描述符个数的限制,是因为在该函数使用链表作为存储结构,链表的特性就是可以充分使用系统空间,非常灵活。对链表感兴趣

各位看官大家好,在上一篇文章中,我们详细讲解了select函数,也在文末上传了实现代码。今天我们来了解一下Poll函数,他和select又有哪些不同,哪些相似。

java怎么自动生成uml图(编程之美IO多路复用)(1)

很尴尬我找不到合适的配图

Poll函数详解

在上一篇文章中我们提到select有如下几个缺点:

  1. select函数能打开的文件描述符(fd)有限;
  2. select采用轮询的遍历方式,导致效率较低;
  3. 由于执行此函数需要一个非常大的struct(结构体)来存储文件描述符属性,会占用很多的系统资源

要知道这些问题是select设计伊始就已经存在的,只要使用就势必存在上述的缺点。

poll函数相比select函数有个质的飞跃——对文件描述符的个数不在限制,虽然没有解决开销大的问题,不过十全十美的东西确实也不存在对吧,这个道理放在程序开发上也是如此。

poll函数和select函数没有本质上的区别。poll将用户传入的数组拷贝到内核,通过查询每个fd对应的设备状态,如果设备就绪则在设备等待队列中加入一项并继续遍历,如果遍历完所有fd后没有发现就绪设备,就把当前进程挂起,直到设备就绪或者超时,被唤醒后重新对fd进行新的遍历。

至于poll为什么没有了对文件描述符个数的限制,是因为在该函数使用链表作为存储结构,链表的特性就是可以充分使用系统空间,非常灵活。对链表感兴趣的朋友可以百度相关内容,资源非常多,这里不再累述。

前面刚说了没有绝对完美的东西,poll也存在着几个比较影响人心情的问题:

  • 由于一直进行遍历,必定会出现无用重复的循环,且无法避免;
  • fd的数组整体复制在用户态和内核地址空间中,但这些fd不一定会用到,也就是说这些复制操作不一定有意义。
  • 如果对收到的fd信息没有处理,那么下次执行的时会再次报告该fd,执行多少次就报告多少次(看起来poll函数确实记性不好。)

另外,在客户端众多的情况下,无论是select还是poll函数在执行一段时间后效率都是直线下降的,因为实际中处于就绪状态的客户端毕竟是少数。

下面我们来具体学习一下poll函数的原型及参数含义:

int poll(struct pollfd fd[] nfds_t nfds int timeout);

struct pollfd fd【】: 一个结构数组 struct pollfd结构如下:

struct pollfd{

int fd; //文件描述符

short events; //请求事件

short revents; //返回事件

};

nfds_t nfds:监听描述符的个数

int timeout:阻塞时间单位:ms

这里要注意一下poll函数的返回值,有以下三种情况:

  1. >0:数组fd中准备好读、写或出错状态的那些socket描述符的总数量;
  2. =0:数组fd中所有socket描述符准备好读、写,或出错;
  3. -1:poll调用错误,全局变量为error。

下面是具体的实现代码:

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <strings.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <poll.h>

int main()

{

int fd = open("/dev/input/mouse1" O_RDONLY);//初始化文件描述符

if (fd < 0)

{

perror("open");

return -1;

}

printf("open success\n");

struct pollfd fds[2];

fds[0].fd = 0; //把键盘加入集合中

fds[0].events = POLLIN;

fds[1].fd = fd; //把鼠标加入集合中

fds[1].events = POLLIN;

int retval;

char buf[100];

while (1)

{

retval = poll(fds 2 1000);

if (retval < 0)

{

perror("poll");

break;

}

else if (0 == retval)

{

printf("timeout..............\n");

continue;

}

if (fds[0].revents & POLLIN) //判断是否是键盘产生事件

{

read(0 buf sizeof(buf));

printf("Data from keyboard!\n");

}

if (fds[1].revents & POLLIN)

{

read(fd buf sizeof(buf));

printf("Date from Mouse!\n");

}

}

close(fd);

return 0;

}


鉴于之前有朋友反应服务器代码太长,所以这里我放了一篇对输入设备事件处理的C代码,涉及到了一点文件IO的知识,不过很简单,代码中也有备注。对本篇内容有疑惑的看官欢迎留言或者私信,看到了都会回复,最后谢谢您的收看!

猜您喜欢: