Linux终端处理和Poll机制

中断是指在CPU正常运行期间,由于内外部事件或由程序预先安排的事件引起的CPU暂时停止正在运行的程序,转而为该内部或外部事件或预先安排的事件服务 的程序中去,服务完毕后再返回去继续运行被暂时中断的程序。Linux中通常分为外部中断(又叫硬件中断)和内部中断(又叫异常)。

单片机中断处理

①分辨中断类型
②调用处理函数
③清中断

Linux系统 : asm_do_IRQ

1.申请中断:request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,const char *name, void *dev);
①分配irqaction结构。
②setup_irq(irq, action);    a.加入中断链表:irq_desc[irq]->action.  b.设置中断引脚和中断类型:desc->chip->settype()  c.使能中断:desc->chip->startup/enable
2.释放中断:free_irq(irq, dev_id);
①从链表取出中断
②禁止中断,free

中断线共享的数据结构:
   struct irqaction {
    irq_handler_t handler; /* 具体的中断处理程序 */
    unsigned long flags;/*中断处理属性*/
    const char *name; /* 名称,会显示在/proc/interreupts 中 */
    void *dev_id; /* 设备ID,用于区分共享一条中断线的多个处理程序 */
    struct irqaction *next; /* 指向下一个irq_action 结构 */
    int irq;  /* 中断通道号 */
    struct proc_dir_entry *dir; /* 指向proc/irq/NN/name 的入口*/
    irq_handler_t thread_fn;/*线程中断处理函数*/
    struct task_struct *thread;/*线程中断指针*/
    unsigned long thread_flags;/*与线程有关的中断标记属性*/
};

thread_flags参见枚举型:
enum {
    IRQTF_RUNTHREAD,/*线程中断处理*/
    IRQTF_DIED,/*线程中断死亡*/
    IRQTF_WARNED,/*警告信息*/
    IRQTF_AFFINITY,/*调整线程中断的关系*/
};

多个中断处理程序可以共享同一条 中断线(引脚),irqaction 结构中的 next 成员用来把共享同一条中断线的所有中断处理程序组成一个单向链表,dev_id 成员用于区分各个中断处理程序。

 

3.poll机制
 app: poll
 kernel: sys_poll -> do_sys_poll(..., timeout_jiffies) -> poll_initwait(&table); -> init_poll_funcptr(&pwq->pt, __pollwait); -> pt->qproc = qproc -> do_poll(nfds, head, &table, timeout) :
      for(;;)
      {
        if (do_pollfd(pfd, pt)){   ->   mask = file->f_op->poll(file, pwait);  return mask;
                       //驱动poll:
                        __pollwait(flip, &button_waitq, p); //把当前进程挂到button_waitq队列里去
          count++;
          pt = NULL;
        }
        //break的条件:count非0, 超时,有信号在等待处理
        if (count || !*timeout || signal_pending(current))
          break;
        //休眠__timeout 5s
        __timeout = schedule_timeout(__timeout);
      }
   

等待队列:

          在 Linux 驱动程序设计中,可以使用等待队列可以看作保存进程的容器,在阻塞进程时,将进程放入等待队列;

          当唤醒进程时,从等待队列中取出进程.

等待队列的 定义 和 初始化 wait_queue_head_t    DECLARE_WAIT_QUEUE_HEAD  :

          Linux 2.6 内核提供了如下关于等待队列的操作:

          1,定义等待队列.

                    wait_queue_head_t   my_queue

          2,初始化等待队列.

                    init_waitqueue_head ( &my_queue )

          3,定义并初始化等待队列.

                   DECLARE_WAIT_QUEUE_HEAD  ( my_queue )


等待队列的 睡眠  wait_event_interruptible :

有条件睡眠:

              1,  wait_event ( queue , condition )

                    当 condition ( 一个布尔表达式 ) 为真,立即返回;否则让进程进入 TASK_UNINTERRUPTIBLE 模式

                    睡眠,并挂在 queue 参数所指定的等待队列上.


             2,  wait_event_interruptible ( queue , condition )

                    当 condition ( 一个布尔表达式 ) 为真,立即返回;否则让进程进入 TASK_INTERRUPTIBLE 模式

                    睡眠,并挂在 queue 参数所指定的等待队列上.


              3, int  wait_event_killable ( wait_queue_t  queue , condition )

                    当 condition ( 一个布尔表达式 ) 为真,立即返回;否则让进程进入 TASK_KILLABLE 模式

                    睡眠,并挂在 queue 参数所指定的等待队列上.


无条件睡眠:

                    ( 老版本,不建议使用 )

                    sleep_on  ( wait_queue_head_t  *q )

                    让进程进入 不可中断 的睡眠,并把它放入等待队列 q.


                    interruptible_sleep_on  ( wait_queue_head_t  *q )

                    让进程进入 可中断 的睡眠,并把它放入等待队列 q.


等待队列中唤醒进程 wake_up :

                    wake_up ( wait_queue_t  *q )

                    从等待队列 q 中唤醒状态为 TASKUNINTERRUPTIBLE ,TASK_INTERRUPTIBLE ,TASK_KILLABLE

                    的所有进程.

                    wake_up_interruptible ( wait_queue_t  *q )

                    从等待队列 q 中唤醒状态为 TASK_INTERRUPTIBLE 的进程.

 

你可能感兴趣的:(嵌入式开发)