該函數允許進程指示內核等待多個事件的任何一個發生,並且只在有一個或多個事件發生或經歷一段指定的時間後才能喚醒。
需要的庫
#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循環。