Linux下文件I/O系统调用
1、文件描述符
定义:
- 文件描述符(file descriptor, fd)是Linux内核为了高效管理已被打开的文件所创建的索引,其是一个非负整数(通常是小整数),用于指代被打开的文件,所有执行I/O操作的系统调用都通过文件描述符。
- 程序在开始运行时,系统会自动打开三个文件描述符,0是标准输入,1是标准输出,2是标准错误。
- POSIX标准要求每次打开文件时(含socket)必须使用当前进程中最小可用的文件描述符号码,因此第一次打开的文件描述符一定是3。
文件描述符 | 用途 | POSIX文件描述符 | 标准I/O文件流 |
---|---|---|---|
0 | 标准输入 | STDIN_FILENO | stdin |
1 | 标准输出 | STDOUT_FILENO | stdout |
2 | 标准出错 | STDERR_FILENO | stderr |
代码演示:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#define MSG_STR "Hello World\n"
int main(int main, char *argv[])
{
printf("%s", MSG_STR);
fputs(MSG_STR, stdout);
write(STDOUT_FILENO, MSG_STR, strlen(MSG_STR));
return 0;
}
执行结果:
2、文件I\O操作函数
open() 系统调用
头文件:
函数定义:
函数功能:
- 用来打开一个文件。
返回值:
- 返回一个文件描述符(file description)。
参数解析:
- pathname:要打开的文件、设备的路径。
- flags:由多个选项进行“或”运算构造flag参数 。
- mode:需要创建文件时的指定文件的权限模式,如0666。
选项 | |
---|---|
必选 | O_RDONLY (只读)、 O_WRONLY(只写)、 O_RDWR(读写) |
可选 | O_APPEND:每次写时都追加到文件的尾端。 O_CREAT:文件不存在则创建它,使用该选项需要第三个参数mode。 O_TRUNC:如果文件存在,而且为只写或读写成功打开,则将其长度截取为0; O_NONBLOCK:如果path是一个FIFO、块设备、字符特殊文件则此选项为文件的本次打开和后续的I/O操作设置非阻塞模式方式(O_EXEC、O_SEARCH、O_CLOEXEC、O_NOCTTY… )。 |
代码示例:
write() 系统调用
头文件:
函数定义:
函数功能:
- 往打开的文件描述符fd指向的文件中写入buf指向的数据。
返回值:
- 返回值
<0
则说明写入出错,返回值>0
则为实际写入的数据大小。
参数解析:
- fd:文件描述符
- buf:指针
- count:buf指向的要写入的数据的大小
read() 系统调用
头文件:
函数定义:
函数功能:
- 从打开的文件描述符对应的文件中读取数据放到buf指向的内存空间中去。
返回值:
- 返回值
<0
则说明写入出错,返回值>0
则为实际写入的数据大小。
参数解析:
- fd:文件描述符
- buf:指针
- count:buf指向的内存空间剩余的空间大小
lseek()系统调用
- 我们在从文件里读出内容,或往文件写入内容的时候都有一个起始地址,这个起始地址就是当前文件偏移量,当我们对文件进行读写的时候都会使文件偏移量往后偏移。
头文件:
函数定义:
函数功能:
- 调整文件偏移量的地址。
参数解析:
- fd:文件描述符
- offset:文件偏移量的位置
- whence:
whence | 位置 |
---|---|
SEEK_SET | 文件头 |
SEEK_CUR | 当前位置 |
SEEK_END | 文件尾 |
代码示例:
dup() 和 dup2() 系统调用
头文件:
函数定义:
函数功能:
- 复制一个新的文件描述符来指向fd对应的文件。这两个系统调用经常用在标准输入、标准输出、标准出错重定向。
返回值:
- dup()返回的新文件描述符一定是当前可用文件描述符中的最小数值;
- dup2可以用fd2参数来指定新的文件描述符。如果fd2已经打开,则先关闭。如fd等于fd2, 则dup2返回fd2, 而不关闭它。
代码演示:
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char *argv)
{
int fd = -1;
fd = open("std.txt", O_RDWR|O_CREAT|O_TRUNC, 0666);
if(fd < 0)
{
printf("Open file failure: %s\n", strerror(errno));
return ;
}
dup2(fd, STDIN_FILENO); //标准输入重定向到 std.txt 文件中去
dup2(fd, STDOUT_FILENO); //标准输出重定向到 std.txt 文件中去
dup2(fd, STDERR_FILENO); //标准出错重定向到 std.txt 文件中去
printf("fd=%d\n", fd);
close(fd);
}
cat std.txt查看执行结果: