How to Write System Call in C++
This tutorial will discuss the method to call the write
system from a program written in C++. First, we will quickly refresh system calls, specifically the write
system call and its prototype.
Later, we will discuss calling the write
system call from a C++ program.
System Call in C++
Every operating system provides a set of services through system calls. It is a mechanism for computer programs to request a service from the operating system.
System calls provide the following services:
- Process creation and management
- Main memory management
- File and File system management
- Device Input/Output
- Protection
- Networking
The most frequent service required by programs is input/output. Next, we are going to discuss the write
system call.
The programs request the underlying operating system to write on some device through write
system calls.
Before moving ahead toward the write
call, getting an idea about a file descriptor is important.
File Descriptor
In Unix and Unix-based operating systems, a file descriptor is a number that uniquely identifies a file or other IO resources like a socket or pipe.
Normally, the file descriptor is a non-negative integer value. Programs access files for IO through file descriptors.
The library functions deal with IO and take file descriptor as a parameter.
The first step is to open a file by the name (path absolute/relative in case the file is not located in the program’s folder) to access a file for IO.
If the open
function successfully opens a file (i.e., a file exists by the same name and the user has the required rights), it returns a file descriptor.
int fd = open("abc.txt", O_RDONLY | O_CREAT);
The open
function has two parameters. The first parameter is the file name, and the second is the read mode (e.g., read-only mode, write-only, etc.).
The subsequent IO operations on file are performed through the file descriptor.
the write
System Call in C++
The write
system call is one of the most basic routines provided by the operating system kernel. It writes data from primary memory (a buffer) into the file (stored on some hardware device).
The write()
system call writes up to count
bytes from the memory buffer pointed by buf
to a file referred to by the file descriptor.
It is a low-level function that is only capable of understanding bytes. The write
call cannot be used to write records, like classes.
Thus, higher-level input-output functions (like printf()
) are inevitable to perform complex I/O.
Let’s first see the syntax of the write
system call used to write data to a file.
ssize_t write(int fd, const void *buf, size_t count);
The write
function’s three parameters details are:
- The file descriptor
fd
is obtained from the call to open a file. It is an integer value. The values0
,1
, and2
can also be given for standard input, standard output, and standard error, respectively. - The pointer to a buffer
buf
in memory where the data is stored in primary memory. - The number of bytes specified by
count
to be written into the file pointed to byfd
from the bufferbuf
.
The types ssize_t
and size_t
are, respectively, signed and unsigned integer data types defined in stddef.h
.
Return Value
The write
function returns a signed value. On success, it returns the number of bytes successfully written into the file, which may sometimes be less than the specified count
.
The possible reasons for total written bytes to be less than the count
can be the output device memory full or the source write-buffer has less number of chars
to write than the number specified in the count
.
On error, the write
system call returns -1
, and errno
is set to indicate the error encountered.
Here, we have a complete program to write in the file using the write
system call.
#include <errno.h>
#include <fcntl.h>
#include <iostream>
extern int errno;
using namespace std;
int main() {
int fd, count;
fd = open("abc.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);
cout << "File descriptor = " << fd << '\n';
if (fd == -1) {
// print which type of error have in a code
printf("Error Number % d\n", errno);
// print program detail "Success or failure"
perror("Program");
}
char buff[] = "This is a test program to check write system call.";
count = write(fd, buff, 50);
if (count == -1)
cout << "Error writing in file";
else
cout << "Number of bytes written to the file: " << count << '\n';
close(fd);
return 0;
}
The first header file, fcntl.h
, has a write
system call. The second header file has error functions.
In the open
function call, we create a new file name, abc.txt
, in write mode. The file may exist before but using O_TRUNC
, the previous contents will be removed, and a new empty file will be created.
The code 0644
indicates the file permissions. Next, the if
condition checks if the file is successfully opened or not.
In case of failure, the error message will be displayed.
Next, we created a character array (to be used as a buffer) with a sample text. Finally, we are writing into the file.
The third parameter is 50
, stating the number of characters to write from the buff
array.
The count
is the integer value returned from the write()
API call. In case of failure, the value will be -1
; therefore, we check the count and print the error message accordingly.
In case of the successful write operation, we will have a positive value of count, and the if
condition will show the total bytes successfully written to the file.
The first output, value 3
, shows that the file is successfully opened. In the second line, 50
shows that all 50 bytes are successfully written.
Next, we modified the open
statement.
fd = open("abc.txt", O_RDONLY | O_CREAT | O_TRUNC, 0644);
Notice that we have replaced O_WRONLY
with O_RDONLY
, and as a result, the output is:
File descriptor = -1
Error Number 13
Program: Permission denied
Error writing in file
Our open
operation failed because it’s impossible to open an existing file in reading mode by truncating the contents.
As a result of failure, you can see the file descriptor is -1
. Also, the writing operation is unsuccessful.
If we close the file before the write
system call, the result will be an unsuccessful operation by a write
system call. In this case, the output should be something like this:
File descriptor = 3
Error writing in file
Here, the file descriptor is not -1
, but the file is closed; therefore, the write
system call fails.
The value returned by the write
system call is -1
. Therefore, an error message is printed.