Comprehensive Guide to File Operations and System Calls in C
File operations and system calls are fundamental aspects of programming in C, essential for managing files, performing I/O operations, and interacting with the underlying operating system.
This comprehensive guide will walk you through creating, opening, closing, reading, and writing files, along with the following:
File descriptors,
Standard file descriptors,
I/O system calls,
Flags,
File permissions,
System calls, and
The difference between functions and system calls.
Creating, Opening, Closing, Reading, and Writing Files
Creating and Opening Files:
In C, files are created and opened using the fopen()
function provided by the standard library. The fopen()
function takes a filename and a mode as arguments and returns a file pointer to the opened file.
#include <stdio.h>
int main() {
FILE *fp;
fp = fopen("example.txt", "w+"); // Opens or creates a file named example.txt in write mode
if (fp == NULL) {
printf("Error opening file!\n");
return -1;
}
// File operations go here
fclose(fp); // Close the file when done
return 0;
}
Closing Files:
To close a file and release its resources, the fclose()
function is used. It's essential to close files after performing operations to prevent resource leaks.
fclose(fp); // Close the file pointer 'fp'
Reading from Files:
Reading from files can be achieved using functions like fgetc()
, fgets()
, or fread()
for binary data.
char buffer[255];
fgets(buffer, 255, fp); // Read a line from the file into buffer
Writing to Files:
Writing to files can be done using functions like fputc()
, fputs()
, or fwrite()
for binary data.
fprintf(fp, "This is a formatted string: %s\n", str); // Write a formatted string to the file
File Descriptors
File descriptors are integers used by the operating system to identify open files in a process. They're managed by the kernel and facilitate I/O operations.
Standard File Descriptors:
In POSIX systems, there are three standard file descriptors:
-
0 (STDIN)
: Standard input -
1 (STDOUT)
: Standard output -
2 (STDERR)
: Standard error
I/O System Calls
I/O system calls are low-level functions provided by the operating system for performing input and output operations. Common I/O system calls include open()
, close()
, read()
, and write()
.
open()
System Call:
The open()
system call is used to open files and returns a file descriptor.
int fd = open("example.txt", O_RDONLY); // Opens the file in read-only mode
close()
System Call:
The close()
system call is used to close an open file.
close(fd); // Close the file descriptor 'fd'
read()
and write()
System Calls:
The read()
and write()
system calls are used for reading from and writing to files respectively.
char buffer[255];
read(fd, buffer, sizeof(buffer)); // Read data from the file descriptor 'fd' into buffer
write(fd, "Hello, World!", 13); // Write "Hello, World!" to the file descriptor 'fd'
Flags and File Permissions
Flags and file permissions control the behavior of file operations and define access rights to files. Common flags include O_RDONLY
, O_WRONLY
, and O_RDWR
.
File Permissions:
File permissions determine who can read, write, or execute a file. They are set using the open()
system call by passing an additional argument representing the file permissions.
int fd = open("example.txt", O_CREAT | O_WRONLY, 0644); // Create the file with read-write permissions for owner and read-only permissions for group and others
System Calls vs. Functions
System calls are requests made by user-space programs to the operating system kernel, whereas functions are routines provided by libraries or the standard C library. System calls involve a context switch to kernel mode, making them more expensive in terms of performance compared to library functions.
Understanding file operations, file descriptors, I/O system calls, flags, and file permissions is crucial for developing robust and efficient file-handling applications in C.
By mastering these concepts, you'll be equipped to manipulate files and interact with the operating system effectively within your C programs.
Top comments (1)
The library functions ultimately also make system calls, so the cost of library function calls are in addition to, not instead of, system calls. The library functions don’t somehow have magic access to bypass system calls.
The advantage of library functions is that they are “higher level” and have better APIs for doing most things and also offer choices in buffering.