本篇主要讲解select描述符监听
当我们read读取管道中的数据,此时管道中没有数据时,会阻塞,程序会卡在哪里,无法继续往下执行,有没有办法不让程序卡住?可以设定一个时间,在这个时间内使用select监听描述符是否有数据可以读,这就是select的作用。select在网络编程中显得尤为重要。
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
参数:
nfds 要监听的描述符+1
readfds 读设备描述符组
writefds 写设备描述符组
exceptfds 其他设备描述符组
timeout 超时时间
struct timeval{
long tv_sec;/*秒*/
long tv_usec;/*微妙*/
};
返回值:
-1 错误
0 代表此时设备中没有数据可以进行读或者写
>0 代表有数据可以进行读写
描述符设置:
int FD_ISSET(int fd, fd_set *set); //描述符是否存在
void FD_SET(int fd, fd_set *set); //描述符添加
void FD_ZERO(fd_set *set); //描述符清零
参数:
fd 文件描述符
set 描述符集
实例:
//pipe.h
#ifndef PIPE_H
#define PIPE_H
typedef int (*phandler_t)(char *buf,int size);
//handler是回调函数 数据通过回调进UI层 中间层和UI层是同步关系
extern int pinit(char *name,int flag,phandler_t handler);
extern int pdestroy();
extern int psend(char *buf,int size);
#endif
//pipe.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include "pipe.h"
static int pfd;
static int pflag;
static pthread_t pthid;
static int state;
static char filename[256];
static int (*postdata)(char *buf,int size);
static void *prun(void* arg){
char buf[4096];
fd_set rfds;
struct timeval t_out;
while(state){
FD_ZERO(&rfds);
FD_SET(pfd,&rfds);
t_out.tv_sec=0;
t_out.tv_usec=200000;
int err=select(pfd+1,&rfds,NULL,NULL,&t_out);
if (err==-1) break;
else if (err==0) {
//printf("----- out time\n");
continue;
}
bzero(buf,4096);
int size=read(pfd,buf,4096); //阻塞
if (size==0) exit(0);
if (postdata!=NULL) postdata(buf,size);
}
}
int pinit(char *name,int flg,phandler_t handler){
postdata=handler;
pflag=flg;
strcpy(filename,name);
if (pflag & O_WRONLY ==O_WRONLY){
int err=mkfifo(filename,0666);//创建文件当管道用
if (err==-1){
printf("---- mkfifo err=%s\n",strerror(errno));
return -1;
}
}
//打开文件
pfd=open(filename,pflag); //打开管道 写入端用只写
if (pfd==-1){
printf("---- open err=%s\n",strerror(errno));
return -1;
}
//启动线程
if (postdata!=NULL){
state=1;
pthread_create(&pthid,NULL,prun,NULL);
}
return 0;
}
int pdestroy(){
state=0;
if (postdata!=NULL){
pthread_join(pthid,NULL);
}
close(pfd);
if (pflag & O_WRONLY ==O_WRONLY) unlink(filename); //删除临时文件
return 0;
}
int psend(char *buf,int size){
return write(pfd,buf,size);
}
//write.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include "pipe.h"
int main(int argc,char **argv){
int err=pinit(argv[1],O_WRONLY,NULL);
if (err==-1) return -1;
char buf[256];
while(1){
scanf("%s",buf);
psend(buf,strlen(buf));
if (strcmp(buf,"q")==0) break;
}
pdestroy();
}
//read.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include "pipe.h"
int recvdata(char *buf,int size){
printf("----size=%d buf=%s\n",size,buf);
if (strcmp(buf,"q")==0) exit(0);
}
void exitfun(void){
pdestroy();
}
int main(int argc,char **argv){
atexit(exitfun);
int err=pinit(argv[1],O_RDONLY,recvdata);
if (err==-1) return -1;
char buf[256];
while(1) {
scanf("%s",buf);
if (strcmp(buf,"q")==0) exit(0);
}
}