linux c语言高级编程-描述符监听select

本篇主要讲解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);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

行走在软件开发路上的人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值