UNIX环境高级编程读书笔记(十二)—高级IO (3)

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

你可能感兴趣的:(linux,读书笔记,apue)