zoukankan      html  css  js  c++  java
  • linux内核学习:中断中推后执行的部分

    软中断-softirq

    特点

    • 相同和不同的软中断都可以在不同处理器上同时执行
    • 一个软中断不会抢占另一个软中断

    何时执行

    • 从中断程序返回时
    • ksoftirqd线程中
    • 显示调用

    软中断最多有32个,一个32位的整型数据可以被用来标记刮起的软中断

    使用策略

    软中断应用于确实需要的场合,目前只有网络驱动和SCSI驱动中使用。另外,内核定时器和tasklet建立在软中断之上。

    使用方法

    注册软中断

    void open_softirq(int nr, void (*action)(struct softirq_action *))

    nr 静态指定于 linux/interrupt.h ,例如:

    enum
    {
     HI_SOFTIRQ=0,
     TIMER_SOFTIRQ,
     NET_TX_SOFTIRQ,
     NET_RX_SOFTIRQ,
     BLOCK_SOFTIRQ,
     BLOCK_IOPOLL_SOFTIRQ,
     TASKLET_SOFTIRQ,
     SCHED_SOFTIRQ,
     HRTIMER_SOFTIRQ,
     RCU_SOFTIRQ,    /* Preferable RCU should always be the last softirq */
     NR_SOFTIRQS
     };
    action为响应函数。

    触发软中断

    void raise_softirq(unsigned int nr);

    会标记某个软中断为挂起状态,以便在何时的时机执行响应函数。

    tasklet

    关键数据

    struct tasklet_struct
     {
     struct tasklet_struct *next;
     unsigned long state;
     atomic_t count;
     void (*func)(unsigned long);
     unsigned long data;
     };

    执行原理

    连个软中断 HI_SOFTIRQ和 TASKLED_SOFTIRQ,每个下面挂这一个tasklet链表,执行相应软中断的时候,会遍历这两个链表,执行可以执行的tasklet。

    所以说tasklet其实是softirq的复用。

    使用

    DECLARE_TASKLET(name, func, data)
    DECLARE_TASKLET_DISABLED(name, func, data)
    void tasklet_schedule(struct tasklet_struct *t)
    void tasklet_disable(struct tasklet_struct *t)
    void tasklet_enable(struct tasklet_struct *t)

    ksoftirqd

    软中断辅助处理线程,每个CPU核心有一个,nice值为19,优先级最低。

     工作队列

     特点

    每个处理器核心对应一个内核线程。

    关键数据

    struct workqueue_struct {
     struct list_head        pwqs;           /* WR: all pwqs of this wq */
     struct list_head        list;           /* PL: list of all workqueues */
     
     struct mutex            mutex;          /* protects this wq */
     int                     work_color;     /* WQ: current work color */
     int                     flush_color;    /* WQ: current flush color */
     atomic_t                nr_pwqs_to_flush; /* flush in progress */
     struct wq_flusher       *first_flusher; /* WQ: first flusher */
     struct list_head        flusher_queue;  /* WQ: flush waiters */
     struct list_head        flusher_overflow; /* WQ: flush overflow list */
     
     struct list_head        maydays;        /* MD: pwqs requesting rescue */
     struct worker           *rescuer;       /* I: rescue worker */
     
     int                     nr_drainers;    /* WQ: drain in progress */
     int                     saved_max_active; /* WQ: saved pwq max_active */
     
     struct workqueue_attrs  *unbound_attrs; /* WQ: only for unbound wqs */
     struct pool_workqueue   *dfl_pwq;       /* WQ: only for unbound wqs */
     
     #ifdef CONFIG_SYSFS
     struct wq_device        *wq_dev;        /* I: for sysfs interface */
     #endif
     #ifdef CONFIG_LOCKDEP
     struct lockdep_map      lockdep_map;
     #endif
     char                    name[WQ_NAME_LEN]; /* I: workqueue name */
     
     /* hot fields used during command issue, aligned to cacheline */
     unsigned int            flags ____cacheline_aligned; /* WQ: WQ_* flags */
     struct pool_workqueue __percpu *cpu_pwqs; /* I: per-cpu pwqs */
     struct pool_workqueue __rcu *numa_pwq_tbl[]; /* FR: unbound pwqs indexed by node */
     };
    struct work_struct {
     atomic_long_t data;
     struct list_head entry;
     work_func_t func;
     #ifdef CONFIG_LOCKDEP
     struct lockdep_map lockdep_map;
     #endif
     };

    使用

    创建

    DECLARE_WORK(n, f)
    INIT_WORK

    处理函数

    void work_handler(void *)

    触发

    schedule_work(&work)
    schedule_delayed_work(&work, delay)

    比较

      软中断 tasklet 工作队列
    并发性 同一软中断可同时运行于不同处理器 不同处理器同时只能运行不同的tasklet  
    是否可阻塞 N N Y
  • 相关阅读:
    linux下进程的实际用户ID(有效组)和有效用户ID(有效组ID)
    ubuntu下软件中心闪退问题解决
    LINUX(UNIX)文件I/O学习
    ubunut下桌面文件路径修改
    ubuntu下设置jdk/jre环境
    Fire net
    JavaScript 自己写一个 replaceAll() 函数
    Canvas 绘制一个像素风电子时钟
    Python3 笔记01:求两数之和
    尝试笔记 01 之 CSS 边角上的标签
  • 原文地址:https://www.cnblogs.com/JonnyLulu/p/3712481.html
Copyright © 2011-2022 走看看