Input子系统剖析

Posted 嵌入式开发白菜

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Input子系统剖析相关的知识,希望对你有一定的参考价值。

Input子系统是Linux内核中的一个重要组成部分,它负责处理各种输入设备(例如键盘、鼠标等)发送的数据,并将其转换为用户空间可用的格式。本文将介绍Input子系统的基本架构和功能。

Input子系统的基本架构由三个组件构成:驱动程序、输入核心和用户接口。其中,驱动程序负责与硬件设备通信并读取输入数据;输入核心负责将输入数据处理和传递到用户接口;用户接口则提供了访问输入设备数据的API接口。

首先,我们需要了解驱动程序的工作原理。在Linux内核中,每个输入设备都由一个对应的驱动程序进行控制。驱动程序通过注册到Input子系统中,并使用一些特定的API函数来告知内核如何读取输入数据。例如,以下代码演示了如何使用Input子系统API函数注册一个键盘驱动程序:

c复制代码

struct input_dev *dev;

dev = input_allocate_device();

dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_SYN);

dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT);

dev->name = "My Keyboard";

input_register_device(dev);

在上述例子中,input_allocate_device()函数用于分配一个新的输入设备结构体;evbit和keybit数组用于设置设备支持的事件类型和键位;name字段则用于指定设备名称。最后,我们调用input_register_device()函数将输入设备添加到Input子系统中进行管理。

其次,我们需要了解输入核心的工作原理。在驱动程序读取完输入数据之后,它会将数据传递给输入核心进行处理。输入核心首先会进行事件分类,即将不同类别的输入事件(例如按键、鼠标移动等)进行分离。然后,输入核心将这些事件转换为通用格式,并将其存储在内核缓冲区中以供用户空间访问。最后,输入核心通过一些特定的API函数将内核缓冲区中的输入数据传递给用户空间。

最后,我们需要了解用户接口的工作原理。用户接口提供了一组API函数,用于访问内核缓冲区中的输入数据。这些函数包括read()、poll()、select()等,可以根据用户的需求实现阻塞或非阻塞方式的输入数据读取。例如,以下代码演示了如何使用read()函数从输入设备中读取数据:

c复制代码

int fd;

char buf[32];

fd = open("/dev/input/event0", O_RDONLY);

read(fd, buf, sizeof(buf));

在上述例子中,open()函数用于打开一个输入设备文件,并返回一个文件描述符;read()函数则用于从输入设备中读取数据。读取的数据存储在buf缓冲区中,并具有固定的格式。

总之,Input子系统是Linux内核中一个重要的组成部分,负责处理各种输入设备并将其转换为用户空间可用的格式。通过驱动程序、输入核心和用户接口三个组件的协同工作,Input子系统可以实现高效稳定的输入数据读取和处理,并为用户空间提供了一组方便易用的API函数。

FFmpeg init_input函数剖析

函数调用逻辑
avformat_open_input
       init_input
            av_probe_input_buffer2


函数原型

static int init_input(AVFormatContext *s, const char *filename, AVDictionary **options)

函数说明
主要是调用av_probe_input_buffer2函数探测码流格式。AVFormatContext结构体flags变量,在经过avformat_alloc_context创建AVFormatContext结构体对象指针之后,flags值是0x200000(AVFMT_FLAG_AUTO_BSF),含义是等待包数据然后确定码流的文件格式,或者是添加一个字节流的过滤器(Wait for packet data before writing a header, and add bitstream filters as requested by the muxer)
AVFMT_FLAG_DISCARD_CORRUPT  0x0100 ///< Discard frames marked corrupted
AVInputFormat结构体flags变量,在经过av_find_input_format("h264"),返回之后flags的值是0x0100(AVFMT_FLAG_DISCARD_CORRUPT)(Discard frames marked corrupted)

函数代码
static int init_input(AVFormatContext *s, const char *filename,
                      AVDictionary **options)
{
    int ret;
    AVProbeData pd = { filename, NULL, 0 };
    int score = AVPROBE_SCORE_RETRY;

    if (s->pb) {
//当前的flags是0x200000
        s->flags |= AVFMT_FLAG_CUSTOM_IO;
//iformat指定h264码流格式之后,不为NULL
        if (!s->iformat)
            return av_probe_input_buffer2(s->pb, &s->iformat, filename,
                                         s, 0, s->format_probesize);
//s->iformat->flags & AVFMT_NOFILE值为真,但是并没有在日志文件中打印出来Custom AVIOContext makes no sense
        else if (s->iformat->flags & AVFMT_NOFILE)
            av_log(s, AV_LOG_WARNING, "Custom AVIOContext makes no sense and "
                                      "will be ignored with AVFMT_NOFILE format.\n");
        return 0;
    }

    if ((s->iformat && s->iformat->flags & AVFMT_NOFILE) ||
        (!s->iformat && (s->iformat = av_probe_input_format2(&pd, 0, &score))))
        return score;

    if ((ret = s->io_open(s, &s->pb, filename, AVIO_FLAG_READ | s->avio_flags, options)) < 0)
        return ret;

    if (s->iformat)
        return 0;
    return av_probe_input_buffer2(s->pb, &s->iformat, filename,
                                 s, 0, s->format_probesize);
}

以上是关于Input子系统剖析的主要内容,如果未能解决你的问题,请参考以下文章

Input子系统剖析

Linux系统运维常见面试简答题系列(9题)

开源的linux运维监控工具都有哪些

Linux运维之NFS网络文件系统功能介绍及应用场景

运维工程师面试题及答案(网络运维工程师面试题)

运维工程师面试题及答案(网络运维工程师面试题)