linux下的select函数

来源:互联网 发布:敏捷软件开发宣言 编辑:程序博客网 时间:2024/05/17 01:47

该函数允许进程指示内核等待多个事件的任何一个发生,并且只在有一个或多个事件发生或经历一段指定的时间后才能唤醒。


需要的库

#include <sys/select.h>

#include <sys/time.h>


int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptest, const, struct timeval *timeout);


fd_set是一组文件描述符的集合。

FD_CLR(inr fd,fd_set* set);用来清除描述词组set中相关fd 的位
FD_ISSET(int fd,fd_set *set);用来测试描述词组set中相关fd 的位是否为真
FD_SET(int fd,fd_set*set);用来设置描述词组set中相关fd的位
FD_ZERO(fd_set *set);用来清除描述词组set的全部位

举例:打开描述符1

fd_set rset;

FD_ZERO(&rset);

FD_SET(1,&rset);


中间的三个参数readset,writeset,exceptset指定我们要让内核测试试着读,写和异常条件的描述符。


如果这三个参数都为空,将获取一个更为精确的定时器。


timval结构

struct timeval{

long tv_sec;

long tv_usec;

}

参数可能

(1)永远等待下去:仅有一个描述符准备好I/O时返回。

(2)等待固定时间:在不超过参数指向的timeval结构内的秒数和微妙数时,在有一个描述符准备好I/O是返回。

(3)根本不等待:检查描述符后立即返回。

前两种会被进程在等待期间捕获的信号中断,并从信号处理返回。


#include <stdio.h>#include <stdlib.h>#include <sys/wait.h>#include <sys/types.h>#include <string.h>int main(){    int pipefd[2];    int i;    if (pipe(pipefd) < 0)//创建管道    {        printf("create pipe failed\n");        return -1;    }    pid_t pid = fork();//创建进程    if (pid == 0)//进入子进程    {        printf("child fork is running\n");        close(pipefd[0]);//关闭管道读取        char str[50];        for (i =0; i < 5; i++)        {            sprintf(str, "child fork msg %d ", i);             write (pipefd[1], str, strlen(str));//循环5次向管道输入数据            sleep(3);        }    }else    {//父进程        printf("parent fork is running\n");        char str[50];        close(pipefd[1]);//关闭管道输入        fd_set readset;        for (i = 0; i < 5; i++ )        {            FD_ZERO(&readset);//因为每次调用下面select语句后readset的值都会该改变,所以每次都要清空为0.            FD_SET(pipefd[0], &readset);//将pipefd[0]描述符添加到readset中            FD_SET(0, &readset);//将(0)也就是标准输入流的描述添加到readset中                        select(pipefd[0]+1, &readset, NULL, NULL, NULL);//对于第一个参数取readset中的最大描述符+1,此时堵塞等待标准输入流,管道输入流有数据输入,其中一个有。立即返回            if (FD_ISSET(pipefd[0], &readset))//判断readset是否管道输入            {                str[read(pipefd[0], str, 50)] = '\0';                printf("parent recv is %s\n", str);            }            if (FD_ISSET(0, &readset))//判断readset是否标准输入流            {                str[read(0, str, 256)] = '\0';                printf("stdout is %s\n", str);            }        }        int status;        wait(&status);    }    return 0;}

结果,主要分为两种情况

情况一:不在终端输入

parent recv is child fork msg 0 

parent recv is child fork msg 1 

parent recv is child fork msg 2

parent recv is child fork msg 3

parent recv is child fork msg 4 

情况一:在有终端输入

parent recv is child fork msg 0 

输入le

stdout is le 

parent recv is child fork msg 1 

输入wang

stdout is lwang

parent recv is child fork msg 2

只出现3次管道输出,原因是for循环5次,但在过程中有标准输入流,每次有标准输入流select马上从堵塞中解除,消耗一次for循环。


0 0
原创粉丝点击