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;
}

  

时间: 2024-10-16 06:30:30

APUE:文件I/O的相关文章

[APUE]文件和目录

一.APUE这一章中的各种晦涩名词 我在读这一章时遇到了各种ID,根据名字完全不清楚什么意思,幸好看到了这篇文章,http://blog.csdn.net/ccjjnn19890720/article/details/6990656,总结一下 每一个进程其实对应了6个以上的ID,它们分别是:实际用户ID.实际组ID(我们实际上是谁,执行这个程序的用户和组),有效用户ID.有效组ID.附加组ID(用于文件访问权限检查),保存设置用户ID,保存设置组ID(由exec函数保存) 实际用户ID/实际组I

APUE: 文件和目录相关的系统调用

Tips:下面的总结是参考APUE(unix环境高级编程)这本书,在linux(ubuntu)上的实现. Linux系统的调用结构: 最上层:应用程序+shell命令(外部命令在coreutils中实现,内部命令在bash中实现) 中间层:linux下的库函数(gnu的c标准库在glibc中实现) 最底层:linux内核(163个linux系统调用接口+内核子系统(驱动)) 系统调用是linux内核和外部的唯一接口. unix的标准主要有两个: posix标准:可移植操作系统接口,IEEE.IS

[APUE]文件和目录(中)

一.link.unlink.remove和rename 一个文件可以有多个目录项指向其i节点.使用link函数可以创建一个指向现存文件连接 #include <unistd.h> int link(const char *existingpath, const char *newpath); 返回值:成功为0,出错为-1 该函数创建一个新目录项newpath,指向现存文件existingpath,如果newpath已存在则返回出错. 为了删除一个现存的目录项,可以调用unlnk函数. #inc

APUE学习-记录一

从开始看APUE已经有快一个星期了,由于正好赶上这几天清明节放假,难得有了三天空闲假期可以不受打扰的学习APUE,现在已经看完前六章了,里面的大部分例程也都亲自编写,调试过了.但总觉得这样学过就忘,因此决定把这个学习过程记录下来,学到后面章节的时候回顾前面的章节,做到温故知新.也可以将自己在学习过程中遇到的问题记录下来. 本书对UNIX系统的提供的接口的方方面面进行了讲解,中间还穿插介绍了很多UNIX或类UNIX系统的相关知识,即使现在我只是看过了前六章,也感觉学到了不少知识,解决了我以前对LI

最佳vim技巧

最佳vim技巧----------------------------------------# 信息来源----------------------------------------www.vim.org         : 官方站点comp.editors        : 新闻组http://www.newriders.com/books/opl/ebooks/0735710015.html : Vim书籍http://vimdoc.sourceforge.net/cgi-bin/vim

apue第四章 文件和目录

函数stat,fstat,fstatat, lstat #include <sys/stat.h> int stat(const char *restrict pathname, struct stat *restrict buf); int fstat(int fd, struct stat *buf); int lstat(const char *restrict pathname, struct stat *restrict buf); int lstat(int fd, const c

APUE(4)---文件和目录 (2)

umask函数为进程设置文件模式创建屏蔽字,并返回之前的值,这是少数几个没有出错返回函数中的一个.其中cmask是9个常量(S_IR/W/XUSR.S_IR/W/XGRP.S_IR/W/XOTH)中的若干个按位“或”构成的. #include<sys/stat.h> mode_t umask(mode_t cmask); //返回值:之前的文件模式创建屏蔽字 #include<apue.h> #include<fcntl.h> #define RWRWRW (S_IRU

APUE(4)---文件和目录 (1)

一.引言 上一章执行I/O的基本函数(打开文件.读文件和写文件),本章将描述文件系统的其他特征和文件的性质,我们将从stat函数开始,并逐个说明stat结构的每一个成员以了解文件的所有属性.在此过程中,我们将说明修改这些属性的各个函数. 二.函数stat.fstat.fstatat和lstat #include <sys/stat.h> int stat(const char *restrict pathname, struct stat *restrict buf); int fstat(i

APUE读书笔记: 文件和目录

stat, fstat, fstatat 和 lstat函数: stat函数返回与pathname命名文件相关的信息结构: fstat函数返回已在文件描述符fd打开文件的相关信息: lstat函数与stat函数类似,但当命名文件是一个符号链接时,返回该符号链接的相关信息: fstatat函数为相对于当前打开目录(有fd参数指向)的路径名返回文件统计信息. struct stat 的具体定义如下图: 文件类型: 文件类型包括:普通文件,目录文件,块特殊文件,字符特殊文件,FIFO,套接字和符号链接

APUE(4)---文件和目录 (3)

十三.函数rename和renameat #include <stdio.h> int rename(const char *oldname, const char *newname); int renameat(int oldfd, const char *oldname, int newfd, const char *newname); 文件或目录可以用rename函数或者renameat函数进行重命名.有几种情况需要说明: 1.如果oldname指的是一个文件而不是目录,那么为该文件或符