程序期待着来自两个源端的输入,但不知道哪个源端的输入先到。如果程序试图从源端A读入,而实际上只有来自源端B的输入可用,那么程序就会发生阻塞,怎么办?

保持阻塞状态,直到一组条件中至少有一个条件为真为止,这种方法称为  或同步(OR synchronization)。

1.监视多个文件描述符的一种方法是为每个描述符分别使用一个独立的进程

下面程序有两个命令行参数,即两个要监视的文件的名字,父进程在创建子进程之前将两个文件都打开,父进程监视第一个文件描述符,子进程监视第二个文件描述符。每个进程都将它对应的文件内容送到标准输出中去,如果监视两个命名管道,输入可用时则会出现输出。



[cpp] view plain copy

1. #include <errno.h>
2. #include <fcntl.h>
3. #include <stdio.h>
4. #include <string.h>
5. #include <unistd.h>
6.   
7. int main(int argc,char
8. int
9. int
10. int
11.       
12. if(argc!=3){  
13. "Usage : %s filel file2 .\n",argv[0]);  
14. return
15.     }  
16. if( (fd1=open(argv[1],O_RDONLY)) == -1){  
17. "Failed open file %s .\n",argv[1]);  
18. return
19.     }  
20. if( (fd2=open(argv[2],O_RDONLY)) == -1){  
21. "Failed open file %s .\n",argv[2]);  
22. return
23.     }  
24. if( (childpid=fork()) == -1){  
25. "Faile to create child process.");  
26. return
27.     }  
28. if(childpid>0){//parent code
29.         fd=fd1;  
30.     }  
31. else{  
32.         fd=fd2;  
33.     }  
34.     bytesread=copyfile(STDOUT_FILENO,fd);  
35. return
36. }



2.select在单进程中监视两个文件描述符

         用独立的进程来监视两个文件描述符可能很有用,但是这两个进程都有独立的地址空间,因此他们的交互变得非常困难。

select函数提供了一种在单个进程中监视多个文件描述符的方法。它可以对三种可能的情况进行监视——可以无阻塞地进行读操作,可以无阻塞地进行写操作,或者有挂起的错误情况的文件描述符。老版本的UNIX在sys/time.h中定义了select方法,但在POSIX是在sys/select.h

        



[cpp] view plain copy


1. #include <sys/select.h>
2.   
3. int select(int
4.     fd_set *restrict readfds,  
5.     fd_set *restrict writefds,  
6.     fd_set *restrict errorfds,  
7. struct


select参数:

nfds 给出了要监视文件描述符的范围,nfds的值必须至少要比要监视的文件描述符的最大值大1。

readfds 指定了为读操作监视的文件描述符集。

writefds 指定了为写操作监视的文件描述符集。

errorfds 指定了为错误情况监视的文件描述符集。

readfds,writefds,errorfds中任何一个都可能为NULL,在这种情况下select不为相应的事件监视描述符

timeout是一个超时值,经过一段特定的时间后,即使没有准备就绪的描述符,它也会迫使select返回,当timeout为NULL时,select可能会无限期地阻塞。

成功返回时,除了那些已经准备就绪的描述符之外,select清空readfds,writefds,errorfds中所有描述符,并返回已准备就绪的文件描述符的数目。

如果不成功,返回-1并设置errno。

历史上,系统将描述符集作为整数比特掩码来实现,但在大多数的系统中,当文件描述符多于32个时,这中实现将不能正常工作。现在通常用整数数组中的比特域来表示描述符集,用宏FD_SET,FD_CLR,FD_ISSET,FD_ZERO以一种独立于实现的方式来操作描述符集。



[cpp] view plain copy

1. void FD_CLR(int
2. int FD_ISSET(int
3. void FD_SET(int
4. void


FD_SET设置了×fdset中对应于文件描述符fd的那个比特位

FD_CLR清除了相应的比特位

FD_ZERO清除了×fdset中的所有比特位

调用select之前,先用这三个宏来设置描述符掩码,在select返回之后用FD_ISSET来测试掩码中对应于文件描述符fd的那个比特位是否被设置

[cpp] view plain copy

1. #include <sys/select.h>
2. #include <fcntl.h>
3. #include <errno.h>
4. #include <string.h>
5. #include <stdio.h>
6.   
7. int main(int argc,char
8. int
9.       
10. if(argc!=3){  
11. "Usage : %s filel file2 .\n",argv[0]);  
12. return
13.     }  
14. if( (fd1=open(argv[1],O_RDONLY)) == -1){  
15. "Failed open file %s .\n",argv[1]);  
16. return
17.     }  
18. if( (fd2=open(argv[2],O_RDONLY)) == -1){  
19. "Failed open file %s .\n",argv[2]);  
20. return
21.     }  
22.     fd=whichisready(fd1,fd2);  
23. if(fd==fd1){  
24. "The %s is ready.\n",argv[1]);  
25.     }  
26. else if(fd==fd2){  
27. "The %s is ready.\n",argv[2]);  
28.     }  
29. return
30. }  
31. int whichisready(int fd1,int
32. int
33. int
34.     fd_set readset;  
35.       
36. if( (fd1<0)||(fd1>=FD_SETSIZE)||(fd2<0)||(fd2>FD_SETSIZE) ){  
37.         errno=EINVAL;  
38. return
39.     }  
40.       
41.     maxfd=(fd1>fd2)?fd2:fd2;  
42.     FD_ZERO(&readset);  
43.     FD_SET(fd1,&readset);  
44.     FD_SET(fd2,&readset);  
45.       
46.     nfds=select(maxfd+1,&readset,NULL,NULL,NULL);  
47.       
48. if(nfds==-1){  
49. return
50.     }  
51. if( FD_ISSET(fd1,&readset) ){  
52. return
53.     }  
54. if( FD_ISSET(fd2,&readset) ){  
55. return
56.     }  
57.     errno=EINVAL;  
58. return
59. }

whichisready存在问题:

1.只能返回一个值

2.当两个文件描述符都准备好时优先返回第一个文件描述符


程序期待着来自两个源端的输入,但不知道哪个源端的输入先到。如果程序试图从源端A读入,而实际上只有来自源端B的输入可用,那么程序就会发生阻塞,怎么办?

保持阻塞状态,直到一组条件中至少有一个条件为真为止,这种方法称为  或同步(OR synchronization)。

1.监视多个文件描述符的一种方法是为每个描述符分别使用一个独立的进程

下面程序有两个命令行参数,即两个要监视的文件的名字,父进程在创建子进程之前将两个文件都打开,父进程监视第一个文件描述符,子进程监视第二个文件描述符。每个进程都将它对应的文件内容送到标准输出中去,如果监视两个命名管道,输入可用时则会出现输出。

[cpp] view plain copy

1. #include <errno.h>
2. #include <fcntl.h>
3. #include <stdio.h>
4. #include <string.h>
5. #include <unistd.h>
6.   
7. int main(int argc,char
8. int
9. int
10. int
11.       
12. if(argc!=3){  
13. "Usage : %s filel file2 .\n",argv[0]);  
14. return
15.     }  
16. if( (fd1=open(argv[1],O_RDONLY)) == -1){  
17. "Failed open file %s .\n",argv[1]);  
18. return
19.     }  
20. if( (fd2=open(argv[2],O_RDONLY)) == -1){  
21. "Failed open file %s .\n",argv[2]);  
22. return
23.     }  
24. if( (childpid=fork()) == -1){  
25. "Faile to create child process.");  
26. return
27.     }  
28. if(childpid>0){//parent code
29.         fd=fd1;  
30.     }  
31. else{  
32.         fd=fd2;  
33.     }  
34.     bytesread=copyfile(STDOUT_FILENO,fd);  
35. return
36. }


2.select在单进程中监视两个文件描述符

         用独立的进程来监视两个文件描述符可能很有用,但是这两个进程都有独立的地址空间,因此他们的交互变得非常困难。

select函数提供了一种在单个进程中监视多个文件描述符的方法。它可以对三种可能的情况进行监视——可以无阻塞地进行读操作,可以无阻塞地进行写操作,或者有挂起的错误情况的文件描述符。老版本的UNIX在sys/time.h中定义了select方法,但在POSIX是在sys/select.h

        



[cpp] view plain copy

1. #include <sys/select.h>
2.   
3. int select(int
4.     fd_set *restrict readfds,  
5.     fd_set *restrict writefds,  
6.     fd_set *restrict errorfds,  
7. struct

select参数:

nfds 给出了要监视文件描述符的范围,nfds的值必须至少要比要监视的文件描述符的最大值大1。

readfds 指定了为读操作监视的文件描述符集。

writefds 指定了为写操作监视的文件描述符集。

errorfds 指定了为错误情况监视的文件描述符集。

readfds,writefds,errorfds中任何一个都可能为NULL,在这种情况下select不为相应的事件监视描述符

timeout是一个超时值,经过一段特定的时间后,即使没有准备就绪的描述符,它也会迫使select返回,当timeout为NULL时,select可能会无限期地阻塞。

成功返回时,除了那些已经准备就绪的描述符之外,select清空readfds,writefds,errorfds中所有描述符,并返回已准备就绪的文件描述符的数目。

如果不成功,返回-1并设置errno。

历史上,系统将描述符集作为整数比特掩码来实现,但在大多数的系统中,当文件描述符多于32个时,这中实现将不能正常工作。现在通常用整数数组中的比特域来表示描述符集,用宏FD_SET,FD_CLR,FD_ISSET,FD_ZERO以一种独立于实现的方式来操作描述符集。

[cpp] view plain copy

1. void FD_CLR(int
2. int FD_ISSET(int
3. void FD_SET(int
4. void


FD_SET设置了×fdset中对应于文件描述符fd的那个比特位

FD_CLR清除了相应的比特位

FD_ZERO清除了×fdset中的所有比特位

调用select之前,先用这三个宏来设置描述符掩码,在select返回之后用FD_ISSET来测试掩码中对应于文件描述符fd的那个比特位是否被设置



[cpp] view plain copy

1. #include <sys/select.h>
2. #include <fcntl.h>
3. #include <errno.h>
4. #include <string.h>
5. #include <stdio.h>
6.   
7. int main(int argc,char
8. int
9.       
10. if(argc!=3){  
11. "Usage : %s filel file2 .\n",argv[0]);  
12. return
13.     }  
14. if( (fd1=open(argv[1],O_RDONLY)) == -1){  
15. "Failed open file %s .\n",argv[1]);  
16. return
17.     }  
18. if( (fd2=open(argv[2],O_RDONLY)) == -1){  
19. "Failed open file %s .\n",argv[2]);  
20. return
21.     }  
22.     fd=whichisready(fd1,fd2);  
23. if(fd==fd1){  
24. "The %s is ready.\n",argv[1]);  
25.     }  
26. else if(fd==fd2){  
27. "The %s is ready.\n",argv[2]);  
28.     }  
29. return
30. }  
31. int whichisready(int fd1,int
32. int
33. int
34.     fd_set readset;  
35.       
36. if( (fd1<0)||(fd1>=FD_SETSIZE)||(fd2<0)||(fd2>FD_SETSIZE) ){  
37.         errno=EINVAL;  
38. return
39.     }  
40.       
41.     maxfd=(fd1>fd2)?fd2:fd2;  
42.     FD_ZERO(&readset);  
43.     FD_SET(fd1,&readset);  
44.     FD_SET(fd2,&readset);  
45.       
46.     nfds=select(maxfd+1,&readset,NULL,NULL,NULL);  
47.       
48. if(nfds==-1){  
49. return
50.     }  
51. if( FD_ISSET(fd1,&readset) ){  
52. return
53.     }  
54. if( FD_ISSET(fd2,&readset) ){  
55. return
56.     }  
57.     errno=EINVAL;  
58. return
59. }


whichisready存在问题:

1.只能返回一个值

2.当两个文件描述符都准备好时优先返回第一个文件描述符