免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 5444 | 回复: 17
打印 上一主题 下一主题

[函数] 关于select函数的问题 [复制链接]

论坛徽章:
1
2015元宵节徽章
日期:2015-03-06 15:53:22
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2015-01-30 18:43 |只看该作者 |倒序浏览
大家应该见过以下的程序吧?在介绍select函数时使用的例子,大概的功能是:实现将文件hello1 里的内容读出,并将此内容每隔10s 写入hello2 中去。

本人十分困惑,为什么执行的时候只能反复写入hello2,而hello1只读取一次就没了,即红色部分使用FD_ISSET函数检测文件描述符准备情况时只有后者准备好了,而第一个始终得到0。这是为什么呢?
按照这个while 循环来看,应该是反复读和写才对啊?


/*循环测试该文件描述符是否准备就绪,并调用select函数对相关文件描述符做对应操作*/
while(FD_ISSET(fds[0],&inset1)||FD_ISSET(fds[1],&inset2)){
     if(select(maxfd+1,&inset1,&inset2,NULL,&tv)<0)
            perror("select");
     else{
           if(FD_ISSET(fds[0],&inset1)){
                 rc = read(fds[0],buf,7);
                 if(rc>0){
                     buf[rc]='\0';
                     printf("read: %s\n",buf);
                 }else
                     perror("read");
             }
            if(FD_ISSET(fds[1],&inset2)){
                  rc = write(fds[1],buf,7);
                  if(rc>0){
                      buf[rc]='\0';
                      printf("rc=%d,write: %s\n",rc,buf);
             }else
                      perror("write");
             sleep(10);
             }
      }
}

论坛徽章:
2
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:56:11
2 [报告]
发表于 2015-01-30 20:33 来自手机 |只看该作者
读到文件结尾就结束了吧

论坛徽章:
1
2015元宵节徽章
日期:2015-03-06 15:53:22
3 [报告]
发表于 2015-01-30 22:45 |只看该作者
回复 2# cobras


    没有结束,有个while语句,会一直循环地写下去,但是不会一直循环地读,也就是 if(FD_ISSET(fds[0],&inset1))里FD_ISSET这个函数第一次调用时返回了1,但是以后就都是返回了0;而if(FD_ISSET(fds[1],&inset2))里FD_ISSET这个函数每次调用都返回了1。这点不是很理解。希望朋友能亲自试一下,或者认真看一下,小弟真的很疑惑。

论坛徽章:
5
戌狗
日期:2014-06-09 10:29:10酉鸡
日期:2014-12-01 16:05:27处女座
日期:2015-01-07 18:35:262015亚冠之水原三星
日期:2015-06-03 09:26:222015亚冠之布里斯班狮吼
日期:2015-06-15 10:53:54
4 [报告]
发表于 2015-01-31 23:20 |只看该作者
需不需要用FD_CLR()  控制一下。。。

方便把之前的代码贴上来吗

论坛徽章:
1
2015元宵节徽章
日期:2015-03-06 15:53:22
5 [报告]
发表于 2015-02-01 13:24 |只看该作者
回复 4# kaede_1

以下是整个程序,希望朋友亲自试一下,就复制粘贴一下,编译一下就可以运行了,看一下运行结果。
/*select.c*/
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
int main(void)
{
    int fds[2];
    char buf[7];
    int i,rc,maxfd;
    fd_set inset1,inset2;
    struct timeval tv;
/*首先按一定的权限打开hello1文件*/
    if((fds[0] = open ("hello1", O_RDWR|O_CREAT,0666))<0)
    perror("open hello1");
/*再按一定的权限打开hello2文件*/
    if((fds[1] = open ("hello2", O_RDWR|O_CREAT,0666))<0)
    perror("open hello2");
    if((rc = write(fds[0],"Hello!\n",7)))
    printf("rc=%d\n",rc);
    lseek(fds[0],0,SEEK_SET);
/*取出两个文件描述符中的较大者*/
    maxfd = fds[0]>fds[1] ? fds[0] : fds[1];
/*初始化读集合inset1,并在读集合中加入相应的描述集*/
    FD_ZERO(&inset1);
    FD_SET(fds[0],&inset1);
/*初始化写集合inset2,并在写集合中加入相应的描述集*/
    FD_ZERO(&inset2);
    FD_SET(fds[1],&inset2);
    tv.tv_sec=2;
    tv.tv_usec=0;
    /*循环测试该文件描述符是否准备就绪,并调用select函数对相关文件描述符做对应操作*/
while(FD_ISSET(fds[0],&inset1)||FD_ISSET(fds[1],&inset2)){
     if(select(maxfd+1,&inset1,&inset2,NULL,&tv)<0)
            perror("select");
     else{
           if(FD_ISSET(fds[0],&inset1)){
                 rc = read(fds[0],buf,7);
                 if(rc>0){
                     buf[rc]='\0';
                     printf("read: %s\n",buf);
                 }else
                     perror("read");
             }
            if(FD_ISSET(fds[1],&inset2)){
                  rc = write(fds[1],buf,7);
                  if(rc>0){
                      buf[rc]='\0';
                      printf("rc=%d,write: %s\n",rc,buf);
             }else
                      perror("write");
             sleep(10);
             }
      }
}

论坛徽章:
5
戌狗
日期:2014-06-09 10:29:10酉鸡
日期:2014-12-01 16:05:27处女座
日期:2015-01-07 18:35:262015亚冠之水原三星
日期:2015-06-03 09:26:222015亚冠之布里斯班狮吼
日期:2015-06-15 10:53:54
6 [报告]
发表于 2015-02-02 09:12 |只看该作者
兄台,你这个程序没有问题啊
你看着只读一次,实际上是读一次后就到结尾了,而FD_ISSET(fds[0],&inset1)一直为真,因此会在结尾不停地读,看上去没什么效果。
对于write,则是不停地将最后一个buf里的内容,写入hello2.

不知道这个是不是你想要的...

论坛徽章:
1
2015元宵节徽章
日期:2015-03-06 15:53:22
7 [报告]
发表于 2015-02-02 19:21 |只看该作者
本帖最后由 AnkerLi 于 2015-02-02 19:23 编辑

回复 6# kaede_1


    你的回答不对。不信你可以复制粘贴,编译运行一下,一试便知。

    首先,我并没有说这个程序有问题,只是有几点迷惑之处,在上面已经提出来了。
    其次,你说FD_ISSET(fds[0],&inset1)一直为真,这个是不对的,如果一直为真,是不是每次都会打印“read:”呢?且不管它读到什么,至少会打印“read:“,哪怕是乱码;
    在次,经过本人在
           else{
           if(FD_ISSET(fds[0],&inset1)){
                 rc = read(fds[0],buf,7);
                 if(rc>0){
                     buf[rc]='\0';
                     printf("read: %s\n",buf);
                     printf("RRR: %d\n",FD_ISSET(fds[0],&inset1);
后加了一行代码(以上红色部分)运行后,发现FD_ISSET(fds[0],&inset1)只有在第一次运行时为真,其余为假。

   

论坛徽章:
5
戌狗
日期:2014-06-09 10:29:10酉鸡
日期:2014-12-01 16:05:27处女座
日期:2015-01-07 18:35:262015亚冠之水原三星
日期:2015-06-03 09:26:222015亚冠之布里斯班狮吼
日期:2015-06-15 10:53:54
8 [报告]
发表于 2015-02-03 08:36 |只看该作者
兄台,我肯定是执行了之后才说的,算了,直接上执行结果吧
  1. rc=7
  2. read: Hello!

  3. rc=7,write: Hello!

  4. read: Success
  5. rc=7,write: Hello!

  6. read: Success
  7. rc=7,write: Hello!

  8. read: Success
  9. rc=7,write: Hello!

  10. read: Success
  11. rc=7,write: Hello!

  12. read: Success
  13. rc=7,write: Hello!

  14. read: Success
  15. rc=7,write: Hello!

  16. read: Success
  17. rc=7,write: Hello!
复制代码
下面这个是hello2的内容
  1. [ L:C$ ]cat hello2
  2. Hello!
  3. Hello!
  4. Hello!
  5. Hello!
  6. Hello!
  7. Hello!
  8. Hello!
  9. Hello!
  10. Hello!
  11. Hello!
  12. Hello!
  13. Hello!
复制代码
而你所谓红色那条语句没执行,是因为你放的分支不对,read函数第二次之后的返回值(rc)都不会再进入printf分支!即rc>0,不成立!

论坛徽章:
0
9 [报告]
发表于 2015-02-03 09:17 |只看该作者
select之后要重新加入fd_set好吧。

论坛徽章:
1
2015元宵节徽章
日期:2015-03-06 15:53:22
10 [报告]
发表于 2015-02-03 23:09 |只看该作者
回复 8# kaede_1


    非常感谢你能亲自试一下,是的,你运行的结果和我运行的结果是一样的。
    但是我的疑惑点正如上面所说的,不明白为什么后面循环的程序里面只会一直写,不会一直读。根据你所说的是因为读的文件到了最后的原因,但是至少它会执行printf("read: %s\n",buf);这个语句吧,也就是说会打印一个"read:“,哪怕是乱码。但是情况是只会一直写,不会一直读,即,select函数返回的值中,只有写是可执行,读不可执行。小弟不明白的是这个。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP