Understanding error codes
Linux error codes
Before implementing the read method, let me quickly explain the error codes (shown in Figure 1) which we should be using in our driver methods.
In Linux, error codes, often referred to as errno
values, are standardized and defined in the <errno.h>
header file. These error codes are used by system calls and library functions to indicate various error conditions that can occur during program execution. Here are some common errno
values and their meanings:
Whenever an error happens, you should return an appropriate error code from your driver method, that is really important.
EACCES (Permission Denied):
This error code is returned when a process does not have the necessary permissions to perform a particular operation, such as opening a file or accessing a resource.
EEXIST (File Exists):
It is returned when a file or directory already exists and a creation operation is attempted with the same name.
EINVAL (Invalid Argument):
This error indicates that an invalid argument was passed to a system call or function.
ENOENT (No Such File or Directory):
It signifies that a file or directory being referenced does not exist in the filesystem.
ENOMEM (Out of Memory):
This error occurs when an operation fails due to insufficient memory available in the system.
EIO (Input/Output Error):
It is used to indicate a hardware or low-level I/O error, often related to storage devices or hardware communication.
ENOSPC (No Space Left on Device):
This error is returned when there is no more space available on the storage device to perform a write operation.
ENOTTY (Not a Typewriter):
It indicates that an operation is not supported on a terminal device, often used for ioctl-related errors.
EPIPE (Broken Pipe):
This error occurs when a process tries to write to a pipe that has no readers, or when a pipe write operation fails for some reason.
EINTR (Interrupted System Call):
It is returned when a system call is interrupted by a signal before it could complete successfully.
EBUSY (Device or Resource Busy):
This error indicates that the requested device or resource is already in use by another process.
ENOTDIR (Not a Directory):
It signifies that an operation expected a directory but encountered a non-directory file.
ENOTEMPTY (Directory Not Empty):
It is used when an attempt is made to delete a non-empty directory.
ENAMETOOLONG (File Name Too Long):
This error is returned when a file path or name exceeds the system-defined maximum length.
ENOSYS (Function Not Implemented):
It indicates that a function or system call is not implemented on the current platform or kernel version.
EROFS (Read-Only File System):
This error is returned when an attempt is made to write to a read-only filesystem.
These are just a few examples of the many error codes available in Linux. Programmers can use these error codes to diagnose and handle errors in their code effectively, improving the reliability and robustness of Linux applications.
The error codes will travel from kernel space to the user space. And in the user space, the user space global variable errno will be set to the error code what you returned from the kernel modules. And the user program can read the errno value to understand what exactly went wrong with the system call handling in the kernel space.
These a errno values or error codes are actually mentioned in this header file errno-base.h. For more information, you can refer to this (include/uapi/asm-generic/errno-base.h) header file.
You should select the appropriate error code. You should not return the error code randomly. For example, let’s say you are copying some data from kernel space to the user space by using copy_to_user and let’s say the copy_to_user returns a non-zero value. That means there was some problem with the memory pointers of the userspace. In that case, you should be returning EFAULT. That means bad address. So, this error code should be passed to the user space, and the errno variable of the user space will be set to EFAULT. Then the user-level program can read that errno value, and it can report that to the user appropriately.
Let’s say the user-level program wants to write some data into the device memory, and let’s say there is no device memory. It is full. Then you should be returning NOMEM out of memory. When you return ENOMEM, then the user level understands that there is a no memory left on the device. Like that, you have to select the appropriate error code from this table what you find in this header file.
In the next article, let’s code for our read method.
Get the Linux Device Driver Full Course Here.
FastBit Embedded Brain Academy Courses
Click here: https://fastbitlab.com/course1