Linux system call function open(), standard C library function fopen() function explanation and the difference between them

Foreword

If you want to learn more about the Linux system call function lseek() and the standard C library function fopen(), you still need to read the help documentation in the Linux system yourself.
Specific input command:

man 2 open
man 3 fopen

You can view the complete information.

open function

open() is a system call function used to open or create a file in Linux system.

Function prototype:

// Use this function to import the following header files
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

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

Parameters:

  • pathname: This is the pathname of the file to open or create.
  • flags: This is a bitmask that determines the access mode and behavior of the file. Commonly used signs are as follows:
    • O_RDONLY: Open for reading only.
    • O_WRONLY: Open for writing only.
    • O_RDWR: Open for reading and writing.
    • O_CREAT: If the file does not exist, create a new file.
    • O_TRUNC: If the file already exists and is opened for writing (O_WRONLY or O_RDWR), its length is truncated to 0.
    • O_APPEND: At each write, start adding from the end of the file.
  • mode: When using the O_CREAT flag, this parameter is used to specify the permissions of the new file. It should be an octal number, usually set using a file permission macro (for example, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH).

Return value:

  • The open() function returns a file descriptor, which is a small non-negative integer used to refer to the open file in subsequent system calls (such as read(), write(), lseek(), or close()) .

  • If the open() call succeeds, the returned file descriptor must be the smallest number of unused file descriptors.

  • If the function call fails, -1 is returned and errno is set to indicate the type of error.

More details and features about open()

  • File Descriptor (File Descriptors): When you use open() to open a file, the system will return a file descriptor, which is an integer, used for subsequent operations (such as reading, writing or close file) identifier. File descriptors are part of process resources, and each process has its own file descriptor table. This means that different processes can open the same file and get different file descriptors, which are unique to each process.

  • Concurrency (Concurrency): If multiple processes open the same file at the same time, some concurrency issues may arise. To solve these problems, open() provides some additional flags, such as O_EXCL (when used with O_CREAT, open() will fail if the file already exists) and O_SYNC (write operation will wait for physical I/O to complete).

  • File Offset (File Offsets): When you open a file, the file offset (the current read/write position in the file) is usually set to the beginning of the file. If you open the file with the O_APPEND flag, each write operation will move the file offset to the end of the file, so new data will be appended to the end of the file.

  • Error Handling (Error Handling): If the open() function call fails, it returns -1 and sets the global variable errno to indicate the error. You can use the error macros defined in to determine the error type, and you can also use the perror() or strerror() functions to get the error description.

Here is an example of using the open() function, which opens a file for writing and creates it if it does not exist:

#include <fcntl.h>
#include <stdio.h>
#include <errno.h>

int main() {<!-- -->
    int fd;

    fd = open("testfile.txt", O_WRONLY | O_CREAT, S_IRWXU);
    if (fd == -1) {<!-- -->
        perror("open");
        return 1;
    }

    /* Read and write operations can be performed here */

    close(fd); // remember to close the file

    return 0;
}

In this example, we use the perror() function to print an error message if the open() call fails. S_IRWXU is the file permission, indicating that the file owner has read, write and execute permissions.

fopen function

The fopen() function is a function in the standard C library for opening files.

Its prototype is as follows:

#include <stdio.h> // Use this function to import this header file

FILE *fopen(const char *filename, const char *mode);

The parameters are described as follows:

  • filename: This is the pathname of the file to open or create.
  • mode: This is a string representing the access mode of the file. Commonly used patterns include:
    • “r”: Open for read-only. File must exist.
    • “w”: Open for writing only. If the file exists, it will be truncated to zero length. If the file does not exist, try to create it.
    • “a”: Append write mode. If the file exists, the data will be appended to the end of the file. Attempts to create the file if it does not exist.
    • “r + “: Open for reading and writing. File must exist.
    • “w + “: Open for reading and writing. If the file exists, it will be truncated to zero length. If the file does not exist, try to create it.
    • “a +”: Open for reading and writing. If the file exists, the data will be appended to the end of the file. If the file does not exist, try to create it.

Return value:

  • If the fopen() function call is successful, it returns a FILE * pointer, which is a file stream object for use in subsequent I/O functions (such as fread(), fwrite(), fseek(), or fclose()) The open file is referenced in .

  • If the fopen() call fails, NULL is returned and errno is set to indicate the type of error.

Some other details and features about the fopen() function

  • Binary mode and text mode: On some platforms (such as Windows), fopen() can switch between text mode (the default) and binary mode. In text mode, certain characters such as newlines and carriage returns may be converted automatically. In binary mode, data is read and written as-is without any conversion. You can specify binary or text mode by adding b or t to the mode string. For example, “rb” means read in binary mode, and “wt” means write in text mode.

  • File Streams (File Streams): The FILE * pointer returned by fopen() is actually a file stream. This is the C standard library’s way of abstracting file I/O, treating files as sequences of bytes and providing a uniform way to deal with various types of I/O devices. File streams also provide buffering, which can reduce the number of physical I/O operations, thereby improving performance.

  • Error handling: If the fopen() call fails, you can determine the type of error by looking at errno. You can also use the perror() or strerror() functions to get error descriptions.

  • Close a file: A file opened with fopen() must be closed with fclose(). If you forget to close the file, it can cause a resource leak, which is a common programming error. Even if there is an error writing to the file, you should close the file because fclose() will attempt to flush any unwritten data.

Here is an example of using fopen(), which opens a file for writing, and writes some data to the file:

#include <stdio.h>

int main() {<!-- -->
    FILE *fp;

    fp = fopen("testfile.txt", "w");
    if (fp == NULL) {<!-- -->
        perror("fopen");
        return 1;
    }

    if (fputs("Hello, World!\\
", fp) == EOF) {<!-- -->
        perror("fputs");
        return 1;
    }

    if (fclose(fp) == EOF) {<!-- -->
        perror("fclose");
        return 1;
    }

    return 0;
}

In this example, we open a file with fopen(), write data with fputs(), and close the file with fclose(). If any function call fails, we use perror() to print out an error message.

The difference between the open function and the fopen function

both open() and fopen() can be used to open files in a program, but there are some key differences between them:

  • Library and system calls:

    • open() is a system call, provided directly by the operating system kernel. It provides very low-level file access and is available on all Unix and Unix-like systems, including Linux.
    • In contrast, fopen() is a C standard library function that provides a higher-level interface, including buffering and file location management. Since fopen() is a library function, it is available on all systems that support the C standard library, including non-Unix systems.
  • Return value:

    • open() returns a file descriptor, which is an integer used to refer to the open file in subsequent system calls such as read(), write(), lseek(), or close().
    • In contrast, fopen() returns a FILE * pointer, which is a pointer to a FILE structure for use in subsequent library calls (such as fread(), fwrite(), fseek(), or fclose()) Reference to an open file.
  • Error handling:

    • Both open() and fopen() return a special value on error (-1 for open(), NULL for fopen()) and set the global variable errno to indicate the type of error.
    • However, the C standard library also provides some additional error handling functions, such as perror() and strerror().
  • Buffering:

    • The file I/O provided by fopen() is buffered, meaning that data typically accumulates in memory and is not actually written to disk until a certain amount is reached. This improves efficiency, since disk I/O is typically much slower than memory operations.
    • While open() provides unbuffered I/O, data will be read and written directly to disk.
  • Access Mode:

    • Both open() and fopen() allow you to specify the access mode of the file, such as read-only, write-only, or read-write.
    • However, fopen() also allows you to choose between text mode and binary mode, which is useful when dealing with non-text files such as image or audio files.

In most cases, the high-level interface and buffered I/O provided by fopen() are a better choice. However, if you need lower-level control, or need to use some special file operations (such as fcntl() or ioctl() system calls), then open() may be more suitable.

Summary

  • open() is a Linux system call to open or create a file. It returns a file descriptor for subsequent file operations. open() provides low-level, unbuffered I/O, interacting directly with the operating system kernel.

  • fopen() is a standard C library function that is also used to open or create files. It returns a FILE * pointer for subsequent file operations. fopen() provides a higher-level interface, including buffering and file location management. Since fopen() is a library function, it is available on all systems that support the C standard library.

  • Both can be used to open files in a program, but fopen() provides a higher-level interface, including error handling and file location management. open() provides more direct, low-level file access.

  • In terms of error handling, both will return a special value when an error occurs, and set the global variable errno to indicate the error type. However, the C standard library also provides some additional error handling functions, such as perror() and strerror().

Overall, if you’re writing a standard, cross-platform C program, fopen() is probably your best choice due to its buffered I/O and cross-platform nature. However, if you’re writing a Unix or Linux program that needs finer-grained control over the file system, needs lower-level control, or needs to use some special file operations, then open() may be more suitable.

Finally, if you think my article is well written, please give me a like and bookmark, follow me, and I will continue to bring you more and better dry content.