zoukankan      html  css  js  c++  java
  • linux字符设备学习笔记【原创】

    1、申请设备号

    int register_chrdev_region(dev_t from, unsigned count, const char *name)

    指定从设备号from开始,申请count个设备号,在/proc/devices中的名字为name。返回值:成功返回0,失败返回错误码。

    2、动态的申请设备号

    int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name)

    动态申请从次设备号baseminor开始的count个设备号,在/proc/devices中的名字为name,并通过dev指针把分配到的设备号返回给调用函数者。返回值:成功返回0,失败返回错误码。

    3、卸载申请的设备号

    void unregister_chrdev_region(dev_t from, unsigned count)

    使用:释放从from开始count个设备号。

    4、注册字符设备

    1)分配cdev

    2)初始化cdev

    3)添加cdev

      4.1  分配cdev

    struct cdev* test_cdev;
    test_cdev = cdev_alloc();

      4.2 初始化cdev

    void cdev_init(struct cdev *cdev, const struct file_operations *fops)

    cdev:之前我定义的cdev结构体;fops:设备对应的文件操作结构体。返回值:(函数有可能失败,查看返回值是必须的);成功返回0,示范返回对应的错误码;

      4.3 添加cdev

    int cdev_add(struct cdev *cdev, dev_t dev, unsigned count)

    cdev:指定要被添加的cdev结构体;dev:对应的设备号;count:从设备号dev开始添加count个设备.返回值:成功返回0,失败返回对应的错误码。

      4.3 卸载cdev

    void cdev_del(struct cdev *p)

    5、error

    Linux的出错处理在设计的时候是考虑了跟平台架构相关。

    6、驱动、设备文件、设备号、应用程序之间的关系

    设备号的申请通过register_chrdev_region()调用这个函数进行申请设备号,之后调用cdev_init()将设备注册进内核,要将设备号与驱动关联起来调用cdev_add(),要给应用程序提供一个接口去访问内核的驱动,需要创建一个文本文件可以手动的创建

    mknod /dev/test c 250 0    应用程序通过open这个路径"/dev/test"就可以访问内核。

    7、struct file

    在内核中,file结构体是用来维护打开的文件的。每打开一次文件,内核空间里就会多增加一个file来维护,当文件关闭是释放

    loff_t f_pos;这是用来记录文件的偏移量。

    8、等待队列

     定义
     wait_queue_head_t test_queue;
    初始化
    init_waitqueue_head(&test_queue);

    如果condition为真,将进程加入等待队列并等待唤醒
    wait_event_interruptible(wq, condition)函数调用成功会进入可中断休眠
    wait_event(queue, condition)函数成功会进入不可中断休眠,不推荐

    void wake_up(wait_queue_head_t *queue); //唤醒等待队列中所有休眠的进程
    void wake_up_interruptible(wait_queue_head_t *queue); //唤醒等待队列中所有可中断睡眠的进

    9、自旋锁、

    使用静态定义并初始化:spinlock_t lock = SPIN_LOCK_UNLOCKED;

    使用动态定义并初始化:spinlock_t lock; spin_lock_init(&lock);

    在进入临界区前,必须先获得锁,使用函数:spin_lock(&lock);

    在退出临界区后,需要释放锁,使用函数:spin_unlock(&lock);

    10、信号量

     定义并初始化一个叫name的计数信号量,允许conut个进程同时持有锁:static DECLARE_SEMAPHORE_GENERIC(name, count)

    定义并初始化一个叫name的互斥信号量:static DECLARE_MUTEX(name)

    第二种是动态定义并初始化:

    struct semaphore sem;

    sema_init(&sem, count);

    /*初始化一个互斥信号量*/

    #define init_MUTEX(sem) sema_init(sem, 1)

    /*初始化一个互斥信号量并加锁*/

    #define init_MUTEX_LOCKED(sem) sema_init(sem, 0)

    获取信号量:

    1/*获取信号量sem,如果不能获取,切换状态至TASK_UNINTERRUPTIBLE*/

    voud down(struct semaphore *sem)

    上面的函数不太常用,因为它的睡眠不能被中断打断,一般使用下面的函数

    2/*获取信号量sem,如果不能获取,切换状态至TASK_INTERRUPTIBLE如果睡眠期间被中断打断,函数返回非0*/

    int down_interruputible(struct semaphore *sem)

    3/*尝试获得信号量,如果获得信号量就返回零,不能获得也不睡眠,返回非零值*/

    int down_try_lock(struct semaphore *sem)

    11、使用kmalloc需要包含的头文件

    1 #include <linux/slab.h>
    2 #include <linux/kernel.h>
    3 #include <linux/fs.h>

    12、IO内存

    物理地址映射虚拟地址的函数

    void *ioremap(unsigned long phys_addr, unsigned long size);

    撤销映射的函数

    void ioumap(void *addr);

    13、注册中断处理函数

    int request_irq(unsigned int irq, irq_handler_t handler,unsigned long irqflags, const char *devname, void *dev_id)
    使用:
    将中断号irq与中断处理函数handler对应
    参数:
    irq:指定要分配的中断号,中断号的定义在“include/mach/irqs.h”中。注意,不管是单独占有中断请求线的中断,还是共享中断请求线的每个中断,都有一个对应的中断号。,所以,调用该函数不需要考虑是哪种中断(是否共享寄存器),你想哪种中断响应,你就填对应的中断号。
    handler:中断处理函数指针。
    irqflags:中断处理标记,待会介绍:
    devname:该字符串将显示在/proc/irq和/pro/interrupt中。
    dev_id:ID 号,待会会介绍。
    返回值:成功返回0,失败返回非0。

    释放中断

    void free_irq(unsigned int irq, void *dev_id)

    中断处理函数

    static irqreturn_t intr_handler(int irq, void *dev_id)

    第一个参数irq,这是调用中断处理函数时传给它的中断号,第二个参数dev_id,这个参数与request_irq()的参数dev_id一致

     cat /proc/interrupts 查看自己申请中断的名称

    14、tasklet的使用

     1 定义一个结构体
     2 struct tasklet_struct test_tasklet;
     3 初始化结构体的tasklet的中断处理函数
     4 void tasklet_fun(unsigned long data)
     5 {
     6     printk("---------%s---------
    ",__func__);
     7     printk("data[%ld]
    ",data);
     8 }
     9 调用中断处理函数
    10 tasklet_schedule(&test_tasklet);
    11 初始化tasklet结构体将中断处理函数与之关联
    12 tasklet_init(&test_tasklet,tasklet_fun,(unsigned long)123);
    13 卸载tasklet_kill(&xiaobai_tasklet);

    15、工作队列的使用

     1 定义与创建工作队列:
     2 struct workqueue_struct *test_wq;
     3 test_wq = create_workqueue("test workqueue");
     4 定义工作与处理函数
     5 struct work_struct test_work;
     6 void test_func(struct work_struct *work)
     7 {
     8     printk("hello test work!
    ");
     9 }
    10 将工作与处理函数想关联
    11 INIT_WORK(&test_work,test_func);
    12 将工作加入工作队列进行调度
    13 queue_work(test_wq,&test_work);
    14 销毁工作队列
    15 flush_workqueue(test_wq);
    16 destroy_workqueue(test_wq);

    16、定时器的使用

     1 定义一个定时器
     2 struct timer_list my_timer;
     3 初始化定时器
     4 init_timer(&my_timer);
     5 设置超时时间和定时器的处理函数
     6 my_timer.expires = jiffies + 5*HZ;
     7 my_timer.function = timer_func,
     8 my_timer.data = (unsigned long)99;
     9 void timer_func(unsigned long data)
    10 {
    11     printk("-----------%s------------
    ",__func__);
    12     printk("time out![%ld][%s]
    ",data,current->comm);
    13 
    14     //my_timer.expires = jiffies + 2*HZ;
    15     //add_timer(&my_timer);
    16     mod_timer(&my_timer,jiffies + 2*HZ);
    17 }
    18 
    19 激活定时器
    20 add_timer(&my_timer);
    21 在定时器的处理函数添加,每隔2秒就会执行一次定时器的处理函数
    22 mod_timer(&my_timer,jiffies + 2*HZ);
  • 相关阅读:
    FCC---Learn How Bezier Curves Work---定义坐标轴点的值,影响斜率,改变速度。具体调试换值既可以体会
    FCC---Change Animation Timing with Keywords--两个小球从A都B,相同循环时间 duration, 不同的速度 speed
    FCC---Animate Multiple Elements at Variable Rates---还可以改循环时间,达到不同律动频率的效果
    FCC---Animate Elements at Variable Rates----一闪一闪亮晶晶,不同的闪动节奏
    FCC---Make a CSS Heartbeat using an Infinite Animation Count----超级好看的心跳,粉色的
    FCC---Animate Elements Continually Using an Infinite Animation Count---设置animation-iteration-count的次数为无限,让小球一直跳动
    FCC---Create Visual Direction by Fading an Element from Left to Right---一个带好看背景色的圆形图案,从左到右移动,透明度opacity渐变为0.1,背景色渐渐消失的效果
    FCC---Create Movement Using CSS Animation---设计一个盒子上下左右移动,结合animation, @keyframe, position (上下左右的offset)
    FCC---Use CSS Animation to Change the Hover State of a Button---鼠标移过,背景色变色,用0.5s的动画制作
    Python入门必学知识,30万年薪Python工程师带你学
  • 原文地址:https://www.cnblogs.com/zzb-Dream-90Time/p/6703186.html
Copyright © 2011-2022 走看看