首页 > 系统相关 >转载:linux kfifo

转载:linux kfifo

时间:2023-04-09 23:33:23浏览次数:45  
标签:__ kfifo fifo linux KFIFO 转载 type size

参考:https://blog.csdn.net/Bruno_Mars/article/details/100061793

kfifo源码:

https://elixir.bootlin.com/linux/v5.4.240/source/include/linux/kfifo.h#L118

https://elixir.bootlin.com/linux/v5.4.240/source/lib/kfifo.c#L113

kfifo smaple code:

https://elixir.bootlin.com/linux/v5.4.240/source/samples/kfifo

kfifo 特性

kfifo是内核里面的一个First In First Out数据结构

源码位于:

linux\lib\kfifo.c
linux\include\linux\kfifo.h
kfifo 实现了使用简单/性能高效的队列操作

只要满足以下要求, kfifo 操作便可以实现不加锁, 从而提高性能:

只有一个 reader 和 一个 writer,不调用 kfifo_reset(),如果有调用 kfifo_reset_out(), 只在出队线程中调用

而对于多个 writer 对应一个 reader 的情况, 只需要在 writer (入队线程)加锁即可
而对于多个 reader 对应一个 writer 的情况, 只需要在 reader (出队线程)加锁即可
源码中关于锁的相关介绍如下:

/*
 * Note about locking: There is no locking required until only one reader
 * and one writer is using the fifo and no kfifo_reset() will be called.
 * kfifo_reset_out() can be safely used, until it will be only called
 * in the reader thread.
 * For multiple writer and one reader there is only a need to lock the writer.
 * And vice versa for only one writer and multiple reader there is only a need
 * to lock the reader.
 */

 


kfifo 分为两种, 一种是普通的 kfifo, 一种是带长度记录的 kfiro_rec
对于 kfifo,内存 buffer 全部用来存放数据,如下图:

而对于 kfiro_rec,内存 buffer 在每次入队时都会用一个字节或两个字节存放数据的长度,如下图:

kfifo 适用于流数据的数据缓存, 一个线程进行数据入队, 另一个线程进行数据出队处理
kfifo_rec 适用于块数据的数据缓存, 一个线程进行一块块的数据入队, 另一个线程进行每次取一块数据进行

kfifo 结构体

struct __kfifo {
    unsigned int    in;
    unsigned int    out;
    unsigned int    mask;
    unsigned int    esize;
    void        *data;
};

#define __STRUCT_KFIFO_COMMON(datatype, recsize, ptrtype) \
    union { \
        struct __kfifo    kfifo; \
        datatype    *type; \
        const datatype    *const_type; \
        char        (*rectype)[recsize]; \
        ptrtype        *ptr; \
        ptrtype const    *ptr_const; \
    }

#define __STRUCT_KFIFO(type, size, recsize, ptrtype) \
{ \
    __STRUCT_KFIFO_COMMON(type, recsize, ptrtype); \
    type        buf[((size < 2) || (size & (size - 1))) ? -1 : size]; \
}

#define STRUCT_KFIFO(type, size) \
    struct __STRUCT_KFIFO(type, size, 0, type)

#define __STRUCT_KFIFO_PTR(type, recsize, ptrtype) \
{ \
    __STRUCT_KFIFO_COMMON(type, recsize, ptrtype); \
    type        buf[0]; \
}

#define STRUCT_KFIFO_PTR(type) \
    struct __STRUCT_KFIFO_PTR(type, 0, type)
/*
 * helper macro to distinguish between real in place fifo where the fifo
 * array is a part of the structure and the fifo type where the array is
 * outside of the fifo structure.
 */
#define    __is_kfifo_ptr(fifo) \
    (sizeof(*fifo) == sizeof(STRUCT_KFIFO_PTR(typeof(*(fifo)->type))))

/**
 * DECLARE_KFIFO_PTR - macro to declare a fifo pointer object
 * @fifo: name of the declared fifo
 * @type: type of the fifo elements
 */
#define DECLARE_KFIFO_PTR(fifo, type)    STRUCT_KFIFO_PTR(type) fifo

/**
 * DECLARE_KFIFO - macro to declare a fifo object
 * @fifo: name of the declared fifo
 * @type: type of the fifo elements
 * @size: the number of elements in the fifo, this must be a power of 2
 */
#define DECLARE_KFIFO(fifo, type, size)    STRUCT_KFIFO(type, size) fifo

/**
 * INIT_KFIFO - Initialize a fifo declared by DECLARE_KFIFO
 * @fifo: name of the declared fifo datatype
 */
#define INIT_KFIFO(fifo) \
(void)({ \
    typeof(&(fifo)) __tmp = &(fifo); \
    struct __kfifo *__kfifo = &__tmp->kfifo; \
    __kfifo->in = 0; \
    __kfifo->out = 0; \
    __kfifo->mask = __is_kfifo_ptr(__tmp) ? 0 : ARRAY_SIZE(__tmp->buf) - 1;\
    __kfifo->esize = sizeof(*__tmp->buf); \
    __kfifo->data = __is_kfifo_ptr(__tmp) ?  NULL : __tmp->buf; \
})

/**
 * DEFINE_KFIFO - macro to define and initialize a fifo
 * @fifo: name of the declared fifo datatype
 * @type: type of the fifo elements
 * @size: the number of elements in the fifo, this must be a power of 2
 *
 * Note: the macro can be used for global and local fifo data type variables.
 */
#define DEFINE_KFIFO(fifo, type, size) \
    DECLARE_KFIFO(fifo, type, size) = \
    (typeof(fifo)) { \
        { \
            { \
            .in    = 0, \
            .out    = 0, \
            .mask    = __is_kfifo_ptr(&(fifo)) ? \
                  0 : \
                  ARRAY_SIZE((fifo).buf) - 1, \
            .esize    = sizeof(*(fifo).buf), \
            .data    = __is_kfifo_ptr(&(fifo)) ? \
                NULL : \
                (fifo).buf, \
            } \
        } \
    }

参考https://elixir.bootlin.com/linux/v5.4.240/source/samples/kfifo/inttype-example.c#L40,有两种方式定义kfifo:

DYNAMIC:使用DECLARE_KFIFO_PTR定义kfifo 后,使用kfifo_alloc 初始化struct _kfifo, 并动态申请kfifo->data的memory

STATIC:使用DEFINE_KFIF定义kfifo.

#ifdef DYNAMIC
static DECLARE_KFIFO_PTR(test, int);
#else
static DEFINE_KFIFO(test, int, FIFO_SIZE);
#endif
static int __init example_init(void)
{
#ifdef DYNAMIC
    int ret;

    ret = kfifo_alloc(&test, FIFO_SIZE, GFP_KERNEL);
    if (ret) {
        printk(KERN_ERR "error kfifo_alloc\n");
        return ret;
    }
#endif
    if (testfunc() < 0) {
#ifdef DYNAMIC
        kfifo_free(&test);
#endif
        return -EIO;
    }

    if (proc_create(PROC_FIFO, 0, NULL, &fifo_fops) == NULL) {
#ifdef DYNAMIC
        kfifo_free(&test);
#endif
        return -ENOMEM;
    }
    return 0;
}

static void __exit example_exit(void)
{
    remove_proc_entry(PROC_FIFO, NULL);
#ifdef DYNAMIC
    kfifo_free(&test);
#endif
}

 

标签:__,kfifo,fifo,linux,KFIFO,转载,type,size
From: https://www.cnblogs.com/fellow1988/p/17301453.html

相关文章

  • 使用paramiko上传文件到Linux并且解压
    思路是,使用zipfile对文件进行压缩,之后使用paramiko提供的SFTPClient()上传文件,之后使用paramiko的SSHClient()执行Linux命令操作文件importosimportzipfileimportparamiko#使用zipfile压缩文件defzip_code(dir_name,zip_name):file_list=[]ifos.path.is......
  • Linux 杀毒软件发现的漏洞可使得黑客获得 root 权限
    McAfeeVirusScanEnterprisefor Linux 版本中的远程代码执行缺陷,使黑客可以获得root权限,安全研究人员称只需欺骗该app使用恶意更新服务器即可实现。Linux安全软件发现的漏洞可使得黑客获得Root权限来自MITLincolnLaboratory的AndrewFasano在他的帖子中......
  • Linux 杀毒软件发现的漏洞可使得黑客获得 root 权限
    McAfeeVirusScanEnterprisefor Linux 版本中的远程代码执行缺陷,使黑客可以获得root权限,安全研究人员称只需欺骗该app使用恶意更新服务器即可实现。Linux安全软件发现的漏洞可使得黑客获得Root权限来自MITLincolnLaboratory的AndrewFasano在他的帖子中......
  • Linux awk 命令
    Linuxawk命令这玩意非常重要,是自动化的核心、核心、核心AWK是一种处理文本文件的语言,是一个强大的文本分析工具。之所以叫AWK是因为其取了三位创始人AlfredAho,PeterWeinberger,和BrianKernighan的FamilyName的首字符。语法awk[选项参数]'script'var=value......
  • Linux read 命令
    Linuxread命令Linuxread命令用于从标准输入读取数值。read内部命令被用来从标准输入读取单行数据。这个命令可以用来读取键盘输入,当使用重定向的时候,可以读取文件中的一行数据。语法read[-ers][-aaname][-ddelim][-itext][-nnchars][-Nnchars][-pprompt][-......
  • Linux updatedb 命令
    Linuxupdatedb命令updatedb命令用来创建或更新slocate/locate命令所必需的数据库文件。updatedb命令的执行过程较长,因为在执行时它会遍历整个系统的目录树,并将所有的文件信息写入slocate/locate数据库文件中。注意:slocate本身具有一个数据库,里面存放了系统中文件与目......
  • Linux whereis命令
    Linuxwhereis命令Linux命令大全Linux命令大全Linuxwhereis命令用于查找文件。该指令会在特定目录中查找符合条件的文件。这些文件应属于原始代码、二进制文件,或是帮助文件。该指令只能用于查找二进制文件、源代码文件和man手册页,一般文件的定位需使用locate命令。语法w......
  • linux系统下Hadoop集群环境搭建
    1、前言基于redhat7.6系统搭建全分布式Hadoop3.3.5集群环境(模拟三台机,1主角色,2从角色)。 2、安装虚拟机参考:https://www.cnblogs.com/jpxjx/p/16800831.html 3、虚拟机安装redhat7.6参考:https://www.cnblogs.com/jpxjx/p/16815045.html 4、修改主机名vi/etc/hosts......
  • Linux umask命令
    Linuxumask命令暂时只需要知道有这么个东西Linuxumask命令指定在建立文件时预设的权限掩码。umask可用来设定[权限掩码]。[权限掩码]是由3个八进制的数字所组成,将现有的存取权限减掉权限掩码后,即可产生建立文件时预设的权限。语法umask[-S][权限掩码]参数说明:-S以文......
  • Linux which命令
    Linuxwhich命令Linuxwhich命令用于查找文件。which指令会在环境变量$PATH设置的目录里查找符合条件的文件。语法which[文件...]参数:-n<文件名长度>指定文件名长度,指定的长度必须大于或等于所有文件中最长的文件名。-p<文件名长度>与-n参数相同,但此处的<文件名长......