1. lseek()
显示修改已打开文件的文件偏移量
#include <unistd.h>
off_t lseek(int fildes, off_t offset, int whence);
1.1 return: 修改成功返回新的文件偏移量,否则返回-1.
1.2 offset: 指定了一个以字节为单位的数值。
1.3 whence: 表明应该参照那个基点来解释offset参数。whence应为下列其中之一。
1.3.1 SEEK_SET: 将文件偏移量设置为从文件头部起始点开始的offset个字节。
1.3.2 SEEK_CUR: 相对于当前文件偏移量,将文件偏移量调整offset个字节。
1.3.3 SEEK_END: 将文件偏移量设置为起始于文件尾部的offset个字节。
2 fcntl()
fcntl()用来操作已打开文件的文件描述符。例如:获取或修改其访问模式或状态标志。
#include <fcntl.h>
int fcntl(int fildes, int cmd, ...);
2.1 return : 成功返回 cmd的依赖,否则返回-1。
2.2 fildes: 要操作文件的文件描述符。
2.3 cmd: fcntl() 执行的命令常数。
3. 文件描述符、打开的文件句柄和i-node之间的关系
4. dup()和dup2()
dup()系统调用复制一个打开的文件描述符oldfd,并返回一个新描述符。
dup2()系统调用会为oldfd参数指定的文件描述符创建副本,编号由newfd指定。若newf所指定编号的文件描述符之前已经打开,那么dup2()会先将其关闭。
#include <unistd.h>
int dup(int fildes);
int dup2(int fildes, int fildes2);
5. pread()和pwrite()
与read()和write()的作用类似,但是pread()和pwrite()会在offset所指定的位置进行I/O操作,而且不会改变文件的当前偏移量。
#include <unistd.h>
ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset);
ssize_t pwrite(int fildes, const void *buf, size_t nbyte, off_t offset);
由于每个已打开文件的文件偏移量会被该进程下的所有线程所共享,所以一个线程进行IO操作可能会影响其他线程。
但是当调用pread()或pwrite()进行IO操作时,不会因为其他线程修改文件偏移量而受到影响。而且pread()和pwrite()系统调用的成本低于lseek()和read()、write()系统调用。
6. readv()和writev()
readv()和writev()系统调用分别实现了分散输入数据到多个缓冲区和从多个缓冲区集中输出数据的功能。
这两个都属于原子操作,缓冲区组中的数据都是一次性输入或输出
#include <sys/uio.h>
ssize_t readv(int fildes, const struct iovec *iov, int iovcnt);
ssize_t writev(int fildes, const struct iovec *iov, int iovcnt);
6.1 iovec: 传输数组的缓冲区组
6.2 将数据输入到缓冲区数组 iovec
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
...
ssize_t bytes_read;
int fd;
char buf0[20];
char buf1[30];
char buf2[40];
int iovcnt;
struct iovec iov[3];
iov[0].iov_base = buf0;
iov[0].iov_len = sizeof(buf0);
iov[1].iov_base = buf1;
iov[1].iov_len = sizeof(buf1);
iov[2].iov_base = buf2;
iov[2].iov_len = sizeof(buf2);
...
iovcnt = sizeof(iov) / sizeof(struct iovec);
bytes_read = readv(fd, iov, iovcnt);
...
6.3 将缓冲区数组的数据输出
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
...
ssize_t bytes_written;
int fd;
char *buf0 = "short string\n";
char *buf1 = "This is a longer string\n";
char *buf2 = "This is the longest string in this example\n";
int iovcnt;
struct iovec iov[3];
iov[0].iov_base = buf0;
iov[0].iov_len = strlen(buf0);
iov[1].iov_base = buf1;
iov[1].iov_len = strlen(buf1);
iov[2].iov_base = buf2;
iov[2].iov_len = strlen(buf2);
...
iovcnt = sizeof(iov) / sizeof(struct iovec);
bytes_written = writev(fd, iov, iovcnt);
...
6.4 Linux 2.6.30 版本新增了两个系统调用 :preadv()和pwritev(),可以在制定文件偏移量处进行分散输入和集中输出。
#include <sys/uio.h>
ssize_t preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset);
ssize_t pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset);
7. truncate()和ftruncate()
truncate()和ftruncate()用来截断文件,将文件大小设置为length参数制定的值。
#include <unistd.h>
int truncate(const char *path, off_t length);
int ftruncate(int fildes, off_t length);
8. mkstemp()和tmpfile()
用来创建临时文件
#include <stdlib.h>
int mkstemp(char *template);
FILE *tmpfile(void);