APUE-第十四章 高级I/O

1、非阻塞I/O

不会永远阻塞的I/O操作。

对于一个给定的文件描述符,有两种方法指定非阻塞I/O

①调用open指定O_NONBLOCK标志。

②对已经打开的描述符,调用fcntl,修改一打开文件描述符的O_NONBLOCK标志。

 

2、记录锁。

record locking

当第一个进程正在读或修改文件的某个部分时,使用记录锁可以阻止其他进程修改同一文件区。(字节范围锁)

apue.h

请求和释放一把锁

int               lock_reg(int,int, int, off_t, int, off_t);

 

#define       read_lock(fd,offset, whence, len) \

                            lock_reg((fd),F_SETLK, F_RDLCK, (offset), (whence), (len))

#define       readw_lock(fd,offset, whence, len) \

                            lock_reg((fd),F_SETLKW, F_RDLCK, (offset), (whence), (len))

#define       write_lock(fd,offset, whence, len) \

                            lock_reg((fd),F_SETLK, F_WRLCK, (offset), (whence), (len))

#define       writew_lock(fd,offset, whence, len) \

                            lock_reg((fd),F_SETLKW, F_WRLCK, (offset), (whence), (len))

#define       un_lock(fd,offset, whence, len) \

                            lock_reg((fd),F_SETLK, F_UNLCK, (offset), (whence), (len))

测试一把锁

pid_t lock_test(int,int, off_t, int,off_t);            

 

#define       is_read_lockable(fd,offset, whence, len) \

                            (lock_test((fd),F_RDLCK, (offset), (whence), (len)) == 0)

#define       is_write_lockable(fd,offset, whence, len) \

                            (lock_test((fd),F_WRLCK, (offset), (whence), (len)) == 0)

记录锁的自动继承和释放3条规则:

²  锁与进程和文件两者相关联

²  fork产生的子进程不继承父进程所设置的锁

²  在执行exec后,新程序可以继承原执行程序的锁

在文件尾端加锁

Writew_lock(fd,o,SEEK_END,O)

Write(fd,buf,1);

Unclock(fd,o,SEEK_END);

Write(fd,buf,1);

 

建议性锁:

强制性锁:让内核检查每一个openreadwrite,验证调用进程是否违背了正在访问的文件上的某一把锁。

 

一般的Unix系统文本编辑器并不使用记录锁。(该文件的最后结果取决于写该文件的最后一个进程)

 

3、死锁

1)条件:要有一个或多个线程、一个或多个资源,每个线程都在等待其中的一个资源,但所有的资源都已经被占用。所有线程都在互相等待,但他们永远不会释放已经占有的资源。

2)避免死锁的规则:

  • 按顺序加锁。
  • 防止发生饥饿
  • 不重复请求同一个锁
  • 设计应力求简单

 

4I/O多路转接

先构造一个我们所关心的描述符列表,然后调用函数(selectpselectpoll)直到这些描述符中的一个已经准备好进行I/O时,该函数才返回。

#include

Int select(int maxfdl,

fd_set *restrict readfds,

fd_set *restrict writefds,

fd_set *restrict exceptfds,

struct timeval *restricttvptr);

 

 

5、异步I/O

POSIX异步I/O接口使用AIO控制块来描述I/O操作。

Struct aiocb

{

}

 

6、函数readv  writev

用于在一次函数调用中读、写多个非连续缓冲区。---散布读、聚集写

#include

Ssize_t readv(int fd, const struct iovec*iov, int iovcnt);

Ssize_t writev(int fd, const struct iovec*iov, int iovcnt);

 

Struct iovec{

                   Void*iov_base;   //starting addressof buffer

                   Size_tiov_len;    //sizeof buffer

}

 

7、函数readn  written

读写指定的N字节数据,并处理返回值可能小于要求值的情况。

#include “apue.h”

Ssize_t readn(int fd, void *buf, size_tnbytes);

Ssize_t writen(int fd, void *buf,size_tnbytes);

 

8、存储映射I/O

Memory-mapped I/O

将一个磁盘文件映射到存储空间中的一个缓冲区上,当从缓冲区中取数据时,就相当于读文件中的相应字节。与此类似,将数据存入缓冲区时,相应字节就自动写入文件。

#include

告诉内核将一个给定文件映射到一个存储区域中,返回映射区的起始地址。

Void *mmap(void *addr, size_t len, intprot, int flag, int fd, off_t off);

更改现有映射的权限

Int mprotect(void *addr, size_t len, intprot);

将已经修改的页“冲洗”到被影射的文件中。

Int msync(void *addr, size_t len, intflags);

解除存储映射区的映射

Int munmap(void *addr, size_tlen);


你可能感兴趣的:(apue)