精华内容
下载资源
问答
  • linux驱动request_threaded_irq

    千次阅读 2017-06-26 11:28:07
    内核开始支持中断线程(threaded interrupt handler),使用接口request_threaded_irq;原来的request_irq也继续支持。使用时可根据实际情况选择合适的接口,可使用request_threaded_irq的地方没必要继续使用request_...
    内核开始支持中断线程(threaded interrupt handler),使用接口request_threaded_irq;原来的request_irq也继续支持。使用时可根据实际情况选择合适的接口,可使用request_threaded_irq的地方没必要继续使用request_irq加tasklet/workqueue或者内核线程的方式;如果中断处理简单时也不要执着使用request_threaded_irq。
    在linux里,中断处理分为顶半(top half),底半(bottomhalf),在顶半里处理优先级比较高的事情,要求占用中断时间尽量的短,在处理完成后,就激活底半,有底半处理其余任务。底半的处理方式主要有soft_irq,tasklet,workqueue三种,他们在使用方式和适用情况上各有不同。soft_irq用在对底半执行时间要求比较紧急或者非常重要的场合,主要为一些subsystem用,一般driver基本上用不上。tasklet和work queue在普通的driver里用的相对较多,主要区别是tasklet是在中断上下文执行,而workqueue是在process上下文,因此可以执行可能sleep的操作。

    2.6.30里,在ingo molnar的RT tree里存在有一段时间的interruptthread终于merge到mainline了。此时如果使用request_threaded_irq申请的中断,handler不是在中断上下文里执行,而是在新创建的线程里执行,这样,该handler非常像执行workqueue,拥有所有workqueue的特性,但是省掉了创建,初始化,调度workqueue的繁多步骤。处理起来非常简单。让我们看看这个接口。

    int request_threaded_irq(unsigned int irq, irq_handler_t handler, irq_handler_t thread_fn,
                             unsigned long irqflags, const char *devname, void *dev_id)
    
    和request_irq非常类似,irq是中断号, handler是在发生中断时,首先要执行的code,非常类似于顶半,该函数最后会return IRQ_WAKE_THREAD来唤醒中断线程,
    一般设为NULL,用系统提供的默认处理。thread_fn,是要在线程里执行的handler,非常类似于底半。 后三个参数基本和request_irq相同。irqsflags新增加了一
    个标志,IRQF_ONESHOT,用来标明是在中断线程执行完后在打开该中断,该标志非常有用,否则中断有可能一直在顶半执行,而不能处理中断线程。例如对于
    gpio level中断,如果不设置该位,在顶半执行完成后,会打开中断,此时由于电平没有变化,马上有执行中断,永远没有机会处理线程。
    
    下边一个实际例子来说明它的应用。在手机平台中,检测耳机的插入一般是通过耳机插孔中机械变化导致一个baseband gpio的电平的变化,
    在该gpio中断里进行耳机插入处理。但是耳机插入一般都有个抖动的过程,需要消抖处理。最简单的办法是在中断发生后,延时一段时间(例如200ms),然后再检
    查GPIO状态是否稳定来确定是否有效插入。如果用老的中断方式,不得不用workqueue的方式,你需要在顶半里激活一个delay 200ms的workqueue,然后在workqueue
    里检查。用线程化的处理方式,你仅仅需要在thread_fn里sleep 200ms,然后在检查即可。看,事情就这么简单!

     

     

    函数request_threaded_irq( )首先对传入的参数进行正确性检查,根据传入的irq号获得数组irq_desc中以irq为下标的元素,然后动态的创建一个irqaction描述符,根据传入的参数初始化新生成的irqaction描述符,最后调用函数__setup_irq( )把该描述符加入到IRQ链表中,完成中断的动态申请及注册

    如果返回值是0则说明申请成功,如果申请不成功,则返回的值非零,一般为负数,可能的取值-16-38例如如果返回值是-16,则说明申请的中断号在内核中已被占用

    附注:此函数申请一个中断处理函数(若赋值为NULL,则使用默认的)和线程,当中断发生时,中断处理函数运行于中断上下文,判断是否是自己所属的中断,若是则关闭自身中断并返回IRQ_WAKE_THREAD来唤醒线程函数的执行。在线程执行中,可以睡眠,执行后返回IRQ_HANDLE

    展开全文
  • Linux 安装 Nginx

    万次阅读 2015-08-10 15:25:59
    Linux 安装 Nginx


    1-Nginx 下载

    官方:

    网盘:


    2-Nginx 安装

    Nginx 是 C 语言开发,建议在 Linux 上运行,也可以安装 Windows 版本,本文使用编译安装方式

    a、安装软件包

    yum install -y gcc-c++ pcre pcre-devel zlib zlib-devel openssl openssl-devel
    
    • 安装 gcc
      # 检查 gcc
      gcc --version
      
      # 安装 Nginx 需要将官网下载的源码进行编译,编译依赖 gcc 环境
      yum install -y gcc-c++
      
    • 安装 pcre-devel
      # PCRE(Perl Compatible Regular Expressions) 是一个 Perl 库,包括 perl 兼容的正则表达式库。
      # Nginx 的 http 模块使用 pcre 来解析正则表达式,Nginx 需要此库。
      # pcre-devel 是使用 pcre 开发的一个二次开发库,Nginx 也需要此库。
      yum install -y pcre pcre-devel
      
    • 安装 zlib-devel
      # zlib 库提供了很多种压缩和解压缩的方式, Nginx 使用 zlib 对 http 包的内容进行 gzip ,Nginx 需要此库。
      yum install -y zlib zlib-devel
      
    • 安装 openssl-devel
      # OpenSSL 是一个强大的安全套接字层密码库,囊括主要的密码算法、常用的密钥和证书封装管理功能及 SSL 协议。
      # Nginx 不仅支持 http 协议,还支持 https(即在 ssl 协议上传输http),Nginx 需要此库。
      yum install -y openssl openssl-devel
      

    b、解压 Nginx 源码包

     tar -zxvf /data/targz/nginx-1.19.6.tar.gz -C /data/targz/
    

    在这里插入图片描述
    c、编译安装 Nginx

    # Nginx 编译目录
    cd /data/targz/nginx-1.19.6
    
    # Nginx 编译配置
    # --user --group 指定work进程启动的用户 用户组
    # --prefix 指定安装路径
    # --with-debug 指定日志等级
    # --with-http_stub_status_module 增加监控模块
    # --with-http_ssl_module 启用 https 支持
    # --with-http_gzip_static_module 支持在线实时压缩输出数据流
    # --with-stream
    ./configure \
    --user=root --group=root \
    --prefix=/data/opt/nginx-1.19.6 \
    --with-debug \
    --with-http_stub_status_module \
    --with-http_ssl_module \
    --with-http_gzip_static_module \
    --with-stream \
    --with-stream_ssl_module
    
    # 编译 Nginx
    make && make install
    

    在这里插入图片描述
    d、启动 Nginx

    /data/opt/nginx-1.19.6/sbin/nginx
    

    在这里插入图片描述
    e、访问 Nginx
    在这里插入图片描述


    3-Nginx 命令

    • Nginx 版本
      # 查看 Nginx 版本
      /data/opt/nginx-1.19.6/sbin/nginx -v
      
    • 启动 Nginx
      # 启动 Nginx 
      /data/opt/nginx-1.19.6/sbin/nginx
      
      # 启动 Nginx 指定配置文件(-c:configuration)
      /data/opt/nginx-1.19.6/sbin/nginx -c /data/opt/nginx-1.19.6/conf/nginx.conf
      
    • 更新 Nginx
      # Nginx 更新配置
      /data/opt/nginx-1.19.6/sbin/nginx -s reload
      
    • 停止 Nginx
      # 停止 Nginx 
      /data/opt/nginx-1.19.6/sbin/nginx -s stop
      
      /data/opt/nginx-1.19.6/sbin/nginx -s quit
      

    4-Nginx 问题

    Nginx 启动无法访问。
    在这里插入图片描述
    a、Nginx 是否启动成功

    ps -ef|grep nginx
    

    在这里插入图片描述
    b、Nginx 是否占用 80 端口

    # yum install -y net-tools
    netstat -lnp|grep 80
    

    在这里插入图片描述
    c、客户端是否 ping 通服务器
    在这里插入图片描述
    d、客户端是否可连接 ip:port

    telnet 192.168.65.31:80
    

    在这里插入图片描述
    e、Linux 关闭防火墙或开放端口

    • 关闭防火墙
      # 防火墙状态
      firewall-cmd --state
      
      # 停止 firewall
      systemctl stop firewalld.service
      
      # 禁止 firewall 开机启动
      systemctl disable firewalld.service
      
    • 开放端口
      # 查看已开放端口
      firewall-cmd --list-ports
      	
      # 开启端口:--zone #作用域  --add-port=80/tcp #添加端口(端口/通讯协议) --permanent #永久生效(无此参数重启后失效)
      firewall-cmd --zone=public --add-port=80/tcp --permanent
      	
      # 关闭 selinux:将 etc/selinux/config 文件中 SELINUX=enforcing 改为 SELINUX=disabled
      vi /etc/selinux/config
      

    f、访问 Nginx 成功
    在这里插入图片描述


    展开全文
  • linux驱动request_threaded_irq()

    万次阅读 2014-01-24 19:18:41
    内核开始支持中断线程(threaded interrupt handler),使用接口request_threaded_irq;原来的request_irq也继续支持。使用时可根据实际情况选择合适的接口,可使用request_threaded_irq的地方没必要继续使用request_...

    内核开始支持中断线程(threaded interrupt handler),使用接口request_threaded_irq;原来的request_irq也继续支持。使用时可根据实际情况选择合适的接口,可使用request_threaded_irq的地方没必要继续使用request_irq加tasklet/workqueue或者内核线程的方式;如果中断处理简单时也不要执着使用request_threaded_irq。

    下面先贴上2.6.35内核代码中这两个接口声明的代码,然后转贴一点资料。最后把添加threaded interrupt handler的commit原原本本贴上,供参考。

    #ifdef CONFIG_GENERIC_HARDIRQS
    extern int __must_check
    request_threaded_irq(unsigned int irq, irq_handler_t handler,
           irq_handler_t thread_fn,
           unsigned long flags, const char *name, void *dev);

    static inline int __must_check
    request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
         const char *name, void *dev)
    {
     return request_threaded_irq(irq, handler, NULL, flags, name, dev);
    }

    extern int __must_check
    request_any_context_irq(unsigned int irq, irq_handler_t handler,
       unsigned long flags, const char *name, void *dev_id);

    extern void exit_irq_thread(void);
    #else

    extern int __must_check
    request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
         const char *name, void *dev);

    /*
     * Special function to avoid ifdeffery in kernel/irq/devres.c which
     * gets magically built by GENERIC_HARDIRQS=n architectures (sparc,
     * m68k). I really love these $@%#!* obvious Makefile references:
     * ../../../kernel/irq/devres.o
     */
    static inline int __must_check
    request_threaded_irq(unsigned int irq, irq_handler_t handler,
           irq_handler_t thread_fn,
           unsigned long flags, const char *name, void *dev)
    {
     return request_irq(irq, handler, flags, name, dev);
    }

    static inline int __must_check
    request_any_context_irq(unsigned int irq, irq_handler_t handler,
       unsigned long flags, const char *name, void *dev_id)
    {
     return request_irq(irq, handler, flags, name, dev_id);
    }

    static inline void exit_irq_thread(void) { }
    #endif

     

     

    http://blog.csdn.net/wangyunqian6/article/details/6585873

    在linux里,中断处理分为顶半(top half),底半(bottomhalf),在顶半里处理优先级比较高的事情,要求占用中断时间尽量的短,在处理完成后,就激活底半,有底半处理其余任务。底半的处理方式主要有soft_irq,tasklet,workqueue三种,他们在使用方式和适用情况上各有不同。soft_irq用在对底半执行时间要求比较紧急或者非常重要的场合,主要为一些subsystem用,一般driver基本上用不上。tasklet和work queue在普通的driver里用的相对较多,主要区别是tasklet是在中断上下文执行,而workqueue是在process上下文,因此可以执行可能sleep的操作。

    2.6.30里,在ingo molnar的RT tree里存在有一段时间的interruptthread终于merge到mainline了。此时如果使用request_threaded_irq申请的中断,handler不是在中断上下文里执行,而是在新创建的线程里执行,这样,该handler非常像执行workqueue,拥有所有workqueue的特性,但是省掉了创建,初始化,调度workqueue的繁多步骤。处理起来非常简单。让我们看看这个接口。

    int request_threaded_irq(unsigned int irq, irq_handler_t handler, irq_handler_t thread_fn,
                             unsigned long irqflags, const char *devname, void *dev_id)
    
    和request_irq非常类似,irq是中断号, handler是在发生中断时,首先要执行的code,非常类似于顶半,该函数最后会return IRQ_WAKE_THREAD来唤醒中断线程,
    一般设为NULL,用系统提供的默认处理。thread_fn,是要在线程里执行的handler,非常类似于底半。 后三个参数基本和request_irq相同。irqsflags新增加了一
    个标志,IRQF_ONESHOT,用来标明是在中断线程执行完后在打开该中断,该标志非常有用,否则中断有可能一直在顶半执行,而不能处理中断线程。例如对于
    gpio level中断,如果不设置该位,在顶半执行完成后,会打开中断,此时由于电平没有变化,马上有执行中断,永远没有机会处理线程。
    
    下边一个实际例子来说明它的应用。在手机平台中,检测耳机的插入一般是通过耳机插孔中机械变化导致一个baseband gpio的电平的变化,
    在该gpio中断里进行耳机插入处理。但是耳机插入一般都有个抖动的过程,需要消抖处理。最简单的办法是在中断发生后,延时一段时间(例如200ms),然后再检
    查GPIO状态是否稳定来确定是否有效插入。如果用老的中断方式,不得不用workqueue的方式,你需要在顶半里激活一个delay 200ms的workqueue,然后在workqueue
    里检查。用线程化的处理方式,你仅仅需要在thread_fn里sleep 200ms,然后在检查即可。看,事情就这么简单!

     

     

    函数request_threaded_irq( )首先对传入的参数进行正确性检查,根据传入的irq号获得数组irq_desc中以irq为下标的元素,然后动态的创建一个irqaction描述符,根据传入的参数初始化新生成的irqaction描述符,最后调用函数__setup_irq( )把该描述符加入到IRQ链表中,完成中断的动态申请及注册

    如果返回值是0则说明申请成功,如果申请不成功,则返回的值非零,一般为负数,可能的取值-16-38例如如果返回值是-16,则说明申请的中断号在内核中已被占用

    附注:此函数申请一个中断处理函数(若赋值为NULL,则使用默认的)和线程,当中断发生时,中断处理函数运行于中断上下文,判断是否是自己所属的中断,若是则关闭自身中断并返回IRQ_WAKE_THREAD来唤醒线程函数的执行。在线程执行中,可以睡眠,执行后返回IRQ_HANDLE

     

     

    相关修改是在2009年添加进内核的,具体可参考下面的commit。后面还有些小改动

    commit 3aa551c9b4c40018f0e261a178e3d25478dc04a9
    Author: Thomas Gleixner <tglx@linutronix.de>
    Date:   Mon Mar 23 18:28:15 2009 +0100

        genirq: add threaded interrupt handler support
        
        Add support for threaded interrupt handlers:
        
        A device driver can request that its main interrupt handler runs in a
        thread. To achive this the device driver requests the interrupt with
        request_threaded_irq() and provides additionally to the handler a
        thread function. The handler function is called in hard interrupt
        context and needs to check whether the interrupt originated from the
        device. If the interrupt originated from the device then the handler
        can either return IRQ_HANDLED or IRQ_WAKE_THREAD. IRQ_HANDLED is
        returned when no further action is required. IRQ_WAKE_THREAD causes
        the genirq code to invoke the threaded (main) handler. When
        IRQ_WAKE_THREAD is returned handler must have disabled the interrupt
        on the device level. This is mandatory for shared interrupt handlers,
        but we need to do it as well for obscure x86 hardware where disabling
        an interrupt on the IO_APIC level redirects the interrupt to the
        legacy PIC interrupt lines.
        
        Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
        Reviewed-by: Ingo Molnar <mingo@elte.hu>

    diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h
    index f832883..2dfaadb 100644
    --- a/include/linux/hardirq.h
    +++ b/include/linux/hardirq.h
    @@ -105,7 +105,7 @@
     # define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
     #endif
     
    -#ifdef CONFIG_SMP
    +#if defined(CONFIG_SMP) || defined(CONFIG_GENERIC_HARDIRQS)
     extern void synchronize_irq(unsigned int irq);
     #else
     # define synchronize_irq(irq) barrier()
    diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
    index 0c9cb63..6fc2b72 100644
    --- a/include/linux/interrupt.h
    +++ b/include/linux/interrupt.h
    @@ -59,6 +59,16 @@
     #define IRQF_NOBALANCING 0x00000800
     #define IRQF_IRQPOLL  0x00001000
     
    +/*
    + * Bits used by threaded handlers:
    + * IRQTF_RUNTHREAD - signals that the interrupt handler thread should run
    + * IRQTF_DIED      - handler thread died
    + */
    +enum {
    + IRQTF_RUNTHREAD,
    + IRQTF_DIED,
    +};
    +
     typedef irqreturn_t (*irq_handler_t)(int, void *);
     
     /**
    @@ -71,6 +81,9 @@ typedef irqreturn_t (*irq_handler_t)(int, void *);
      * @next: pointer to the next irqaction for shared interrupts
      * @irq: interrupt number
      * @dir: pointer to the proc/irq/NN/name entry
    + * @thread_fn: interupt handler function for threaded interrupts
    + * @thread: thread pointer for threaded interrupts
    + * @thread_flags: flags related to @thread
      */
     struct irqaction {
      irq_handler_t handler;
    @@ -81,11 +94,31 @@ struct irqaction {
      struct irqaction *next;
      int irq;
      struct proc_dir_entry *dir;
    + irq_handler_t thread_fn;
    + struct task_struct *thread;
    + unsigned long thread_flags;
     };
     
     extern irqreturn_t no_action(int cpl, void *dev_id);
    -extern int __must_check request_irq(unsigned int, irq_handler_t handler,
    -         unsigned long, const char *, void *);
    +
    +extern int __must_check
    +request_threaded_irq(unsigned int irq, irq_handler_t handler,
    +       irq_handler_t thread_fn,
    +       unsigned long flags, const char *name, void *dev);
    +
    +static inline int __must_check
    +request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
    +     const char *name, void *dev)
    +{
    + return request_threaded_irq(irq, handler, NULL, flags, name, dev);
    +}
    +
    +#ifdef CONFIG_GENERIC_HARDIRQS
    +extern void exit_irq_thread(void);
    +#else
    +static inline void exit_irq_thread(void) { }
    +#endif
    +
     extern void free_irq(unsigned int, void *);
     
     struct device;
    diff --git a/include/linux/irq.h b/include/linux/irq.h
    index 873e4ac..8b1cf06 100644
    --- a/include/linux/irq.h
    +++ b/include/linux/irq.h
    @@ -20,6 +20,7 @@
     #include <linux/irqreturn.h>
     #include <linux/irqnr.h>
     #include <linux/errno.h>
    +#include <linux/wait.h>
     
     #include <asm/irq.h>
     #include <asm/ptrace.h>
    @@ -155,6 +156,8 @@ struct irq_2_iommu;
      * @affinity:  IRQ affinity on SMP
      * @cpu:  cpu index useful for balancing
      * @pending_mask: pending rebalanced interrupts
    + * @threads_active: number of irqaction threads currently running
    + * @wait_for_threads: wait queue for sync_irq to wait for threaded handlers
      * @dir:  /proc/irq/ procfs entry
      * @name:  flow handler name for /proc/interrupts output
      */
    @@ -186,6 +189,8 @@ struct irq_desc {
      cpumask_var_t  pending_mask;
     #endif
     #endif
    + atomic_t  threads_active;
    + wait_queue_head_t       wait_for_threads;
     #ifdef CONFIG_PROC_FS
      struct proc_dir_entry *dir;
     #endif
    diff --git a/include/linux/irqreturn.h b/include/linux/irqreturn.h
    index c5584ca..819acaa 100644
    --- a/include/linux/irqreturn.h
    +++ b/include/linux/irqreturn.h
    @@ -5,10 +5,12 @@
      * enum irqreturn
      * @IRQ_NONE  interrupt was not from this device
      * @IRQ_HANDLED  interrupt was handled by this device
    + * @IRQ_WAKE_THREAD handler requests to wake the handler thread
      */
     enum irqreturn {
      IRQ_NONE,
      IRQ_HANDLED,
    + IRQ_WAKE_THREAD,
     };
     
     typedef enum irqreturn irqreturn_t;
    diff --git a/include/linux/sched.h b/include/linux/sched.h
    index 46d6806..38b77b0 100644
    --- a/include/linux/sched.h
    +++ b/include/linux/sched.h
    @@ -1292,6 +1292,11 @@ struct task_struct {
     /* Protection of (de-)allocation: mm, files, fs, tty, keyrings */
      spinlock_t alloc_lock;
     
    +#ifdef CONFIG_GENERIC_HARDIRQS
    + /* IRQ handler threads */
    + struct irqaction *irqaction;
    +#endif
    +
      /* Protection of the PI data structures: */
      spinlock_t pi_lock;
     
    diff --git a/kernel/exit.c b/kernel/exit.c
    index 167e1e3..ca0b348 100644
    --- a/kernel/exit.c
    +++ b/kernel/exit.c
    @@ -1037,6 +1037,8 @@ NORET_TYPE void do_exit(long code)
       schedule();
      }
     
    + exit_irq_thread();
    +
      exit_signals(tsk);  /* sets PF_EXITING */
      /*
       * tsk->flags are checked in the futex code to protect against
    diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
    index 9ebf779..fe8f453 100644
    --- a/kernel/irq/handle.c
    +++ b/kernel/irq/handle.c
    @@ -357,8 +357,37 @@ irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action)
     
      do {
       ret = action->handler(irq, action->dev_id);
    -  if (ret == IRQ_HANDLED)
    +
    +  switch (ret) {
    +  case IRQ_WAKE_THREAD:
    +   /*
    +    * Wake up the handler thread for this
    +    * action. In case the thread crashed and was
    +    * killed we just pretend that we handled the
    +    * interrupt. The hardirq handler above has
    +    * disabled the device interrupt, so no irq
    +    * storm is lurking.
    +    */
    +   if (likely(!test_bit(IRQTF_DIED,
    +          &action->thread_flags))) {
    +    set_bit(IRQTF_RUNTHREAD, &action->thread_flags);
    +    wake_up_process(action->thread);
    +   }
    +
    +   /*
    +    * Set it to handled so the spurious check
    +    * does not trigger.
    +    */
    +   ret = IRQ_HANDLED;
    +   /* Fall through to add to randomness */
    +  case IRQ_HANDLED:
        status |= action->flags;
    +   break;
    +
    +  default:
    +   break;
    +  }
    +
       retval |= ret;
       action = action->next;
      } while (action);
    diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
    index 6458e99..a4c1ab8 100644
    --- a/kernel/irq/manage.c
    +++ b/kernel/irq/manage.c
    @@ -8,16 +8,15 @@
      */
     
     #include <linux/irq.h>
    +#include <linux/kthread.h>
     #include <linux/module.h>
     #include <linux/random.h>
     #include <linux/interrupt.h>
     #include <linux/slab.h>
    +#include <linux/sched.h>
     
     #include "internals.h"
     
    -#if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_HARDIRQS)
    -cpumask_var_t irq_default_affinity;
    -
     /**
      * synchronize_irq - wait for pending IRQ handlers (on other CPUs)
      * @irq: interrupt number to wait for
    @@ -53,9 +52,18 @@ void synchronize_irq(unsigned int irq)
     
       /* Oops, that failed? */
      } while (status & IRQ_INPROGRESS);
    +
    + /*
    +  * We made sure that no hardirq handler is running. Now verify
    +  * that no threaded handlers are active.
    +  */
    + wait_event(desc->wait_for_threads, !atomic_read(&desc->threads_active));
     }
     EXPORT_SYMBOL(synchronize_irq);
     
    +#ifdef CONFIG_SMP
    +cpumask_var_t irq_default_affinity;
    +
     /**
      * irq_can_set_affinity - Check if the affinity of a given irq can be set
      * @irq:  Interrupt to check
    @@ -72,6 +80,18 @@ int irq_can_set_affinity(unsigned int irq)
      return 1;
     }
     
    +static void
    +irq_set_thread_affinity(struct irq_desc *desc, const struct cpumask *cpumask)
    +{
    + struct irqaction *action = desc->action;
    +
    + while (action) {
    +  if (action->thread)
    +   set_cpus_allowed_ptr(action->thread, cpumask);
    +  action = action->next;
    + }
    +}
    +
     /**
      * irq_set_affinity - Set the irq affinity of a given irq
      * @irq:  Interrupt to set affinity
    @@ -100,6 +120,7 @@ int irq_set_affinity(unsigned int irq, const struct cpumask *cpumask)
      cpumask_copy(desc->affinity, cpumask);
      desc->chip->set_affinity(irq, cpumask);
     #endif
    + irq_set_thread_affinity(desc, cpumask);
      desc->status |= IRQ_AFFINITY_SET;
      spin_unlock_irqrestore(&desc->lock, flags);
      return 0;
    @@ -150,6 +171,8 @@ int irq_select_affinity_usr(unsigned int irq)
     
      spin_lock_irqsave(&desc->lock, flags);
      ret = setup_affinity(irq, desc);
    + if (!ret)
    +  irq_set_thread_affinity(desc, desc->affinity);
      spin_unlock_irqrestore(&desc->lock, flags);
     
      return ret;
    @@ -384,6 +407,93 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
      return ret;
     }
     
    +static inline int irq_thread_should_run(struct irqaction *action)
    +{
    + return test_and_clear_bit(IRQTF_RUNTHREAD, &action->thread_flags);
    +}
    +
    +static int irq_wait_for_interrupt(struct irqaction *action)
    +{
    + while (!kthread_should_stop()) {
    +  set_current_state(TASK_INTERRUPTIBLE);
    +  if (irq_thread_should_run(action)) {
    +   __set_current_state(TASK_RUNNING);
    +   return 0;
    +  } else
    +   schedule();
    + }
    + return -1;
    +}
    +
    +/*
    + * Interrupt handler thread
    + */
    +static int irq_thread(void *data)
    +{
    + struct sched_param param = { .sched_priority = MAX_USER_RT_PRIO/2, };
    + struct irqaction *action = data;
    + struct irq_desc *desc = irq_to_desc(action->irq);
    + int wake;
    +
    + sched_setscheduler(current, SCHED_FIFO, &param);
    + current->irqaction = action;
    +
    + while (!irq_wait_for_interrupt(action)) {
    +
    +  atomic_inc(&desc->threads_active);
    +
    +  spin_lock_irq(&desc->lock);
    +  if (unlikely(desc->status & IRQ_DISABLED)) {
    +   /*
    +    * CHECKME: We might need a dedicated
    +    * IRQ_THREAD_PENDING flag here, which
    +    * retriggers the thread in check_irq_resend()
    +    * but AFAICT IRQ_PENDING should be fine as it
    +    * retriggers the interrupt itself --- tglx
    +    */
    +   desc->status |= IRQ_PENDING;
    +   spin_unlock_irq(&desc->lock);
    +  } else {
    +   spin_unlock_irq(&desc->lock);
    +
    +   action->thread_fn(action->irq, action->dev_id);
    +  }
    +
    +  wake = atomic_dec_and_test(&desc->threads_active);
    +
    +  if (wake && waitqueue_active(&desc->wait_for_threads))
    +   wake_up(&desc->wait_for_threads);
    + }
    +
    + /*
    +  * Clear irqaction. Otherwise exit_irq_thread() would make
    +  * fuzz about an active irq thread going into nirvana.
    +  */
    + current->irqaction = NULL;
    + return 0;
    +}
    +
    +/*
    + * Called from do_exit()
    + */
    +void exit_irq_thread(void)
    +{
    + struct task_struct *tsk = current;
    +
    + if (!tsk->irqaction)
    +  return;
    +
    + printk(KERN_ERR
    +        "exiting task \"%s\" (%d) is an active IRQ thread (irq %d)\n",
    +        tsk->comm ? tsk->comm : "", tsk->pid, tsk->irqaction->irq);
    +
    + /*
    +  * Set the THREAD DIED flag to prevent further wakeups of the
    +  * soon to be gone threaded handler.
    +  */
    + set_bit(IRQTF_DIED, &tsk->irqaction->flags);
    +}
    +
     /*
      * Internal function to register an irqaction - typically used to
      * allocate special interrupts that are part of the architecture.
    @@ -420,6 +530,26 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
      }
     
      /*
    +  * Threaded handler ?
    +  */
    + if (new->thread_fn) {
    +  struct task_struct *t;
    +
    +  t = kthread_create(irq_thread, new, "irq/%d-%s", irq,
    +       new->name);
    +  if (IS_ERR(t))
    +   return PTR_ERR(t);
    +  /*
    +   * We keep the reference to the task struct even if
    +   * the thread dies to avoid that the interrupt code
    +   * references an already freed task_struct.
    +   */
    +  get_task_struct(t);
    +  new->thread = t;
    +  wake_up_process(t);
    + }
    +
    + /*
       * The following block of code has to be executed atomically
       */
      spin_lock_irqsave(&desc->lock, flags);
    @@ -456,15 +586,15 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
      if (!shared) {
       irq_chip_set_defaults(desc->chip);
     
    +  init_waitqueue_head(&desc->wait_for_threads);
    +
       /* Setup the type (level, edge polarity) if configured: */
       if (new->flags & IRQF_TRIGGER_MASK) {
        ret = __irq_set_trigger(desc, irq,
          new->flags & IRQF_TRIGGER_MASK);
     
    -   if (ret) {
    -    spin_unlock_irqrestore(&desc->lock, flags);
    -    return ret;
    -   }
    +   if (ret)
    +    goto out_thread;
       } else
        compat_irq_chip_set_default_handler(desc);
     #if defined(CONFIG_IRQ_PER_CPU)
    @@ -532,8 +662,19 @@ mismatch:
       dump_stack();
      }
     #endif
    + ret = -EBUSY;
    +
    +out_thread:
      spin_unlock_irqrestore(&desc->lock, flags);
    - return -EBUSY;
    + if (new->thread) {
    +  struct task_struct *t = new->thread;
    +
    +  new->thread = NULL;
    +  if (likely(!test_bit(IRQTF_DIED, &new->thread_flags)))
    +   kthread_stop(t);
    +  put_task_struct(t);
    + }
    + return ret;
     }
     
     /**
    @@ -559,6 +700,7 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
     {
      struct irq_desc *desc = irq_to_desc(irq);
      struct irqaction *action, **action_ptr;
    + struct task_struct *irqthread;
      unsigned long flags;
     
      WARN(in_interrupt(), "Trying to free IRQ %d from IRQ context!\n", irq);
    @@ -605,6 +747,10 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
       else
        desc->chip->disable(irq);
      }
    +
    + irqthread = action->thread;
    + action->thread = NULL;
    +
      spin_unlock_irqrestore(&desc->lock, flags);
     
      unregister_handler_proc(irq, action);
    @@ -612,6 +758,12 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
      /* Make sure it's not being used on another CPU: */
      synchronize_irq(irq);
     
    + if (irqthread) {
    +  if (!test_bit(IRQTF_DIED, &action->thread_flags))
    +   kthread_stop(irqthread);
    +  put_task_struct(irqthread);
    + }
    +
     #ifdef CONFIG_DEBUG_SHIRQ
      /*
       * It's a shared IRQ -- the driver ought to be prepared for an IRQ
    @@ -664,9 +816,12 @@ void free_irq(unsigned int irq, void *dev_id)
     EXPORT_SYMBOL(free_irq);
     
     /**
    - * request_irq - allocate an interrupt line
    + * request_threaded_irq - allocate an interrupt line
      * @irq: Interrupt line to allocate
    - * @handler: Function to be called when the IRQ occurs
    + * @handler: Function to be called when the IRQ occurs.
    + *    Primary handler for threaded interrupts
    + *      @thread_fn: Function called from the irq handler thread
    + *                  If NULL, no irq thread is created
      * @irqflags: Interrupt type flags
      * @devname: An ascii name for the claiming device
      * @dev_id: A cookie passed back to the handler function
    @@ -678,6 +833,15 @@ EXPORT_SYMBOL(free_irq);
      * raises, you must take care both to initialise your hardware
      * and to set up the interrupt handler in the right order.
      *
    + * If you want to set up a threaded irq handler for your device
    + * then you need to supply @handler and @thread_fn. @handler ist
    + * still called in hard interrupt context and has to check
    + * whether the interrupt originates from the device. If yes it
    + * needs to disable the interrupt on the device and return
    + * IRQ_THREAD_WAKE which will wake up the handler thread and run
    + * @thread_fn. This split handler design is necessary to support
    + * shared interrupts.
    + *
      * Dev_id must be globally unique. Normally the address of the
      * device data structure is used as the cookie. Since the handler
      * receives this value it makes sense to use it.
    @@ -693,8 +857,9 @@ EXPORT_SYMBOL(free_irq);
      * IRQF_TRIGGER_*  Specify active edge(s) or level
      *
      */
    -int request_irq(unsigned int irq, irq_handler_t handler,
    -  unsigned long irqflags, const char *devname, void *dev_id)
    +int request_threaded_irq(unsigned int irq, irq_handler_t handler,
    +    irq_handler_t thread_fn, unsigned long irqflags,
    +    const char *devname, void *dev_id)
     {
      struct irqaction *action;
      struct irq_desc *desc;
    @@ -742,6 +907,7 @@ int request_irq(unsigned int irq, irq_handler_t handler,
       return -ENOMEM;
     
      action->handler = handler;
    + action->thread_fn = thread_fn;
      action->flags = irqflags;
      action->name = devname;
      action->dev_id = dev_id;
    @@ -771,4 +937,4 @@ int request_irq(unsigned int irq, irq_handler_t handler,
     #endif
      return retval;
     }
    -EXPORT_SYMBOL(request_irq);
    +EXPORT_SYMBOL(request_threaded_irq);

    展开全文
  • linux request_module

    千次阅读 2014-03-01 11:09:59
    在soundcore_open打开/dev/dsp节点函数中会调用到下面的: ...函数,这表示,让linux系统的用户空间调用/sbin/modprobe函数加载名为sound-slot-0.ko模块 #define request_module(mod...) __request_module(true
    在soundcore_open打开/dev/dsp节点函数中会调用到下面的:
        request_module("sound-slot-%i", unit>>4);
    函数,这表示,让linux系统的用户空间调用/sbin/modprobe函数加载名为sound-slot-0.ko模块
    #define request_module(mod...) __request_module(true, mod)
    #define request_module_nowait(mod...) __request_module(false, mod)

    luther@gliethttp:~$ cat /proc/sys/kernel/modprobe 
    /sbin/modprobe
    我们也可以向/proc/sys/kernel/modprobe添加新的modprobe应用程序路径,这里的/sbin/modprobe是内核默认路径.

    /**
     * __request_module - try to load a kernel module       // 尝试加载一个ko模块[luther.gliethttp]
     * @wait: wait (or not) for the operation to complete
     * @fmt: printf style format string for the name of the module
     * @...: arguments as specified in the format string
     *
     * Load a module using the user mode module loader. The function returns
     * zero on success or a negative errno code on failure. Note that a
     * successful module load does not mean the module did not then unload
     * and exit on an error of its own. Callers must check that the service
     * they requested is now available not blindly invoke it.
     *
     * If module auto-loading support is disabled then this function
     * becomes a no-operation.
     */
    int __request_module(bool wait, const char *fmt, ...)
    {
        va_list args;
        char module_name[MODULE_NAME_LEN];
        unsigned int max_modprobes;
        int ret;
    // char modprobe_path[KMOD_PATH_LEN] = "/sbin/modprobe";
        char *argv[] = { modprobe_path, "-q", "--", module_name, NULL };
        static char *envp[] = { "HOME=/",
                    "TERM=linux",
                    "PATH=/sbin:/usr/sbin:/bin:/usr/bin",
                    NULL }; // 环境变量.
        static atomic_t kmod_concurrent = ATOMIC_INIT(0);
    #define MAX_KMOD_CONCURRENT 50    /* Completely arbitrary value - KAO */
        static int kmod_loop_msg;

        va_start(args, fmt);
        ret = vsnprintf(module_name, MODULE_NAME_LEN, fmt, args);   // 生成module名,这里就是sound-slot-0
        va_end(args);
        if (ret >= MODULE_NAME_LEN)
            return -ENAMETOOLONG;

        /* If modprobe needs a service that is in a module, we get a recursive  // 对递归循环的一个硬性限制
         * loop.  Limit the number of running kmod threads to max_threads/2 or  // 最多同时运行max_modprobes个modprobe用户程序
         * MAX_KMOD_CONCURRENT, whichever is the smaller.  A cleaner method     // 如果超过,那么__request_module返回-ENOMEM
         * would be to run the parents of this process, counting how many times // [luther.gliethttp]
         * kmod was invoked.  That would mean accessing the internals of the
         * process tables to get the command line, proc_pid_cmdline is static
         * and it is not worth changing the proc code just to handle this case. 
         * KAO.
         *
         * "trace the ppid" is simple, but will fail if someone's
         * parent exits.  I think this is as good as it gets. --RR
         */
        max_modprobes = min(max_threads/2, MAX_KMOD_CONCURRENT);    // 最多同时运行max_modprobes个modprobe用户程序
        atomic_inc(&kmod_concurrent);
        if (atomic_read(&kmod_concurrent) > max_modprobes) {
            /* We may be blaming an innocent here, but unlikely */
            if (kmod_loop_msg++ < 5)
                printk(KERN_ERR
                       "request_module: runaway loop modprobe %s\n",
                       module_name);
            atomic_dec(&kmod_concurrent);                           // 消除前面atomic_inc产生的引用
            return -ENOMEM;                                         // 返回错误[luther.gliethttp]
        }

        ret = call_usermodehelper(modprobe_path, argv, envp,        // 执行用户空间的应用程序/sbin/modprobe
                wait ? UMH_WAIT_PROC : UMH_WAIT_EXEC);
        atomic_dec(&kmod_concurrent);                               // 消除atomic_inc产生的引用
        return ret;
    }
    EXPORT_SYMBOL(__request_module);
    展开全文
  • Linuxrequest_firmware 的用法

    千次阅读 2014-07-22 16:00:04
    (三) 发表于 2012 年 3 月 30 日 获取固件的正确方法是当需要时从用户空间获取它。一定不要试图从内核空间直接打开包含固件的文件,那是一个易出错的操作...int request_firmware(const struct firmware **fw,
  • linuxrequest_region()函数的分析

    千次阅读 2013-06-05 11:14:33
    linuxrequest_region()函数的分析  struct resource ioport_resource = { .name = "PCI IO", .start = 0, .end = IO_SPACE_LIMIT, //IO_SPACE_LIMIT = 0xffffffff .flags = ...
  • Linux 安装 Docker

    万次阅读 2015-09-23 22:40:13
    Linux 安装 Docker
  • linuxrequest_mem_region的粗略理解

    千次阅读 2008-02-25 14:00:00
    linuxrequest_mem_region的粗略理解文章来源:http://gliethttp.cublog.cn Linux把基于I/O映射方式的I/O端口和基于内存映射方式的I/O端口资源统称为“I/O区域”(I/O Region)。I/O Region仍然是一种I/O资源,因此...
  • 安装内核模块时,如果里面有更改系统调用等情况,有时会崩溃,出现如下错误: BUG: unable to handle kernel paging request at virtual address c06357b4 printing eip:d0aac056 *pde = 0e9dd163 *pte = 00635161 ...
  • ![图片说明](https://img-ask.csdn.net/upload/201703/07/1488852796_601941.png) ![图片说明](https://img-ask.csdn.net/upload/201703/07/1488852810_692969.png) 系统是Linux centos 6.6
  • Linux 安装 nodejs

    千次阅读 2017-04-07 09:20:30
    打开nodejs官网 ... 选择二进制 右键复制链接 1.在Linux控制台输入 wget https://nodejs.org/dist/v6.10.2/node-v6.10.2-linux-x64.tar.xz [root@iZm5efk0kft7tkZ home]# wget https://nodejs
  • LiNUX安装PHP7.X

    千次阅读 2018-12-04 14:50:12
    LiNUX安装PHP7.X PHP版本:7.2.12 下载地址:http://cn2.php.net/get/php-7.2.12.tar.bz2/from/this/mirror 安装前准备,避免在安装PHP依赖包时报错:configure: error: mcrypt.h not found. Please reinstall ...
  • Linux 安装kafka

    千次阅读 2017-12-28 15:56:51
    下载地址:... 安装以及启动kafka 步骤1:安装kafka  $tar -xzf kafka_2.10-0.8.1.1.tgz $ cd kafka_2.10-0.8.1.1.tgz   步骤2:配置server.prop...
  • Linux安装PHP环境LNMP

    万次阅读 2018-09-27 15:37:20
    服务器版本是CentOS Linux release 7.4.1708,阿里云服务器,所以部署环境之前,需要先登录阿里云服务器管理后台开启端口:80、82、443、3306,其中82端口是我的项目配置站点的端口。 打开阿里云官网-》控制台-》云...
  • Linux 安装python爬虫框架 scrapy

    千次阅读 2015-08-21 15:57:19
    Linux 安装python爬虫框架 scrapy
  • Linux下解决python request SSLError

    千次阅读 2020-04-14 14:04:04
    2. 如果方法1无效,则可以先导入这个不认可得证书,然后指定request证书的路径,步骤如下: 1)获取证书 openssl s_client -connect google.com:443 -showcerts 2>&1 < /dev/null | sed -n ...
  • Linux安装虚拟PDF打印机

    千次阅读 2020-04-12 07:02:07
    原文地址:https://lujun9972.github.io/blog/2020/04/11/为linux安装虚拟pdf打印机/index.html 今天发现一个 CUPS-PDF 项目,可以为 CUPS(Common Unix Printing System) 添加 PDF 打印机. 步骤非常简单: 安装...
  • linux安装nginx配置https

    千次阅读 2019-02-18 17:17:56
    最近在linux中配置nginx,然后需要配置https访问域名。 安装nginx前,我们首先要确保系统安装了g++、gcc、openssl-devel、pcre-devel和zlib-devel软件。如果安装请忽略。 1、# yum install gcc-c++ nginx是C语言...
  • linux宏定义request_mem_region()

    千次阅读 2009-10-29 16:11:00
    基于I/O Region的操作函数__XXX_region(),Linux在头文件include/linux/ioport.h中定义了三个对I/O内存资源进行操作的宏: ①request_mem_region()宏,请求分配指定的I/O内存资源。 ②check_ mem_region()宏,检查...
  • linux安装jdk1.8(rpm方式)

    万次阅读 2016-08-01 14:32:56
    由于版权原因,Linux发行版并没有包含官方版的Oracle JDK,必须自己从官网上下载安装。Oracle官网用Cookie限制下载方式,使得眼下只能用浏览器进行下载,使用其他方式可能会导致下载失败。但还是有方法可以在Linux...
  • Linux中断关于 request_threaded_irq

    千次阅读 2012-06-18 09:08:13
    --------------------------------------------------------------------- ...回过头来,request一个IRQ的过程实际上就是构造irqaction项,free的过程就是移除不需要的irqaction项。
  • Linux安装IntelliJ IDEA Community Edition

    万次阅读 2016-06-28 18:45:49
    刚在 Windows7下安装了 IntelliJ IDEA Community Edition 2016.1.3(64),又在 WindowsXP下安装IntelliJ IDEA Ultimate Edition,又在Mac OS 下安装IntelliJ IDEA Community Edition,今天再在Linux安装一下看看...
  • linux驱动中request_mem_region()相关函数

    千次阅读 2012-02-23 18:02:16
    http://www.diybl.com/course/6_system/linux/Linuxjs/20090503/166312.html   Region的操作函数__XXX_region(),Linux在头文件include/linux/ioport.h... ①request_mem_region()宏,请求分配指定的I/O内存资源。
  • linux 安装docker 并使用docker 安装nginx

    千次阅读 2019-04-26 17:43:32
    之前也在linux安装过docker,并且也一直使用,但是一直没有记录下安装的过程,为了多年以后能再次发现自己的足迹,就抽个时间记录下这些过程。 什么是 Docker Docker 最初是 dotCloud 公司创始人 Solomon Hykes...
  • Consul4-linux安装consul以及集群搭建

    千次阅读 2018-07-28 11:28:01
    前面几篇关于consul的文章简单的介绍了windows下安装consul以及consul作为注册中心和配置中心的简单使用,基于前面的基础,这里介绍下载linux安装consul以及结合docker搭建consul集群,解决consul配置的数据无法...
  • linux驱动之中断函数request_irq()

    千次阅读 2014-04-11 20:18:38
    request_irq()、free_...在include/linux/sched.h里声明。  request_irq()调用的定义:  int request_irq(unsigned int irq,  void (*handler)(int irq, void *dev_id, struct pt_regs *regs  ), 
  • linux内核中request_region()函数详解

    千次阅读 2017-07-19 16:42:59
    void request_region(unsigned long from,  unsigned long num, const char *name) 这个函数用来申请一块输入输出区域。 如果这段I/O端口没有被占用,在我们的驱动程序中就可以使用它。在使用之前,...
  • 这个问题不是我自己碰到的是一个同学问我在linux系统中安装软件:/lib/ld-linux.so.2: bad ELF interpreter怎么解决,这里我分析有两种,一种是常用的安装因为系统软件位数问题,如:64位系统中安装了32位程序了,另...
  • Linux 6下安装编译安装Nginx

    千次阅读 2016-05-05 17:42:24
    在高连接并发的情况下,Nginx是Apache服务器不错的替代品:Nginx在美国是做虚拟主机生意的老板们经常选择的软件平台之一。能够支持高达50,000个并发连接数的响应...本文演示了基于Linux 6下编译安装Nginx,供大家参考。
  • request_irq() linux注册中断服务

    千次阅读 2013-12-22 14:40:37
    linux内核中用于申请中断的函数是request_irq(),函数原型在Kernel/irq/manage.c中定义: int request_irq(unsigned int irq, irq_handler_t handler,  unsigned long irqflags, const char *devn

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 237,298
精华内容 94,919
关键字:

linux安装request

linux 订阅