Click the blue text above to follow us
fcntl() and ioctl() are two system calls used to control file descriptors, each serving different purposes and functionalities in various situations.
1
fcntl() Function
The fcntl() function provides the capability to perform various control operations on an open file descriptor, such as duplicating a file descriptor (similar to dup, dup2), getting/setting file descriptor flags, and getting/setting file status flags. It is a multifunctional tool for managing file descriptors. You can view the prototype of the fcntl() function by using the command “man 2 fcntl”.
#include
int fcntl(int fd, int cmd, ... /* arg */);
The parameters and return values of the fcntl() function are as follows:
-
fd: File descriptor.
-
cmd: Operation command. This specifies the type of operation to be performed on the file descriptor fd. These commands typically start with F_XXX, such as F_DUPFD, F_GETFD, F_SETFD, etc. The specific functions of these commands can be understood by consulting the manual page (man 2 fcntl). Common functionalities include:
-
Duplicating a file descriptor (F_DUPFD or F_DUPFD_CLOEXEC);
-
Getting/setting file descriptor flags (F_GETFD or F_SETFD);
-
Getting/setting file status flags (F_GETFL or F_SETFL);
-
Getting/setting asynchronous IO ownership (F_GETOWN or F_SETOWN);
-
Getting/setting record locks (F_GETLK or F_SETLK).
-
…: The fcntl() function is a variable argument function, and the third parameter must be passed according to the specific cmd.
-
Return value: If the execution fails, it returns -1 and sets errno; if successful, the return value depends on cmd (the operation command). For example, F_DUPFD (duplicate file descriptor) will return a new file descriptor, F_GETFD (get file descriptor flags) will return the file descriptor flags, and F_GETFL (get file status flags) will return the file status flags, etc.
Example usage:
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
int main() {
int fd = open("example.txt", O_RDONLY);
if (fd == -1) {
perror("open");
return 1;
}
// Get file descriptor flags
int flags = fcntl(fd, F_GETFL, 0);
if (flags == -1) {
perror("fcntl");
close(fd);
return 1;
}
// Set file descriptor flags, adding non-blocking flag
if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
perror("fcntl");
close(fd);
return 1;
}
// Other operations...
close(fd);
return 0;
}
2
ioctl() Function
The ioctl() function can be seen as a multifunctional toolbox for file IO operations, capable of handling various miscellaneous and non-unified tasks, typically used for interacting with special files or hardware peripherals.
This blog post only introduces this system call; specific usage will be discussed in advanced articles, such as using ioctl() to obtain LCD-related information. The prototype of the ioctl() function is as follows (you can view it using the command “man 2 ioctl”):
#include
int ioctl(int fd, unsigned long request, ...);
The parameters and return values of the ioctl() function are as follows:
-
fd: File descriptor.
-
request: Used to specify the operation to be performed; the specific value depends on the object of the operation, which will be detailed later.
-
…: Variable argument list, specific parameters are determined based on the request parameter, used for operations related to the request.
-
Return value: Returns 0 on success, -1 on failure.
Example usage:
#include <sys/ioctl.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <linux/fs.h>
int main() {
int fd = open("/dev/sda", O_RDONLY);
if (fd == -1) {
perror("open");
return 1;
}
// Query device block size
long block_size;
if (ioctl(fd, BLKSSZGET, &block_size) == -1) {
perror("ioctl");
close(fd);
return 1;
}
printf("Block size: %ld bytes\n", block_size);
// Other operations...
close(fd);
return 0;
}
Click Read the original text for more exciting content~