4.
名称:: |
pselect |
功能: |
指行I/O多路转接 |
头文件: |
#include <sys/select.h> |
函数原形: |
int pselect(int masfdp1,fd_set *restrict readfds,fd_set *restrict writefds,fd_set excepfds,const struct timespec *restrict tsptr,const sigset_t *restrict sigmask); |
参数: |
maxfdpl 最大描述符加1 readfds 读描述符集 writefds 写描述符集 excepfds 异常描述符集 tsptr 愿意等待时间 sigmask 信号屏蔽集 |
返回值: |
若fd在描述符集中则返回非0值,否则返回0(FD_ISSET) |
pselect是select的一个变体,除以下几点外,pselect与select相同:
(1) select的超时值用timeval结构指定,但pselect使用timespec结构指定。timespec以秒和纳秒表示超时值。
(2) pselect的超时值被定义为const,这保证了调用pselect不会改变此值,。
(3) 对于paselect可以使用一可选的信号屏蔽字。若sigmask为空,那么在于信号有关的方面,pselect和select相同。否则,sigmask指向一信号屏蔽字,在调用pselect时,以原子操作的方式安装该信号屏蔽字。在返回时恢复以前的信号屏蔽字。
5.
名称:: |
poll |
功能: |
指行I/O多路转接 |
头文件: |
#include <sys/select.h> |
函数原形: |
int poll(struct pollfd fdarray[],nfds_t nfds,int timeout); |
参数: |
fdarray 存放描述符集的数组 nfds fdarray数组元素个数 timeout 超时等待时间 |
返回值: |
准备就绪的描述符数,若超时则返回0,若出错则返回-1 |
poll类似于select,但是其接口则有所不同。poll不时为每个状态(可读性,可写性和异常状态)构造一个描述符集,而是构造一个pollfd结构的数组,每个数组元素指定一个描述符编号以及其所关心的状态。
struct pollfd{
int fd; 文件描述符
shout events;
shout revents;
};
fdarray数组中的元素由nfds说明。
应将每个数组元素的events成员设置为下表的值。通过这些告诉内核我们对该描述符关系的时什么。返回时,内核设置revents成员,以说明对于该描述符已经发生了什么事件。
标志名 |
说明 |
POLLIN POLLRDNORM POLLRDBAND POLLPRI |
不阻塞地可读除高优先级外的数据(等效于POLLRDNORM|POLLRDBAD) 不阻塞地可读普通数据(优先级波段为0) 不阻塞地可读非0优先级波段数据 不阻塞地可读高优先级数据 |
POLLOUT POLLWRNORM POLLWRBAND |
不阻塞地可写普通数据 与POLLOUT相同 不阻塞地可写非0优先级波段数据 |
POLLERR POLLHUP POLLNVAL |
已出错 已挂断 描述符不引用一打开文件 |
表头四行测试可读性,接着三行测试可写性,最后三行则是测试异常状态。最后三行是由内核在返回时设置的。即使在events字段中没有指定这三个值,如果相应条件发生,则在revents中也它们。
当一个描述符被挂断后,就不能再写向该描述符。但是仍可能从该描述符读取数据。
poll的最后一个参数说明我们愿意等待多少时间。如同sellect一样,有三种不同情形:
(1) timeout==-1永远等待,当所指定的描述符中的一个已准备好,或捕捉到一个信号时则返回。如果捕捉到一个信号,则poll返回-1,error设置为EINTR.
(2)timeout==0 不等待。测试所有的描述符并立即返回。这是得到多个描述符的状态而不阻塞select函数的轮询方法。
(3)timeout>0 等待timeout毫秒。当指定的描述符之一已准备好,或当指定的时间值已超过时立即返回。如果在超时还没有一个描述符准备好,则返回值是0。
三、读写多个缓冲区
6.
名称:: |
readv/writev |
功能: |
散布读/聚集写 |
头文件: |
#include <sys/uio.h> |
函数原形: |
ssize_t readv(int filedes,const struct iovec *iov,int iovcnt); ssize_t writev(int filedes,const struct iovec *iov,int iovcnt); |
参数: |
filedes 文件描述符 iov 指向iovec结构数组的一个指针。 iovcnt 数组元素的个数 |
返回值: |
若成功则返回已读、写的字节数,若出错则返回-1 |
readv和writev函数用于在一次函数调用中读、写多个非连续缓冲区。有时也将这两个函数成为散布读和聚集写。
这两个函数的第二个参数是指向iovec结构数组的一个指针:
struct iovec{
void *iov_base;
size_t iov_len;
};
writev以顺序iov[0]至iov[iovcnt-1]从缓冲区中聚集输出数据。writev返回输出的字节总数,通常,它应等于所有缓冲区长度之和。
readv则将读入的数据按上述同样顺序散布读到缓冲区中。readv总是先填满一个缓冲区,然后再填写下一个。readv返回读到的总字节数。如果遇到文件结尾,已无数据可读,则返回0。
下面就是读多个缓冲区的例子:
/*12_4.c*/ #include <sys/uio.h> #include <stdio.h> #include <fcntl.h>
int main(int argc,char *argv[]) { ssize_t size; char buf1[9]; char buf2[9]; struct iovec iov[2];
fd1=open(argv[1],O_RDONLY); fd2=open(argv[2],O_RDONLY); fd3=open(argv[3],O_WRONLY);
size=read(fd1,buf1,sizeof(buf1)); printf(“%s size is:%d\n”,argv[1],size); size=read(fd2,buf2,sizeof(buf2)); printf(“%s size is:%d\n”,argv[2],size);
iov[0].iov_base=buf1; iov[0].iov_len=sizeof(buf1); iov[1].iov_base=buf2; iov[1].iov_len=sizeof(buf2);
size=writev(fd3,iov,2)); printf(“%s size is:%d\n”,argv[3],size);
close(fd1); close(fd2); close(fd3); } |
先用vi或cat建立三个文件(test1,test2,test3),test写入123456789,test写入abcdefghi. test3为空。
然后运行命令:
#./12_4 test1 test2 test3
在屏幕上会输出:
test1 size is:9
test2 size is:9
test3 size is:18
打开test3,文件内容为123456789abcdefghi.
程序先把test1和test2的内容分别读到缓冲区buf1和buf2中。然后用write把buf1