• linux内核基本知识一


    1.ioremap映射访问和使用in/out直接访问的区别与联系

    linux中使用ioremap映射访问和使用in/out直接访问的区别与联系???
    Linux内核中,ioremap()函数用于将物理地址映射到虚拟地址空间,以便在内核中访问设备寄存器或
    其他I/O地址空间。而in/out指令则是直接访问I/O端口的指令。

    区别:

    1. ioremap()用于将物理地址映射到虚拟地址空间,而in/out指令是直接对I/O端口进行读写操作。
    2. ioremap()返回的是虚拟地址,可以通过指针访问设备寄存器,
      而in/out指令是直接对I/O端口进行读写操作,不需要进行地址映射。

    联系:

    1. ioremap()和in/out都用于访问设备的I/O地址空间,只是方式不同。
    2. 在驱动程序中,可以使用ioremap()将设备的物理地址映射到虚拟地址空间,
      然后通过指针对设备寄存器进行读写操作。
    3. 在某些情况下,可能需要使用in/out指令直接对I/O端口进行读写操作,
      例如在一些特殊的设备上,或者在一些嵌入式系统中。

    总的来说,ioremap()和in/out都是用于访问设备的I/O地址空间,但方式和应用场景略有不同。
    ioremap()适用于将物理地址映射到虚拟地址空间,然后通过指针访问设备寄存器;
    而in/out指令适用于直接对I/O端口进行读写操作。

    2.strrchr()函数

    在Linux中,strrchr()函数是一个字符串处理函数,用于在一个字符串中查找最后一个出现的指定字符
    函数原型:

    char *strrchr(const  char *s, int c);	//s:搜索的字符串	c:查找的字符
    return  指向最后一个匹配字符的指针,若未找到,则返回NULL
    
    • 1
    • 2

    3.sysfs_create_file()函数

    sysfs_create_file()函数是Linux内核中的一个函数,用于在sysfs文件系统中为指定的内核对象创建一个文件
    函数原型:

    int sysfs_create_file(struct  kobject  *kobj,  const struct attribute *attr);
    kobj:一个指向struct attribute的指针,表示创建文件的属性
    struct kobject和struct attribute是Linux内核中用于管理sysfs文件系统的数据结构。
    struct attribute结构体包含了文件的属性信息,例如文件名、读写权限等。
    
    • 1
    • 2
    • 3
    • 4

    4.C语言标准库提供的一组宏

    //C语言标准库中的一个头文件,提供了一组宏和类型,用于处理可变参数函数。
    //这些宏和类型的目的是允许函数接受可变数量的参数。

    #include 		
    
    void my_function(int count, ...)
    {
        va_list args;
        va_start(args, count);
    
        // 使用 va_arg 获取可变参数列表中的参数值
    
        va_end(args);
    }
    
    va_list steps;
    va_start(steps, step_count);
    va_arg(steps, int);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    这两句代码是用于处理可变参数的宏和函数,用于获取可变参数列表的首地址。

    1. va_list steps;
      va_list 是C语言提供的一种数据类型,用于存储可变参数列表。
      valist 类型的 steps 的变量,为可变参数列表分配内存空间。

    2. va_start(steps, step_count);
      va_start是一个宏,用于初始化 va_list 类型的变量,以便访问可变参数列表。
      argv[0]是一个 va_list 类型的变量,argv[1] 是可变参数列表中的最后一个已知的固定参数。
      va_start 宏将可变参数列表的起始地址存储在 steps 变量中,以便后续访问可变参数。

    3. va_arg(steps, int);
      va_arg是一个宏,用于从可变参数列表中获取下一个参数的值
      arg[0]是一个 va_list 类型的变量, argv[1] 是要获取的参数的类型
      如:va_arg(steps, int); //表示从steps可变参数列表中获取下一个参数,并将其作为int类型返回
      备注:一般会有多个va_arg操作

    4. va_end(steps);
      va_end用于结束可变参数列表的处理,作用是清理和释放与可变参数列表相关的资源。

    e.g.
    #define STEP(type, addr, value)		(type),(addr),(value)
    #define STEP_OVER			(OP_TYPE_NONE),0,0
    #define STEP_CNT(n)		(n)
    调用:i2c_select_steps_init(&(bd->i2c_select_table[I2C_DEV_FAN + 0]),    		\
    		STEP_CNT(2), 					\
    		STEP(OP_TYPE_WR_CPLD, bd->cpldaddr_main_i2c_sel, 0x10),	\
    		STEP_OVER);
    函数:int i2c_select_steps_init(i2c_select_operation_steps *i2c_steps, int step_count, ...)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    5.#define __stringify(x) #x

    __stringify(x)函数是一个预处理宏,用于将参数转换为字符串常量
    在__stringify(x)宏的定义中,第二个#符号是用于字符串化操作的
    在C预处理器中,#符号是一种字符串化操作符,用于将宏参数转换为字符串常量
    这个宏在编写宏定义时非常有用,特别是当你需要将参数转换为字符串以进行日志记录或错误消息时!!!

    6.出参与入参

    func(OUT u8* value, IN u16 offset); //OUT:表示出参 IN:表示入参
    这种参数修饰符并不是C语言的标准特性,而是一种约定或命名规则,
    用于提供更多的信息给开发者,以便更好地理解函数参数的用途和特性。
    在实际代码中,OUT和IN通常是作为注释或文档的一部分使用,以帮助
    开发者理解函数的使用方式。

    7.底层I/O端口的读写、内存映射相关函数

    在Linux系统中,用于访问I/O端口的函数通常定义在asm/io.h头文件中。
    该头文件包含了一系列宏和函数,用于进行I/O端口的读写操作。

    asm/io.h头文件是Linux内核提供的头文件之一,用于底层硬件访问和驱动程序开发。
    它定义了一些宏和函数,用于进行底层I/O端口的读写、内存映射等操作。

    以下是一些常用的I/O端口访问函数和宏定义:
    inb(port):从指定的I/O端口读取一个字节的数据。
    inw(port):从指定的I/O端口读取一个字(两个字节)的数据。
    inl(port):从指定的I/O端口读取一个双字(四个字节)的数据。
    outb(value, port):向指定的I/O端口写入一个字节的数据。
    outw(value, port):向指定的I/O端口写入一个字(两个字节)的数据。
    outl(value, port):向指定的I/O端口写入一个双字(四个字节)的数据。
    这些函数和宏定义在asm/io.h头文件中,可以通过包含该头文件来使用它们。
    在Linux内核开发或底层编程中,使用这些函数和宏可以方便地进行I/O端口的读写操作。

    需要注意的是,asm/io.h头文件通常是Linux内核的一部分,因此在用户空间的应用程序中可能无法直接包含该头文件。
    如果你想在用户空间的应用程序中进行I/O端口的访问,通常需要使用特定的库或驱动程序接口。

    8.驱动编写步骤

    前言:
    sysfs是一种基于RAM的文件系统,它与Kobject结合使用,能够
    将Kernel的数据结构以及属性导出到用户空间,以文件目录结构
    的形式提供对这些数据结构的访问支持。

    1)module_param(参数, 类型, 权限); //传递权限
    2)module_param_named(insmod对应的参数变量名,程序中定义的变量名,类型,权限);
    3)MODULE_PARM_DESC(参数,描述…)//对模块的参数进行描述
    4)EXPORT_SYMBOL(文件或目录或函数或锁)
    EXPORT_SYMBOL标签内定义的函数或者符号对全部内核代码公开,不用修改内核代
    码就可以在您的内核模块中直接调用;
    将一个函数以符号的方式导出给其他模块使用;

    简单驱动步骤:
    1)文件引入(共有文件、私有文件)
    2)SYSFS_RW_ATTR_DEF(参数, 函数1,函数2); //SYSFS函数族
    3)指针数组参数
    e.g. static struct attritube *参数名A[] = {参数。。。};
    4)释放参数
    5)初始化入口函数(可能拥有多个初始化函数)
    6)出口函数
    7)EXPORT_SYMBOL(本文件中使用的变量)
    (备注:向上与内核打交道,向下与硬件打交道)

  • 相关阅读:
    ElasticSearch之Quick.ElasticSearch.Furion组件的使用
    Hive——DML数据操作(数据导入&数据导出)
    一起Talk Android吧(第三百九十八回:从网络中获取Bitmap二)
    【Linux操作系统实战】Linux基础命令面试必备(二)
    k8s利用StatefulSet部署mysql
    网络安全(黑客)自学
    国产测温速度快且功耗低的温度传感芯片MY18E20可Pin-Pin替换DS18B20
    类和对象6:相关内置函数
    no main manifest attribute, in xxx.jar
    《MATLAB 神经网络43个案例分析》:第32章 小波神经网络的时间序列预测——短时交通流量预测
  • 原文地址:https://blog.csdn.net/hold_the_key/article/details/134338745