【linuxC语言】系统调用IO文件操作

小明 2025-05-05 09:58:39 6

文章目录

  • 前言
  • 一、文件描述符介绍
  • 二、系统调用IO API介绍
    • 2.1 open函数
    • 2.2 close函数
    • 2.3 read函数
    • 2.4 write函数
    • 2.5 lseek函数
    • 三、示例代码
    • ���结

      前言

      在Linux系统中,C语言通过系统调用实现对文件的输入输出(I/O)操作。系统调用提供了访问操作系统核心功能的接口,其中包括文件的创建、读取、写入和关闭等操作。这篇文章将介绍在Linux环境下,如何利用C语言进行基本的文件操作,通过系统调用实现对文件的有效管理。


      一、文件描述符介绍

      在Linux中,文件描述符是一个用来标识打开文件或者其他I/O资源的整数。每当你打开一个文件、网络连接或者其他的I/O资源时,Linux内核会分配一个唯一的文件描述符来标识这个资源。

      文件描述符的作用很重要,因为它允许程序访问和操作打开的文件或者其他I/O资源。通过文件描述符,程序可以读取、写入、关闭以及对文件进行其他操作,比如移动文件指针。文件描述符也被用来进行进程间通信,比如通过管道或者套接字。

      在Linux中,标准输入、标准输出和标准错误输出也分别有对应的文件描述符,它们分别是0、1和这意味着你可以把标准输出重定向到一个文件,或者把标准错误输出发送到另一个程序,这些都是通过文件描述符来完成的。总之,文件描述符在Linux系统中扮演着非常重要的角色,是程序与文件系统和其他I/O资源进行交互的桥梁。

      二、系统调用IO API介绍

      在使用系统调用IO之前我们需要加上下面这些头文件:

      #include 
      #include 
      #include 
      #include 
      

      2.1 open函数

      open函数原型如下:

      int open(const char *pathname, int flags);
      

      参数1为打开文件的位置,他可以打开文件还可以打开一个设备device

      参数2为一个类似于权限设置的一个标识,他有如下取值:

      O_RDONLY:只读方式打开文件。

      O_WRONLY:只写方式打开文件。

      O_RDWR:读写方式打开文件。

      O_CREAT:如果文件不存在,则创建一个新文件。

      O_TRUNC:如果文件存在,将其长度截断为0。

      O_APPEND:在文件末尾追加写入数据,而不是覆盖文件内容。

      O_EXCL:与 O_CREAT 一起使用,如果文件存在则返回错误。

      O_NONBLOCK:以非阻塞方式打开文件。

      O_SYNC:在每次写操作之后立即将数据写入磁盘,确保数据同步。

      这些参数可以单独使用,也可以通过按位或 | 连接

      他的返回值为文件描述符,类型为int

      2.2 close函数

      close用于关闭一个文件描述符

      他的函数原型如下:

      int close(int fd);
      

      参数为文件描述符

      close 返回 0 表示 成功 , 或者 -1 表示 有 错误 发生 .

      2.3 read函数

      read函数原型如下:

      ssize_t read(int fd, void *buf, size_t count);
      

      函数 read() 用于从文件描述符 fd 指定的文件中读取数据,并将读取的数据存储到 buf 指向的内存空间中,最多读取 count 字节的数据。该函数的参数和返回值如下:

      fd:要读取数据的文件描述符。

      buf:指向存储读取数据的缓冲区的指针。

      count:要读取的最大字节数。

      返回值是 ssize_t 类型,表示读取的字节数。如果读取成功,则返回实际读取的字节数;如果到达文件末尾,返回值为0;如果发生错误,返回值为-1,并设置全局变量 errno 来指示发生的错误类型。

      2.4 write函数

      write函数原型如下:

      ssize_t write(int fd, const void *buf, size_t count);
      

      函数 write() 用于将数据从内存中的 buf 写入到文件描述符 fd 所指定的文件中,最多写入 count 字节的数据。该函数的参数和返回值如下:

      fd:要写入数据的文件描述符。

      buf:指向包含要写入数据的缓冲区的指针。

      count:要写入的字节数。

      返回值是 ssize_t 类型,表示实际写入的字节数。如果写入成功,则返回写入的字节数;如果发生错误,返回值为-1,并设置全局变量 errno 来指示错误类型。

      需要注意的是,write() 函数不保证一次性写入所有请求的字节数,它可能写入部分数据,而不是全部。在实际应用中,我们通常需要在返回值不等于请求写入的字节数时进行额外的处理。

      2.5 lseek函数

      lseek函数原型如下:

      off_t lseek(int fd, off_t offset, int whence);
      

      fd:要设置偏移量的文件描述符。

      offset:要移动的偏移量,可以为正数、负数或零。正数表示向文件尾方向移动,负数表示向文件头方向移动,零表示从文件开头计算的绝对偏移量。

      whence:指定偏移量的计算方式,可以是以下几个值之一:

      SEEK_SET:偏移量相对于文件开头计算。

      SEEK_CUR:偏移量相对于当前位置计算。

      SEEK_END:偏移量相对于文件末尾计算。

      返回值是 off_t 类型,表示设置后的文件偏移量。如果设置成功,则返回新的偏移量;如果发生错误,返回值为-1,并设置全局变量 errno 来指示错误类型。

      三、示例代码

      #include 
      #include 
      #include 
      #include 
      #define BUFFER_SIZE 1024
      int main() {
          int fd;
          ssize_t bytes_written, bytes_read;
          off_t offset;
          char buffer[BUFFER_SIZE];
          // 打开文件
          fd = open("example.txt", O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
          if (fd == -1) {
              perror("open");
              exit(EXIT_FAILURE);
          }
          // 写入数据到文件
          const char *data_to_write = "Hello, World!";
          bytes_written = write(fd, data_to_write, strlen(data_to_write));
          if (bytes_written == -1) {
              perror("write");
              exit(EXIT_FAILURE);
          }
          printf("Bytes written: %ld\n", bytes_written);
          // 设置文件偏移量
          offset = lseek(fd, 0, SEEK_SET);
          if (offset == -1) {
              perror("lseek");
              exit(EXIT_FAILURE);
          }
          // 读取文件数据
          bytes_read = read(fd, buffer, BUFFER_SIZE);
          if (bytes_read == -1) {
              perror("read");
              exit(EXIT_FAILURE);
          }
          printf("Bytes read: %ld\n", bytes_read);
          printf("Data read: %.*s\n", (int)bytes_read, buffer);
          // 关闭文件
          if (close(fd) == -1) {
              perror("close");
              exit(EXIT_FAILURE);
          }
          return 0;
      }
      


      总结

      通过系统调用进行文件I/O操作是Linux C编程中的关键方面。我们了解了如何使用系统调用来创建文件、读取文件内容、写入数据,并最终关闭文件。这些基本的文件操作是构建更复杂应用程序的基础。通过合理地利用系统调用,我们能够更好地掌控文件资源,实现高效、稳定的文件处理。在深入学习C语言和Linux编程的过程中,对文件I/O的理解将成为编写强大、可靠程序的不可或缺的一部分。

The End
微信