首页 > 代码库 > APUE:文件I/O

APUE:文件I/O

标准流描述符:

/* Standard file descriptors.  */
#define	STDIN_FILENO	0	/* Standard input.  */
#define	STDOUT_FILENO	1	/* Standard output.  */
#define	STDERR_FILENO	2	/* Standard error output.  */

 

打开、创建、关闭文件:

#define O_ACCMODE	0003			/* O_ACCMODE = O_RDONLY | O_WRONLY | O_RDWR */
#define O_RDONLY	00
#define O_WRONLY	01
#define O_RDWR		02
#define O_CREAT		0100			/* open() 第 3 个参数指定权限位 */
#define O_EXCL		0200
#define O_NOCTTY	0400
#define O_TRUNC		01000
#define O_APPEND	02000
#define O_NONBLOCK	04000			/* 非阻塞 */
#define O_SYNC		04010000
#define O_FSYNC		O_SYNC
#define O_ASYNC		020000
#define O_DIRECTORY	__O_DIRECTORY		/* 打开非目录出错 */
#define O_NOFOLLOW	__O_NOFOLLOW		/* 打开符号链接出错 */
#define O_CLOEXEC	__O_CLOEXEC		/* exec() 时关闭 */

int open (const char *__file, int __oflag, ...);
int openat (int __fd, const char *__file, int __oflag, ...);
// open(__file, O_WRONLY | O_CREAT | O_TRUNC, __mode) int creat (const char *__file, mode_t __mode); int close (int __fd);

 

移动指针:

#define SEEK_SET	0	/* Seek from beginning of file.  */
#define SEEK_CUR	1	/* Seek from current position.  */
#define SEEK_END	2	/* Seek from end of file.  */

__off_t lseek (int __fd, __off_t __offset, int __whence);
__off64_t lseek64 (int __fd, __off64_t __offset, int __whence);

 

读写(注意原子操作):

ssize_t read (int __fd, void *__buf, size_t __nbytes);
ssize_t pread (int __fd, void *__buf, size_t __nbytes, __off_t __offset);
ssize_t write (int __fd, const void *__buf, size_t __n);
ssize_t pwrite (int __fd, const void *__buf, size_t __n, __off_t __offset);

 

文件共享:

int dup (int __fd);
int dup2 (int __fd, int __fd2);    // 先关闭 fd2, 再复制 fd -> fd2

 

刷新内部缓冲:

void sync (void);          // 只写入队列,不等待磁盘 I/O
int fsync (int __fd);        // 等待磁盘 I/O,更新数据和属性
int fdatasync (int __fildes);    // 等待磁盘 I/O,只更新数据

 

fcntl()和ioctl():

#define F_DUPFD				0		/* Duplicate file descriptor.  */
#define F_DUPFD_CLOEXEC		1030	/* Duplicate file descriptor with close-on-exit set.  */
#define F_GETFD				1		/* Get file descriptor flags.  */
#define F_SETFD				2		/* Set file descriptor flags.  */
#define F_GETFL				3		/* Get file status flags.  */
#define F_SETFL				4		/* Set file status flags.  */
#define F_SETOWN	__F_SETOWN 		/* Get owner (process receiving SIGIO).  */
#define F_GETOWN	__F_GETOWN 		/* Set owner (process receiving SIGIO).  */

int fcntl (int __fd, int __cmd, ...);

int ioctl (int __fd, unsigned long int __request, ...);

 

/dev/fd:

每个进程看到的都不一样,例如:

# ls -l /dev/fd/ > a.txt
# cat a.txt 
total 0
lrwx------. 1 root root 64 May 20 16:34 0 -> /dev/pts/0
l-wx------. 1 root root 64 May 20 16:34 1 -> /root/a.txt
lrwx------. 1 root root 64 May 20 16:34 2 -> /dev/pts/0
lr-x------. 1 root root 64 May 20 16:34 3 -> /proc/6259/fd

 

习题3.2  自己实现一个dup2():

int mydup2 (int fd, int fd2) {
	int fd_close[20] = { 0 };
	int fd_temp;

	if(fd == fd2) {
		return fd2;
	}

	close(fd2);

	while((fd_temp = dup(fd)) != fd2) {
		fd_close[fd_temp] = 1;
	}

	for(int i = 0; i < (sizeof fd_close / sizeof fd_close[0]); i ++) {
		if(fd_close[i]) {
			close(i);
		}
	}

	return fd2;
}

 

习题3.3  考虑下边代码,显然 fd1 和 fd2 指向同一个 vnode:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>


int main(void)
{
	int fd11 = open("a.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);
	int fd12 = dup(fd11);

	int fd21 = open("a.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);

	// abcdefg
	write(fd11, "abcdefg", 7);
	lseek(fd11, 0, SEEK_SET);

	// xxxxxxx
	write(fd12, "xxxxxxx", 7);

	// xxxxxxxyyyyyyy
	lseek(fd21, 0, SEEK_END);
	write(fd21, "yyyyyyy", 7);

	// xxxxxxxaaaaaaa
	write(fd11, "aaaaaaa", 7);

	return 0;
}

 

习题3.6  以下代码说明可以任意位置读,写入总在尾部追加:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>


int main(void)
{
	char buffer[4] = { 0 };

	int fd = open("a.txt", O_RDWR | O_CREAT | O_TRUNC | O_APPEND, 0644);

	write(fd, "abcdefg", 7);
	lseek(fd, 2, SEEK_SET);

	printf("%d\n", read(fd, buffer, 3));
	printf("%s\n", buffer);

	printf("%d\n", write(fd, "xxx", 3));

	return 0;
}

  

APUE:文件I/O