嵌入式Linux:fcntl()和ioctl()函数

2024-05-26 10:29:20 浏览数 (1)

fcntl()ioctl()是用于对文件描述符进行控制的两个系统调用,它们在不同的情况下有不同的用途和功能。

1、fcntl()函数

fcntl()函数提供了对已打开文件描述符执行各种控制操作的功能,例如复制文件描述符(与dupdup2类似)、获取/设置文件描述符标志、获取/设置文件状态标志等,是一个多功能的文件描述符管理工具。可通过"man 2 fcntl"命令查看fcntl()函数的原型。

代码语言:javascript复制
#include <fcntl.h>

int fcntl(int fd, int cmd, ... /* arg */);

函数fcntl()的参数和返回值含义如下:

  • fd:文件描述符。
  • cmd:操作命令。用于指定对文件描述符 fd 执行的操作类型。这些命令通常以 F_XXX 开头,如 F_DUPFDF_GETFDF_SETFD 等,具体命令的作用可以通过查阅手册页面(man 2 fcntl)了解,常见的功能包括:
    • 复制文件描述符(F_DUPFDF_DUPFD_CLOEXEC);
    • 获取/设置文件描述符标志(F_GETFDF_SETFD);
    • 获取/设置文件状态标志(F_GETFLF_SETFL);
    • 获取/设置异步 IO 所有权(F_GETOWNF_SETOWN);
    • 获取/设置记录锁(F_GETLKF_SETLK)。
  • ...fcntl() 函数是一个可变参数函数,第三个参数根据不同的 cmd 需要传入相应的实参。
  • 返回值:若执行失败,则返回 -1 并设置 errno;若执行成功,则返回值与 cmd(操作命令)有关。例如,F_DUPFD(复制文件描述符)将返回一个新的文件描述符,F_GETFD(获取文件描述符标志)将返回文件描述符标志,F_GETFL(获取文件状态标志)将返回文件状态标志等。

示例用法:

代码语言:javascript复制
#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;
    }
    
    // 获取文件描述符标志
    int flags = fcntl(fd, F_GETFL, 0);
    if (flags == -1) {
        perror("fcntl");
        close(fd);
        return 1;
    }

    // 设置文件描述符标志,添加非阻塞标志
    if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
        perror("fcntl");
        close(fd);
        return 1;
    }

    // 其他操作...

    close(fd);
    return 0;
}

2、ioctl()函数

ioctl()函数可视为文件IO操作的多功能工具箱,可处理各种杂项且不统一的任务,通常用于与特殊文件或硬件外设交互。

本篇博文只是介绍此系统调用,具体用法将在进阶篇中详细探讨,例如可以利用ioctl获取LCD相关信息等。ioctl()函数原型如下所示(可通过"man 2 ioctl"命令查看):

代码语言:javascript复制
#include <sys/ioctl.h>

int ioctl(int fd, unsigned long request, ...);

函数ioctl()参数和返回值含义如下:

  • fd:文件描述符。
  • request:用于指定要执行的操作,具体值与操作对象有关,后续会详细介绍。
  • ...:可变参数列表,根据 request 参数确定具体参数,用于与请求相关的操作。
  • 返回值:成功时返回 0,失败时返回 -1。

示例用法:

代码语言:javascript复制
#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;
    }

    // 查询设备块大小
    long block_size;
    if (ioctl(fd, BLKSSZGET, &block_size) == -1) {
        perror("ioctl");
        close(fd);
        return 1;
    }
    printf("Block size: %ld bytesn", block_size);

    // 其他操作...

    close(fd);
    return 0;
}

0 人点赞