深入理解Linux底层文件操作:write、read、open、close、lseek和ioctl命令详解
文章目录
- 深入理解Linux底层文件操作:write、read、open、close、lseek和ioctl命令详解
- 1. write 系统调用
- 1.1 功能概述
- 1.2 用法
- 1.3 返回值
- 1.4 注意事项
- 2. read 系统调用
- 2.1 功能概述
- 2.2 用法
- 2.3 返回值
- 2.4 注意事项
- 3. open 系统调用
- 3.1 功能概述
- 3.2 用法
- 3.3 返回值
- 3.4 打开方式
- 3.5 权限设置
- 4. close 系统调用
- 4.1 功能概述
- 4.2 用法
- 4.3 返回值
- 4.4 注意事项
- 5. lseek 系统调用
- 5.1 功能概述
- 5.2 用法
- 5.3 返回值
- 5.4 注意事项
- 6. ioctl 系统调用
- 6.1 功能概述
- 6.2 用法
- 6.3 参数说明
- 总结
深入理解Linux底层文件操作:write、read、open、close、lseek和ioctl命令详解
在Linux中,文件操作是开发中至关重要的一部分。Linux通过一系列的底层系统调用为文件操作提供支持,这些系统调用不仅涉及文件的读取和写入,还涵盖了文件位置的控制以及设备的管理。本文将详细介绍几个常见的文件操作系统调用:write
、read
、open
、close
、lseek
和 ioctl
,并结合代码示例进行深入讲解,帮助开发者更好地理解和使用这些底层文件操作命令。
1. write 系统调用
1.1 功能概述
write
是Linux中的一个底层文件写操作系统调用,它用于将数据从缓冲区写入文件。它直接操作文件描述符,能够把数据写入到标准输出(stdout
)、标准错误(stderr
)或任何其他文件。
1.2 用法
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>int main(void) {char buffer[] = "hello world\n";int len = write(1, buffer, sizeof(buffer));if(len < 0){printf("write to stdout failed. reason: %s\n", strerror(errno));} else {printf("write %d bytes.\n", len);}return 0;
}
1.3 返回值
- 成功:返回实际写入的字节数。
- 失败:返回
-1
,此时可以通过errno
查看具体的错误信息。
1.4 注意事项
write
是从文件的当前指针位置开始写入数据。如果文件是刚打开的,文件指针会指向文件的头部,写入操作会从头开始。- 可以用于写入标准输出和标准错误输出。
2. read 系统调用
2.1 功能概述
read
是Linux中用于从文件中读取数据的系统调用。它将从指定的文件描述符中读取数据,并将数据存储到指定的缓冲区中。这个系统调用通常用于从文件、终端等设备中获取输入。
2.2 用法
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int main(void) {char buffer[1024];int cnt = read(0, buffer, sizeof(buffer)); // 从标准输入读取if (cnt > 0) {write(1, buffer, cnt); // 输出到标准输出}return 0;
}
2.3 返回值
- 大于
0
:表示实际读取的字节数。 - 等于
0
:表示已到达文件尾部,表示文件读取完毕。 - 小于
0
:表示发生了错误,可以通过errno
获取具体的错误信息。
2.4 注意事项
read
的第三个参数表示最多能读取的字节数,但实际读取字节数可以小于这个值。如果文件较短或者文件指针指向文件的末尾,实际读取的字节数可能会小于请求读取的字节数。
3. open 系统调用
3.1 功能概述
open
系统调用用于打开文件并返回文件描述符,这个文件描述符是后续所有文件操作的基础。它可以用来指定文件的打开模式、权限等。
3.2 用法
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>int main(void) {int fd = open("test.txt", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);if(fd < 0){printf("open file failed. reason: %s\n", strerror(errno));exit(-1);}close(fd);return 0;
}
3.3 返回值
- 成功:返回文件描述符,值为一个非负整数。
- 失败:返回
-1
,此时可以通过errno
获取具体的错误信息。
3.4 打开方式
O_RDONLY
:只读模式打开文件。O_WRONLY
:只写模式打开文件。O_RDWR
:读写模式打开文件。O_CREAT
:如果文件不存在,则创建文件。如果文件已存在,则打开文件。O_EXCL
:如果与O_CREAT
一起使用且文件已存在,则返回错误。O_APPEND
:以追加模式打开文件,文件写入操作总是从文件末尾开始。O_TRUNC
:如果文件已经存在且成功打开,则将文件内容截断为零长度。
3.5 权限设置
open
函数的第三个参数用于设置文件权限,特别是当使用 O_CREAT
创建新文件时。常见的权限设置常量包括:
S_IRUSR
:文件所有者可读。S_IWUSR
:文件所有者可写。S_IXUSR
:文件所有者可执行。- 权限通常采用八进制表示,例如
0600
表示文件所有者可读可写,其他用户没有任何权限。
4. close 系统调用
4.1 功能概述
close
用于关闭已打开的文件描述符,释放文件资源。文件描述符被关闭后,其他进程或线程无法再使用该描述符。
4.2 用法
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>int main(void) {int fd = open("test.txt", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);if(fd < 0) {perror("Failed to open file");return -1;}close(fd); // 关闭文件return 0;
}
4.3 返回值
- 成功:返回
0
。 - 失败:返回
-1
,此时可以通过errno
获取具体的错误信息。
4.4 注意事项
- 关闭文件描述符后,可以重新分配文件描述符。因此,应该在文件操作结束后立即关闭文件描述符,释放资源。
5. lseek 系统调用
5.1 功能概述
lseek
系统调用用于更改文件的读写指针位置。它允许开发者在文件中随意定位指定位置,以便进行读取或写入操作。
5.2 用法
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>int main(void) {int fd = open("test.txt", O_RDONLY);if(fd < 0){perror("Failed to open file");return -1;}off_t file_size = lseek(fd, 0, SEEK_END); // 获取文件大小printf("File size: %ld bytes\n", file_size);close(fd);return 0;
}
5.3 返回值
- 成功:返回新的文件指针位置,即当前文件头到文件指针的偏移量。
- 失败:返回
-1
,并将errno
设置为错误码。
5.4 注意事项
SEEK_SET
:从文件开头开始偏移。SEEK_CUR
:从当前指针位置开始偏移。SEEK_END
:从文件末尾开始偏移。
6. ioctl 系统调用
6.1 功能概述
ioctl
是一个用于控制设备的系统调用。它是Linux中设备驱动程序用于与硬件设备进行交互的接口函数。通过 ioctl
,我们可以配置设备的工作参数,如串口的波特率、硬盘的传输速率等。
6.2 用法
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>int main(void) {int fd = open("/dev/ttyS0", O_RDWR);if(fd < 0){perror("Failed to open device");return -1;}int cmd = TIOCGWINSZ; // 获取窗口大小的命令ioctl(fd, cmd, NULL); // 执行ioctl命令close(fd);return 0;
}
6.3 参数说明
fd
:设备的文件描述符,通过open
打开设备文件后得到。cmd
:控制命令,用于指定设备的控制操作。arg
:根据控制命令的不同,可能需要传递一些额外的参数。
总结
通过本文的讲解,我们详细探讨了 write
、read
、open
、close
、lseek
和 ioctl
这些底层文件操作系统调用。每个系统调用都具有其独特的功能和用途,掌握它们的用法对于编写高效的文件操作程序至关重要。理解这些系统调用的细节将帮助你更好地进行文件管理、设备控制以及性能优化。希望本文的内容对你理解Linux的文件操作有所帮助。