select poll使用

select poll使用
 
 


2.1. 怎样管理多个连接?
“我想同一时候监控一个以上的文件描写叙述符(fd)/连接(connection)/流(stream),应该怎么办?” 

使用 select() 或 poll() 函数。 

注 意:select() 在BSD中被引入,而poll()是SysV STREAM流控制的产物。因此,这里就有了平台移植上的考虑:纯粹的BSD系统可 能仍然缺少poll(),而早一些的SVR3系统中可能没有select(),虽然在SVR4中将其增加。眼下两者都是POSIX. 1g标准,(译者 注:因此在Linux上两者都存在) 

select()和poll()本质上来讲做的是同一件事,仅仅是完毕的方法不一样。两者都通过检验一组文件描写叙述符来检測是否有特定的时间将在上面发生并在一定的时间内等待其发生。 

[重要事项:不管select()还是poll()都不正确普通文件起非常大效用,它们着重用于套接口(socket)、管道(pipe)、伪终端(pty)、终端设备(tty)和其它一些字符设备,可是这些操作都是系统相关(system-dependent)的。] 

2.1.1. 我怎样使用select()函数?
select()函数的接口主要是建立在一种叫'fd_set'类型的基础上。它('fd_set') 是一组文件描写叙述符(fd)的集合。由于fd_set类型的长度在不同平台上不同,因此应该用一组标准的宏定义来处理此类变量: 

    fd_set set;
    FD_ZERO(&set);       /* 将set清零 */
    FD_SET(fd, &set);    /* 将fd增加set */
    FD_CLR(fd, &set);    /* 将fd从set中清除 */
    FD_ISSET(fd, &set);  /* 假设fd在set中则真 */
      
在 过去,一个fd_set通常仅仅能包含少于等于32个文件描写叙述符,由于fd_set事实上仅仅用了一个int的比特矢量来实现,在大多数情况下,检查 fd_set能包含随意值的文件描写叙述符是系统的责任,但确定你的fd_set究竟能放多少有时你应该检查/改动宏FD_SETSIZE的值。*这个值是系 统相关的*,同一时候检查你的系统中的select() 的man手冊。有一些系统对多于1024个文件描写叙述符的支持有问题。[译者注: Linux就是这样 的系统!你会发现sizeof(fd_set)的结果是128(*8 = FD_SETSIZE=1024) 虽然非常少你会遇到这样的情况。] 

select的基本接口十分简单: 

    int select(int nfds, fd_set *readset, fd_set *writeset,
               fd_set *exceptset, struct timeval *timeout);
      
当中: 

nfds     
     须要检查的文件描写叙述符个数,数值应该比是三组fd_set中最大数
     更大,而不是实际文件描写叙述符的总数。
readset    
     用来检查可读性的一组文件描写叙述符。
writeset
     用来检查可写性的一组文件描写叙述符。
exceptset
     用来检查意外状态的文件描写叙述符。(注:错误并非意外状态)
timeout
     NULL指针代表无限等待,否则是指向timeval结构的指针,代表最
     长等待时间。(假设当中tv_sec和tv_usec都等于0, 则文件描写叙述符
     的状态不被影响,但函数并不挂起)
      
函数将返回响应操作的相应操作文件描写叙述符的总数,且三组数据均在恰当位置被改动,仅仅有响应操作的那一些没有改动。接着应该用FD_ISSET宏来查找返回的文件描写叙述符组。 

这里是一个简单的測试单个文件描写叙述符可读性的样例: 

     int isready(int fd)
     {
         int rc;
         fd_set fds;
         struct timeval tv;
    
         FD_ZERO(&fds);
         FD_SET(fd,&fds);
         tv.tv_sec = tv.tv_usec = 0;
    
 rc = select(fd+1, &fds, NULL, NULL, &tv);
         if (rc < 0)
           return -1;
    
         return FD_ISSET(fd,&fds) ? 1 : 0;
     }
      
当然假设我们把NULL指针作为fd_set传入的话,这就表示我们对这样的操作的发生不感兴趣,但select() 还是会等待直到其发生或者超过等待时间。 

[译 者注:在Linux中,timeout指的是程序在非sleep状态中度过的时间,而不是实际上过去的时间,这就会引起和非Linux平台移植上的时间不 等问题。移植问题还包含在System V风格中select()在函数退出前会把timeout设为没有定义的 NULL状态,而在BSD中则不是这样, Linux在这点上遵从System V,因此在反复利用timeout指针问题上也应该注意。] 

2.1.2. 我怎样使用poll()?
poll ()接受一个指向结构'struct pollfd'列表的指针,当中包含了你想測试的文件描写叙述符和事件。事件由一个在结构中事件域的比特掩码确定。当前 的结构在调用后将被填写并在事件发生后返回。在SVR4(可能更早的一些版本号)中的 "poll.h"文件里包含了用于确定事件的一些宏定义。事件的等待 时间精确到毫秒 (但令人困惑的是等待时间的类型却是int),当等待时间为0时,poll()函数马上返回,-1则使poll()一直挂起直到一个指定 事件发生。以下是pollfd的结构。 

     struct pollfd {
         int fd;        /* 文件描写叙述符 */
         short events;  /* 等待的事件 */
         short revents; /* 实际发生了的事件 */
     };
      
于select()十分类似,当返回正值时,代表满足响应事件的文件描写叙述符的个数,假设返回0则代表在规定事件内没有事件发生。如发现返回为负则应该马上查看 errno,由于这代表有发生错误。 

假设没有事件发生,revents会被清空,所以你不必多此一举。 

这里是一个样例 

   /* 检測两个文件描写叙述符,分别为一般数据和高优先数据。假设事件发生
      则用相关描写叙述符和优先度调用函数handler(),无时间限制等待,直到
      发生错误或描写叙述符挂起。*/
   
   #include <stdlib.h>
   #include <stdio.h>
  
   #include <sys/types.h>
   #include <stropts.h>
   #include <poll.h>
  
   #include <unistd.h>
   #include <errno.h>
   #include <string.h>
  
   #define NORMAL_DATA 1
   #define HIPRI_DATA 2
  
   int poll_two_normal(int fd1,int fd2)
   {
       struct pollfd poll_list[2];
       int retval;
  
       poll_list[0].fd = fd1;
       poll_list[1].fd = fd2;
       poll_list[0].events = POLLIN|POLLPRI;
       poll_list[1].events = POLLIN|POLLPRI;
  
       while(1)
       {
           retval = poll(poll_list,(unsigned long)2,-1);
           /* retval 总是大于0或为-1,由于我们在堵塞中工作 */
  
           if(retval < 0)
           {
               fprintf(stderr,"poll错误: %s/n",strerror(errno));
               return -1;
           }
    
           if(((poll_list[0].revents&POLLHUP) == POLLHUP) ||
              ((poll_list[0].revents&POLLERR) == POLLERR) ||
              ((poll_list[0].revents&POLLNVAL) == POLLNVAL) ||
              ((poll_list[1].revents&POLLHUP) == POLLHUP) ||
              ((poll_list[1].revents&POLLERR) == POLLERR) ||
              ((poll_list[1].revents&POLLNVAL) == POLLNVAL))
             return 0;
  
           if((poll_list[0].revents&POLLIN) == POLLIN)
             handle(poll_list[0].fd,NORMAL_DATA);
           if((poll_list[0].revents&POLLPRI) == POLLPRI)
             handle(poll_list[0].fd,HIPRI_DATA);
           if((poll_list[1].revents&POLLIN) == POLLIN)
             handle(poll_list[1].fd,NORMAL_DATA);
           if((poll_list[1].revents&POLLPRI) == POLLPRI)
             handle(poll_list[1].fd,HIPRI_DATA);
       }
   }
      
2.1.3. 我能否够同一时候使用SysV IPC和select()/poll()?
*不能。* (除非在AIX上,由于它用一个无比奇怪的方法来实现这样的组合) 

一般来说,同一时候使用select()或poll()和SysV 消息队列会带来很多麻烦。SysV IPC的对象并非用文件描写叙述符来处理的,所以它们不能被传递给select()和 poll()。这里有几种解决方法,其粗暴程度各不同样: 


全然放弃使用SysV IPC。 :-)

用fork(),然后让子进程来处理SysV IPC,然后用管道或套接口和父进程 说话。父进程则使用select()。 

同上,但让子进程用select(),然后和父亲用消息队列交流。 

安排进程发送消息给你,在发送消息后再发送一个信号。*警告*:要做好 这个并不简单,非常easy写出会丢失消息或引起死锁的程序。 

另外还有其它方法。 

 

 

poll :

 

luanjian2006-7-19 01:47
驱动中poll_wait()函数的疑问

应用程序的select()系统调用,调用驱动中的poll()方法。
不理解的是在以下的poll()方法实现中,首先调用poll_wait将等待队列加入到wait结构中,接下来是个推断语句  
if (dev->rp != dev->wp)
                mask |= POLLIN | POLLRDNORM;  /* readable */
仅仅 考虑可读情况。假设这个if语句的条件不满足,那么就不会返回可读,也就是返回0。那么在这里怎么实现堵塞的呢?也就是说假设在应用的select()系 统中,指定一个等待时间,在这个等待时间里假设没有描写叙述符可读,就一直堵塞。那个这个等待时间是怎么和驱动中的poll()方法联系起来的呢?假设要改动 这个poll()方法怎么改动呢?还有在poll()方法中,怎么指定描写叙述符集中的哪一个是可读的呢?简单的返回POLLIN | POLLRDNORM,是无法指定是哪一个描写叙述符可读的呀?
               
static unsigned int scull_p_poll(struct file *filp, poll_table *wait)
{
        struct scull_pipe *dev = filp->private_data;
        unsigned int mask = 0;

        /*
        * The buffer is circular; it is considered full
        * if "wp" is right behind "rp" and empty if the
        * two are equal.
        */
        down(&dev->sem);
        poll_wait(filp, &dev->inq,  wait);
       // poll_wait(filp, &dev->outq, wait);
        if (dev->rp != dev->wp)
                mask |= POLLIN | POLLRDNORM;  /* readable */
        //if (spacefree(dev))
        //        mask |= POLLOUT | POLLWRNORM;  /* writable */
        up(&dev->sem);
        return mask;
}

siasd2006-7-19 02:14
在调用驱动程序的poll之前,实现调用VFS相关的poll接口的(比方sys_poll等),堵塞、等待时间等的实现是在那个里面完毕的

luanjian2006-7-19 02:28
那么驱动的这个poll()方法总是立马返回的?

siasd2006-7-19 02:49
对啊

luanjian2006-7-19 03:07
是立马返回的,那么假设有一个描写叙述符集当前不可读,也就返回0。但等了一段时间后可读,那么怎么返回mask |= POLLIN | POLLRDNORM;。我的意思是怎么指示给应用程序可读的呢?
那么驱动的poll()方法的作用是什么呢?

siasd2006-7-19 03:19
假设当前不可读,那么在sys_poll->do_poll中当 前进程就会睡眠在等待队列上,这个等待队列是由驱动程序提供的(就是poll_wait中传入的那个)。当可读的时候,驱动程序可能有一部分代码执行了 (比方驱动的中断服务程序),那么在这部分代码中,就会唤醒等待队列上的进程,也就是之前睡眠的那个,当那个进程被唤醒后do_poll会再一次的调用驱 动程序的poll函数,这个时候应用程序就知道是可读的了。

不知道有没有解释清楚啊,呵呵

luanjian2006-7-19 03:24
很感谢。

snow_insky2006-7-19 04:30
POOL方法就是用来支持非堵塞式的訪问,当然是马上返回,可是它会把这次请求放入一个等待队列中,当某个条件满足时,内核会通知应用程序(应用程序的select函数会感知),然后就会接着select操作
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/264271.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何用distinct消除重复记录的同时又能选取多个字段值?

如何用distinct消除重复记录的同时又能选取多个字段值&#xff1f; 需求是&#xff1a;我要消除name字段值重复的记录&#xff0c;同时又要得到id字段的值&#xff0c;其中id是自增字段。 select distinct name from t1 能消除重复记录&#xff0c;但只能取一个字段&#xf…

学计算机需要多少内存,电脑内存多大才够用

现在内存的价钱越来越便宜&#xff0c;很多新装机的朋友都已经在使用1GB的内存&#xff0c;而还有很多人也在给老电脑的内存升级。在升级了物理内存之后&#xff0c;如何有效设置虚拟内存才能获得最大限度的性能提升?网上流传的一些优化虚拟内存的方法真的有效吗?下面学习啦小…

2019十二省联考游记

这次省选真的经历了很多&#xff0c;虽然最后一波三折进了省队&#xff0c;但还是留下了许多遗憾。 DAY1 进考场先看T1&#xff0c;区间线性基&#xff1f;想了想大概像超级钢琴那样做&#xff1f;但trie树上怎么查区间第k大&#xff1f;一时间没想出来。咦&#xff01;暴力60分…

Android开发学习笔记-自定义对话框

系统默认的对话框只能显示简单的标题内容以及按钮&#xff0c;而如果想要多现实其他内容则就需要自定义对话框&#xff0c;下面是自定义对话框的方法。 1、先定义对话框的模版 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:andro…

TreeView控件二(递归算法)

扩展了一下。每个控件都有其独特的写法和用法&#xff0c;treeview就是这样的一个控件。做个类似资源管理器的页面。如果逐层遍历&#xff0c;代码会不断重复&#xff0c;所以这时需要用递归算法 Codepublic static void TreeBindMethod(TreeView tvFile,string target) …

计算机中桌面中不显示U盘图标,电脑不显示u盘怎么回事 电脑不显示u盘的解决办法...

在平时的工作中&#xff0c;我们会经常使用到U盘来拷贝资料&#xff0c;U盘便于携带并且储存量大&#xff0c;所以很受大家的欢迎。但是平时我们在拷贝资料将U盘插入电脑中&#xff0c;会发现U盘在电脑中不显示&#xff0c;即使在桌面上仔细寻找也无济于事。这种情况小编也有遇…

js中的cookie使用和vue-cookie的使用

在HTTP协议的定义中&#xff0c;采用了一种机制来记录客户端和服务器端交互的信息&#xff0c;这种机制被称为cookie&#xff0c;cookie规范定义了服务器和客户端交互信息的格式、生存期、使用范围、安全性。 在JavaScript中可以通过 document.cookie 来读取或设置这些信息。由…

asp上传错误:此键已与该集合的一个元素关联

在做一个图片上传的时候&#xff0c;提示“此键已与该集合的一个元素关联”&#xff0c;错误是出现在无组件上传的文件里。 查了一下原来是由于提交数据的页面中出现了页面控件重名的问题&#xff0c;可能是页面中用到的多选项同名引起的&#xff0c;虽然报错&#xff0c;但不影…

spring-在配置文件中配置DAO时直接引用DataSource

一、创建spring项目 项目名称&#xff1a;spring101306二、在项目上添加jar包 1.在项目中创建lib目录 /lib 2.在lib目录下添加spring支持 commons-logging.jar junit-4.10.jar log4j.jar mysql-connector-java-5.1.18-bin.jar …

计算机基础知识总结及自学,计算机基础知识的简单总结

我说明一下&#xff0c;本文只是基于作者的个人理解所作出的总结&#xff0c;如果有什么不对的地方&#xff0c;希望大家给我指正&#xff0c;我会尽快更正的。我也想通过51cto这个大平台&#xff0c;能够与大家一同学习&#xff0c;一同交流&#xff0c;一同进步。1.计算机的组…

【转载】网络流和最小费用流

这段时间复习了下网络流模型&#xff0c;感觉比以前的理解有了长足进展&#xff0c;虽然我知道这东西难就难在建模上&#xff0c;而它的算法本身其实难度不大&#xff0c;但我还是决定说一些我的理解&#xff0c;毕竟理解了本质的东西运用起来才会更灵活。最大流的求解一般有两…

实验1.1

转载于:https://www.cnblogs.com/P201821430028/p/10689308.html

札记__ADT:URL,Lua:strlen方法

2019独角兽企业重金招聘Python工程师标准>>> 01&#xff0c;Android ADT 在线更新的URL&#xff1a; https://dl-ssl.google.com/android/eclipse/ 02&#xff0c;Lua中字符串长度的判断可以使用 # local str "abcabc" print(#str) --6 print(#"a…

vue路由添加.html,怎么使用VueRouter的addRoutes方法实现动态添加用户的权限路由

怎么使用VueRouter的addRoutes方法实现动态添加用户的权限路由发布时间&#xff1a;2021-04-26 13:34:44来源&#xff1a;亿速云阅读&#xff1a;76作者&#xff1a;小新小编给大家分享一下怎么使用VueRouter的addRoutes方法实现动态添加用户的权限路由&#xff0c;希望大家阅读…

vue中的适配:px2rem

这应该是vue项目在适配移动端时候&#xff0c;最简单的方法之一下面是基本步骤&#xff08;使用cnpm&#xff09;1.下载并引入lib-flexible cnpm install --save lib-flexible 在main.js中 &#xff1a;import ‘lib-flexible/flexible’2.引入px2rem-loader cnpm install --sa…

SQL Server 2005参考:Apply运算符

SQL Server 2005参考&#xff1a;Apply运算符 使用 APPLY 运算符可以为实现查询操作的外部表表达式返回的每个行调用表值函数。表值函数作为右输入&#xff0c;外部表表达式作为左输入。通过对右输入求值来获得左输入每一行的计算结果&#xff0c;生成的行被组合起来作为最终输…

Java高级篇 -- List选择及优化

为什么80%的码农都做不了架构师&#xff1f;>>> 在java编程中&#xff0c;我们常常使用到java自带的集合类List 以下为几点简单的优化建议&#xff1a; 1.Vector还是ArrayList Vector有其特有有点&#xff0c;其每个方法都为同步方法【synchronized】&#xff0c…

韶关无线电厂台式计算机,中国芯片30年的历史 它背后有哪些不为人知的故事?...

1972年&#xff0c;自主研制的大规模1973年&#xff0c;北京大学、北京有线电厂等单位联合研制150计算机&#xff0c;该机字长数48位&#xff0c;运算能力达每秒100万次&#xff0c;主要用于石油、地质、气象和军事部门。1973年&#xff0c;韶关市无线电厂研制成功晶体管161型“…

Java————迷宫问题

它表示一个迷宫&#xff0c;其中的1表示墙壁&#xff0c;0表示可以走的路&#xff0c;只能横着走或竖着走&#xff0c;不能斜着走&#xff0c;要求编程序找出从左上角到右下角的最短路线。 package algorithm_java;import java.util.Scanner; import java.util.Stack;/*** 路径…

PB中函数测试遇到的问题

在PB中写了一个函数&#xff0c;需要连接两个数据库 tr_1,tr_2&#xff0c;测试时报错&#xff08;无法连接到第二个数据库&#xff09;&#xff0c;再确定该函数代码没有其它问题后&#xff0c;选中该函数&#xff0c;右键Regenerate后&#xff0c;测试成功.转载于:https://ww…