#include
#include
#include
#include
#include
int main(void)
{
int fds[2];//定义int的数组,由于存放两个文件描述符
char buf[7];
int i,rc,maxfd;
unsigned int tmp1,tmp2,tmp3;
fd_set inset1,inset2 //定义两个fd_set的变量,具体类型见内核原代码,一定要遵循内核函数规则,不要
//乱定义变量,依葫芦画瓢就可以了.
struct timeval tv; // 定义一个结构体,类型为struct timeval,名称为tv
if((fds[0]=open("hello1",O_RDWR |O_CREAT,0666))<0)//打开一个文件,并且判断是否出错
{
perror("open hello1");
}
if((fds[1]=open("hello2",O_RDWR|O_CREAT,0666))<0)
{
perror("open hello2");
}
if((rc=write(fds[0],"hello!\n",7)))//向hello1这个文件中写hello !, 长度为7个字节
{
printf("rc=%d\n",rc);//打印write返回的长度
}
lseek(fds[0],0,SEEK_SET);//移动文件的读写指针,让起从文件头开始,这不很重要
printf("the fds[0] is %d\n",fds[0]);//打印文件描述符
printf("the fds[1] is %d\n",fds[1]);
maxfd=fds[0]>fds[1]?fds[0]:fds[1];//判断这两个文件描述符中的最大值
FD_ZERO(&inset1);
FD_SET(fds[0],&inset1);
FD_ZERO(&inset2);
FD_SET(fds[1],&inset2);//见后面的注释
tv.tv_sec=2;
tv.tv_usec=0;//时间设置为2s
while(FD_ISSET(fds[0],&inset1)||FD_ISSET(fds[1],&inset2))
{
tmp3=select(maxfd+1,&inset1,&inset2,NULL,&tv);
printf("the tmp3 is %d\n",tmp3);
if(select(maxfd+1,&inset1,&inset2,NULL,&tv)<0)
{
perror("select");
}
else
{
tmp1=FD_ISSET(fds[0],&inset1);
printf("the tmp1 is %d\n",tmp1);
//if(FD_ISSET(fds[0],&inset1))
if(tmp1)
{
rc=read(fds[0],buf,7);
if(rc>0)
{
buf[rc]='\0';
printf("read:%s\n",buf);
}
else
{
perror("read");
}
}
tmp2=FD_ISSET(fds[1],&inset2);
printf("the tmp2 is %d\n",tmp2);
//if(FD_ISSET(fds[1],&inset2))
if(tmp2)
{
//printf("the inset2 is :%d\n",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(5);
}
}
}
exit(0);
}
/*-----------------------------------------------------
1.select函数说明:
前面的fcntl函数解决了文件的共享问题,接下来该来处理IO复用的情况
IO处理的模型有5种:
阻塞IO模型:若所调用的IO函数没有完成相关的功能就会使进程挂起,直到
相关数据到才会出错返回.
非阻塞模型:当请就的IO操作不能完成时,则不让进程睡眠.而且返回一个错误.
IO多路转接模型:如果请求的IO操作阻塞,且它不是真正阻塞IO,而是让其中的
一个函数等待,在这期间,IO还能进行其他的操作.
信号驱动IO模型:通过安装一个信号处理程序,系统可以自动捕获特定的信号的到来,
从而启动IO.
异步IO模型:当一个描述符已准备好,可以启动IO时,进程会通知内核.现在,
并不是所有的系统都支持这种模型.
2.select函数格式
1)所需要的头文件:
#include
#include
#include
2)函数原型
int select(int numfds,fd_set *readfs,fd_set *writefds,fd_set *exeptfds,
struct timeval *timeout)
3)输入参数
numfds:需要检查的号码最大的文件描述符加1
readfds:由select()监视的读文件描述符集合
writefds:由select()监视的写文件描述符集合
exeptfds:由select()监视的异常处理文件描述符集合
timeout
NULL:永远等待,知道捕捉到信号或文件描述符已准备好为止.
具体值:struct timeval类型的指针,若等待为timeout时间还没有文件描述符准备好,
就立刻返回.
0:从不等待,测试所有指定的描述符并立即返回.
4函数返回值
成功:准备好的文件描述符
-1:出错.
3.selsect 文件描述符处理函数
FD_ZERO(fd_set *set) //清除一个文件描述符集
FD_SET(int fd,fd_set *set) //将一个文件描述符加入文件描述符集中
FD_CLR(int fd,fd_set *set) //将一个文件描述符从文件描述符中清除
FD_ISSET(int fd,fd_set *set) //测试该集中的一个给定位是否有变化
一般来说,在使用select函数之前,首先使用FD_ZERO和FD_SET来初始化文件描述符
集,在使用了select函数时,可循环使用FD_ISSET测试描述符集,在执行完对相关
文件描述符后,使用FD_CLR来清除描述符集.
4.struct timeval类型的指针,该结构体如下所示:
struct timeval
{
long tv_sec ; //second
long tv_unsec ; //and microseconds
}
--------------------------------------------------------*/
阅读(646) | 评论(0) | 转发(0) |