1. 程式人生 > >APUE:文件I/O

APUE:文件I/O

size nis position close ioctl ++ 標準 rect 追加

標準流描述符:

/* 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