2. 摄像头设备打开与关闭

任务目标

本案例实现通过V4L2接口打开指定摄像头设备(/dev/video0),检查设备打开状态,并在使用完毕后正确关闭设备。核心是掌握open()/close()系统调用在V4L2设备上的标准用法及错误处理流程。

核心实现

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>

#define DEVICE_PATH "/dev/video0"

int main(void)
{
    int fd = -1;
    struct v4l2_capability cap;

    /* 1. 打开设备 */
    fd = open(DEVICE_PATH, O_RDWR);
    if (fd < 0) {
        fprintf(stderr, "打开 %s 失败: %s\n", DEVICE_PATH, strerror(errno));
        return EXIT_FAILURE;
    }

    /* 2. 检查设备是否为有效的V4L2设备 */
    memset(&cap, 0, sizeof(cap));
    if (ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0) {
        fprintf(stderr, "设备不支持V4L2: %s\n", strerror(errno));
        close(fd);
        return EXIT_FAILURE;
    }

    printf("设备打开成功\n");
    printf("驱动名称: %s\n", cap.driver);
    printf("设备名称: %s\n", cap.card);
    printf("总线信息: %s\n", cap.bus_info);

    /* 3. 检查是否支持视频采集 */
    if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
        fprintf(stderr, "设备不支持视频采集\n");
        close(fd);
        return EXIT_FAILURE;
    }

    /* 4. 正常关闭设备 */
    if (close(fd) < 0) {
        fprintf(stderr, "关闭设备失败: %s\n", strerror(errno));
        return EXIT_FAILURE;
    }

    printf("设备已正确关闭\n");
    return EXIT_SUCCESS;
}

编译与运行

# 编译
gcc -o v4l2_open_close v4l2_open_close.c

# 运行(需要root权限或video组权限)
./v4l2_open_close

验证方法

满足以下条件即判定通过:

  • 程序退出码为0,且依次输出“设备打开成功”“设备已正确关闭”
  • 输出的驱动名称、设备名称与v4l2-ctl --list-devices查询结果一致
  • 若设备不存在或权限不足,程序输出对应strerror错误信息并以非零码退出

关键说明

  • open()使用O_RDWR标志,确保后续可进行读写操作;若仅查询能力可用O_RDONLY
  • VIDIOC_QUERYCAP是验证设备是否为V4L2设备的标准方法,避免对非摄像头设备误操作
  • 关闭设备后应将fd置为-1,防止悬空指针误用(本示例直接退出,实际工程中需注意)
  • 错误处理覆盖了打开失败、非V4L2设备、不支持采集、关闭失败四种典型场景