APUE:高级I/O

非阻塞I/O

调用 fcntl() 设置文件描述符 O_NONBLOCK 标志,调用 read() 和 write() 不再阻塞,有可能会返回 -1 并设置 errno 为 EAGAIN。

 

记录锁(字节锁)

用于锁住文件的某一部分,支持读锁和写锁。由于锁信息 lockf_entry 和 v-node 对应,系统并不关心也不知道锁和文件描述符的对应关系。如果同一个进程有多个文件描述符(包括 dup() 和 open())指向同一个文件,对任意一个 close() 都会导致全部解锁。如果在文件尾部加锁,文件向后增长时,新增内容也加了锁。fork() 子进程不继承父进程的锁。

建议性锁:由程序员主动检测锁,有锁时主动保证不进行I/O操作;

强制性锁:不管有没有锁,直接进行I/O,由内核保证锁起作用。

struct flock
  {
    short int l_type;	/* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK.	*/
    short int l_whence;	/* Where `l_start' is relative to (like `lseek').  */
    __off_t l_start;	/* Offset where the lock begins.  */
    __off_t l_len;	/* Size of the locked area; zero means until EOF.  */
    __pid_t l_pid;	/* Process holding the lock.  */
  };

fcntl(fd, F_SETLK or F_SETLKW or F_GETLK, & fl);

 

I/O多路转接(I/O多路复用)

主要是用于同时等待多个I/O。阻塞在等待函数 select()、poll() 上,而非特定文件描述符上。select() 和 poll() 不重启。

/* Check the first NFDS descriptors each in READFDS (if not NULL) for read
   readiness, in WRITEFDS (if not NULL) for write readiness, and in EXCEPTFDS
   (if not NULL) for exceptional conditions.  If TIMEOUT is not NULL, time out
   after waiting the interval specified therein.  Returns the number of ready
   descriptors, or -1 for errors.

   This function is a cancellation point and therefore not marked with
   __THROW.  */
// nfds 是 readfds、writefds、exceptfds 里最大的描述符序号 +1,可可以是 FD_SETSIZE
// timeout 用来设置超时,NULL 为永远阻塞
// 返回 -1 表示出错,如产生信号;其它表示准备好的描述符数量
// readfds、writefds、exceptfds 在返回后保存的是准备好的描述符
extern int select (int __nfds, fd_set *__restrict __readfds,
		   fd_set *__restrict __writefds,
		   fd_set *__restrict __exceptfds,
		   struct timeval *__restrict __timeout);

#define	FD_SET(fd, fdsetp)	__FD_SET (fd, fdsetp)
#define	FD_CLR(fd, fdsetp)	__FD_CLR (fd, fdsetp)
#define	FD_ISSET(fd, fdsetp)	__FD_ISSET (fd, fdsetp)
#define	FD_ZERO(fdsetp)		__FD_ZERO (fdsetp)


// 调用时屏蔽 sigmask 里的信号
extern int pselect (int __nfds, fd_set *__restrict __readfds,
		    fd_set *__restrict __writefds,
		    fd_set *__restrict __exceptfds,
		    const struct timespec *__restrict __timeout,
		    const __sigset_t *__restrict __sigmask);
#define POLLIN		0x001		/* There is data to read.  */
#define POLLPRI		0x002		/* There is urgent data to read.  */
#define POLLOUT		0x004		/* Writing now will not block.  */

/* Data structure describing a polling request.  */
struct pollfd
  {
    int fd;			/* File descriptor to poll.  */
    short int events;		/* Types of events poller cares about.  */
    short int revents;		/* Types of events that actually occurred.  */
  };

int poll (struct pollfd *__fds, nfds_t __nfds /* fds 的数量 */, int __timeout /* -1 为永远阻塞,其它为毫秒数 */);

  

异步I/O

  1. 创建 aiocb 结构体,填入描述符、偏移量、缓冲区大小、数据大小、通知方式(不通知?信号?新线程?)
  2. 如果需要立即写,调用 aio_fsync(),就像 fdatasync() 或 fsync() 一样
  3. 调用 aio_read() 或 aio_write() 进行异步 I/O
  4. 在 I/O 完成后(异步或调用 aio_suspend() 阻塞等待)调用 aio_error() 获取是否成功,如果成功,调用 aio_return() 获取相当于 read() 或者 write() 返回的结果
/* Enqueue read request for given number of bytes and the given priority.  */
extern int aio_read (struct aiocb *__aiocbp) __THROW __nonnull ((1));
/* Enqueue write request for given number of bytes and the given priority.  */
extern int aio_write (struct aiocb *__aiocbp) __THROW __nonnull ((1));

/* Retrieve error status associated with AIOCBP.  */
extern int aio_error (const struct aiocb *__aiocbp) __THROW __nonnull ((1));
/* Return status associated with AIOCBP.  */
extern __ssize_t aio_return (struct aiocb *__aiocbp) __THROW __nonnull ((1));

/* Try to cancel asynchronous I/O requests outstanding against file
   descriptor FILDES.  */
extern int aio_cancel (int __fildes, struct aiocb *__aiocbp) __THROW;

/* Suspend calling thread until at least one of the asynchronous I/O
   operations referenced by LIST has completed.

   This function is a cancellation point and therefore not marked with
   __THROW.  */
extern int aio_suspend (const struct aiocb *const __list[], int __nent,
			const struct timespec *__restrict __timeout)
  __nonnull ((1));

/* Force all operations associated with file desriptor described by
   `aio_fildes' member of AIOCBP.  */
extern int aio_fsync (int __operation, struct aiocb *__aiocbp)
  __THROW __nonnull ((2));

/* Initiate list of I/O requests.  */
extern int lio_listio (int __mode,
		       struct aiocb *const __list[__restrict_arr],
		       int __nent, struct sigevent *__restrict __sig)
  __THROW __nonnull ((2));

 

散布读和聚集写

将数据读入多个缓冲区,或从多个缓冲区写入数据

/* Structure for scatter/gather I/O.  */
struct iovec
  {
    void *iov_base;	/* Pointer to data.  */
    size_t iov_len;	/* Length of data.  */
  };

/* Read data from file descriptor FD, and put the result in the
   buffers described by IOVEC, which is a vector of COUNT 'struct iovec's.
   The buffers are filled in the order specified.
   Operates just like 'read' (see <unistd.h>) except that data are
   put in IOVEC instead of a contiguous buffer.

   This function is a cancellation point and therefore not marked with
   __THROW.  */
extern ssize_t readv (int __fd, const struct iovec *__iovec, int __count)
  __wur;

/* Write data pointed by the buffers described by IOVEC, which
   is a vector of COUNT 'struct iovec's, to file descriptor FD.
   The data is written in the order specified.
   Operates just like 'write' (see <unistd.h>) except that the data
   are taken from IOVEC instead of a contiguous buffer.

   This function is a cancellation point and therefore not marked with
   __THROW.  */
extern ssize_t writev (int __fd, const struct iovec *__iovec, int __count)
  __wur;

 

存储映射 I/O

将磁盘文件映射到内存中,像操作缓冲区一样操作文件。

#define PROT_READ	0x1		/* Page can be read.  */
#define PROT_WRITE	0x2		/* Page can be written.  */
#define PROT_EXEC	0x4		/* Page can be executed.  */

#define MAP_SHARED	0x01		/* 更新到文件  */
#define MAP_PRIVATE	0x02		/* 不更新到文件  */
#define MAP_FIXED	0x10		/* 要求地址必须是 addr  */


void *mmap (void *__addr, size_t __len, int __prot, int __flags, int __fd, __off_t __offset);
int munmap (void *__addr, size_t __len);

int mprotect (void *__addr, size_t __len, int __prot);


#define MS_ASYNC	1		/* Sync memory asynchronously.  */
#define MS_SYNC		4		/* Synchronous memory sync.  */

int msync (void *__addr, size_t __len, int __flags);

  

 

posted @ 2017-05-27 21:28  mfmans  阅读(180)  评论(0编辑  收藏  举报