1.相关介绍及常用函数
Linux高级编程中的文件I/O(输入/输出)是操作系统编程中的一个重要部分。在Linux环境下,文件I/O操作通常涉及到对文件描述符(file descriptor)的管理和操作。以下是一些常见的文件I/O操作和相关的系统调用:
-
打开文件:
- 使用
open()
系统调用打开一个文件,并返回一个文件描述符。 - 语法:
int open(const char *pathname, int flags, mode_t mode);
- 使用
-
关闭文件:
- 使用
close()
系统调用关闭一个文件描述符。 - 语法:
int close(int fd);
- 使用
-
读取文件:
- 使用
read()
系统调用从文件中读取数据。 - 语法:
ssize_t read(int fd, void *buf, size_t count);
- 使用
-
写入文件:
- 使用
write()
系统调用向文件写入数据。 - 语法:
ssize_t write(int fd, const void *buf, size_t count);
- 使用
-
文件定位:
- 使用
lseek()
系统调用改变文件描述符的文件偏移量。 - 语法:
off_t lseek(int fd, off_t offset, int whence);
- 使用
-
文件属性:
- 使用
stat()
或fstat()
系统调用来获取文件状态信息。 - 语法:
int stat(const char *pathname, struct stat *buf);
- 语法:
int fstat(int fd, struct stat *buf);
- 使用
-
文件截断:
- 使用
truncate()
或ftruncate()
系统调用来截断文件。 - 语法:
int truncate(const char *path, off_t length);
- 语法:
int ftruncate(int fd, off_t length);
- 使用
-
文件同步:
- 使用
fsync()
或fdatasync()
系统调用来同步文件数据。 - 语法:
int fsync(int fd);
- 语法:
int fdatasync(int fd);
- 使用
-
文件锁定:
- 使用
fcntl()
系统调用来设置或获取文件描述符的属性,包括文件锁定。 - 语法:
int fcntl(int fd, int cmd, ... /* arg */ );
- 使用
-
文件权限和所有权:
- 使用
chmod()
和chown()
系统调用来更改文件权限和所有权。 - 语法:
int chmod(const char *path, mode_t mode);
- 语法:
int chown(const char *path, uid_t owner, gid_t group);
- 使用
1.1 open()函数:
原型: int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
功能:打开一个文件并获得关于这个文件的文件描述符
参数:
pathname:文件名
flags:文件的属性
O_RDONLY: 以只读的方式打开文件
O_WRONLY: 以只写的方式打开文件
O_CREAT:文件不存在会自动创建
O_TRUNC: 文件内容清零
O_APPEND:向文件追加写入
mode:文件权限 0666 (加入O_CREAT选项后,需要0666)
返回值:
成功返回一个新的文件描述符
失败返回-1
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
int fd = open("1.txt",O_WRONLY| O_CREAT|O_TRUNC,0666);
if(-1 == fd)
{
fprintf(stderr,"open error\n");
return 1;
}
printf("fd is %d\n",fd);
return 0;
}
1.2 write()函数
函数原型:ssize_t write(int fd, const void *buf, size_t count);
功能: 向fd对应的文件中写入从buf开始的count个字节数据
参数:
fd: 文件描述符
buf:写入数据的首地址
count:写入数据的大小
返回值:
成功返回实际向文件中写入的字节个数
失败返回-1
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[])
{
int fd = open("1.txt",O_WRONLY| O_CREAT|O_TRUNC,0666);
if(-1 == fd)
{
fprintf(stderr,"open error\n");
return 1;
}
printf("fd is %d\n",fd);
char buf[512]="hello";
int ret = write(fd,buf,strlen(buf));
if(-1 == ret)
{
fprintf(stderr,"write error\n");
return 1;
}
close(fd);
return 0;
}
1.3 read()函数
函数原型: ssize_t read(int fd, void *buf, size_t count);
功能: 从fd对应文件的中读取count个字节数据存入到buf中
参数:
fd: 文件描述符
buf:存储数据的空间首地址
count:存储数据的大小
返回值:
成功返回实际读取到的字节个数
失败返回-1
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int fd = open("1.txt",O_RDONLY);
if(-1 == fd)
{
fprintf(stderr,"open error\n");
return 1;
}
printf("fd is %d\n",fd);
char buf[512]={0};
while(1)
{
int ret = read(fd,buf,sizeof(buf));
if(ret<=0)
{
break;
}
printf("%s\n",buf);
}
close(fd);
return 0;
}
1.4 close()函数
函数原型:int close(int fd)
功能:关闭文件描述符对应的文件
参数:
fd:文件描述符
返回值:
成功返回0
失败返回-1
1.5 lseek()函数
lseek()
函数在 Linux 系统中用于改变文件描述符的文件偏移量,也就是文件的当前读写位置。这个函数非常有用,因为它允许程序在文件中任意位置进行读写操作,而不仅仅是从文件的开头开始。
函数原型:off_t lseek(int fd, off_t offset, int whence);
参数说明
fd
:文件描述符,是一个非负整数,表示要操作的文件。offset
:偏移量,可以是正数、负数或零。这个值将根据whence
参数的设置来解释。whence
:指定offset
参数的解释方式,可以是以下宏之一:SEEK_SET
:文件开头。offset
是相对于文件开头的绝对位置。SEEK_CUR
:当前位置。offset
是相对于当前文件偏移量的相对位置。SEEK_END
:文件结尾。offset
是相对于文件结尾的相对位置(通常是负值)。
返回值
- 成功时,
lseek()
返回新的文件偏移量,即操作后的文件位置。 - 失败时,返回
-1
并设置errno
以指示错误。
错误
EBADF
:fd
不是一个有效的文件描述符。EINVAL
:whence
参数的值无效。ESPIPE
:文件是管道或FIFO,不支持lseek()
。
假设我们有一个文件,我们想要从文件的第10个字节开始读取数据:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int main() {
int fd = open("example.txt", O_RDONLY);
if (fd == -1) {
perror("open");
return 1;
}
off_t offset = 10; // 从文件开头的第10个字节
off_t new_pos = lseek(fd, offset, SEEK_SET);
if (new_pos == -1) {
perror("lseek");
close(fd);
return 1;
}
// 现在可以继续使用 read() 来读取数据
// ...
close(fd);
return 0;
}