精华内容
下载资源
问答
  • 实现程序在驱动层面的保护;分享一份用于隐藏进程及其线程的rootkit驱动程序源代码.
  • 线程同步机制在应用程序与驱动程序通信中的应用
  • 一种多线程程序内存系统模拟器Trace驱动仿真方法
  • 注意:kernel_thread()的参数fn,以及kthread_create()/kthread_run()的参数threadfn即使是一样的函数,只要创建的线程不一样(线程名字不一样),那么fn,threadfn函数在不同的线程里面,运行的空间地址是不一样的。...

    参考博客文章来源:https://blog.csdn.net/ezimu/article/details/60467017

    第一种方法:kernel_thread

    #include <linux/sched.h>
    
    extern pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);

    (1)参数说明:

    fn线程函数地址
    arg线程函数的形参,没有,可以是NULL
    flags标志,一般用CLONE_KERNEL(定义在linux/sched.h中,注意有的版本中,CLONE_FS | CLONE_FILES | CLONE_SIGHAND),其他标志及含义见uapi/linux/sched.h中
    返回值pid_t返回线程ID值

    (2)使用例子:

    #include <linux/module.h>
    #include <linux/moduleparam.h>
    #include <linux/init.h>
    #include <linux/kmod.h>
    #include <linux/sched.h>
    #include <linux/delay.h>
    
    MODULE_AUTHOR("pyl");
    MODULE_LICENSE("GPL");
    
    #define CLONE_KERNEL    (CLONE_FS | CLONE_FILES | CLONE_SIGHAND)
    
    int my_kernel_thread(void *arg)
    {
            int n = 0;
    
            while(1)
            {
                    printk("%s: %d\n",__func__,n++);
                    ssleep(3);
            }
    
            return 0;
    }
    static int __init practice_call(void)
    {
            printk("%s:\n",__func__);
    
    //创建一个线程,并开始执行
            kernel_thread(my_kernel_thread,NULL,CLONE_KERNEL);    
    
            return 0;
    }
    
    static void __exit practice_call_exit(void)
    {
            printk("%s:\n",__func__);
    }
    
    module_init(practice_call);
    module_exit(practice_call_exit);

    第二种方法:kthread_create

    #include <linux/kthread.h>
    
    struct task_struct *kthread_create_on_node(
                       int (*threadfn)(void *data), 
                       void *data,int node,
                       const char namefmt[], ...);
    
    /**
     * kthread_create - create a kthread on the current node
     * @threadfn: the function to run in the thread
     * @data: data pointer for @threadfn()
     * @namefmt: printf-style format string for the thread name
     * @...: arguments for @namefmt.
     *
     * This macro will create a kthread on the current node, leaving it in
     * the stopped state.  This is just a helper for kthread_create_on_node();
     * see the documentation there for more details.
     */
    #define kthread_create(threadfn, data, namefmt, arg...) \
            kthread_create_on_node(threadfn,
                                   data,
                                   namefmt, ##arg)

    (1)参数说明:

    threadfn

    线程函数地址
    data线程函数形参,如果没有可以定义为NULL
    namefmt,arg…线程函数名字,可以格式化输出名字
    返回值(strcut task_struct *)线程指针

    注意:kthread_create()创建后,线程没有立即运行,需要将返回的值,即线程指针(struct task_struct *),作为参数传入到wake_up_process()唤起线程运行。

    (2)使用例子:

    #include <linux/module.h>
    #include <linux/moduleparam.h>
    #include <linux/init.h>
    #include <linux/kmod.h>
    #include <linux/sched.h>
    #include <linux/delay.h>
    #include <linux/kthread.h>
    
    MODULE_AUTHOR("pyl");
    MODULE_LICENSE("GPL");
    
    #define CLONE_KERNEL    (CLONE_FS | CLONE_FILES | CLONE_SIGHAND)
    
    //线程指针
    strcut task_struct *practice_task_p = NULL;
    
    int my_kernel_thread(void *arg)
    {
            int n = 0;
    
            while(1)
            {
                    printk("%s: %d\n",__func__,n++);
                    ssleep(3);
    
    //kthread_should_stop判断线程是否应该结束,返回true表示结束,false表示不结束
            if(kthread_should_stop())
                    {
                            break;
                    }
    
            }
    
            return 0;
    }
    static int __init practice_call(void)
    {
            printk("%s:\n",__func__);
            practice_task_p = kthread_create(my_kernel_thread,NULL,"practice task");    
            if(!IS_ERR(practice_task_p))
                    wake_up_process(practice_task_p);//唤醒practice_task_p指向的线程
            return 0;
    }
    
    static void __exit practice_call_exit(void)
    {
            printk("%s:\n",__func__);
            kthread_stop(practice_task_p);//停止线程,kthread_should_stop会做出响应
    }
    
    module_init(practice_call);
    module_exit(practice_call_exit);

    注意:在编写线程循环体时,一般都要加入kthread_should_stop(),如果不加,调用kthread_stop()是没有效果的,也会导致模块退出后,线程仍然还在运行。

    第三种方法:kthread_run

    #include <linux/kthread.h>
    /**
     * kthread_run - create and wake a thread.
     * @threadfn: the function to run until signal_pending(current).
     * @data: data ptr for @threadfn.
     * @namefmt: printf-style name for the thread.
     *
     * Description: Convenient wrapper for kthread_create() followed by
     * wake_up_process().  Returns the kthread or ERR_PTR(-ENOMEM).
     */
    #define kthread_run(threadfn, data, namefmt, ...)                          \
    ({                                                                         \
            struct task_struct *__k                                            \
                    = kthread_create(threadfn, data, namefmt, ## __VA_ARGS__); \
            if (!IS_ERR(__k))                                                  \
                    wake_up_process(__k);                                      \
            __k;                                                               \
    })
    

    (1)参数说明:

    threadfn

    线程函数地址
    data线程函数形参,没有可以制定为NULL
    namefmt, …线程名字,可以格式化输出
    返回值__k线程结构体指针(struct task_struct * )

    注意:kthread_run()创建的线程,是立刻运行的。

    (2)使用例子:

    #include <linux/module.h>
    #include <linux/moduleparam.h>
    #include <linux/init.h>
    #include <linux/kmod.h>
    #include <linux/sched.h>
    #include <linux/delay.h>
    #include <linux/kthread.h>
    
    MODULE_AUTHOR("zimu");
    MODULE_LICENSE("GPL");
    
    #define CLONE_KERNEL    (CLONE_FS | CLONE_FILES | CLONE_SIGHAND)
    
    int my_kernel_thread(void *arg)
    {
            int n = 0;
    
            while(1)
            {
                    printk("%s: %d\n",__func__,n++);
                    ssleep(3);
            if(kthread_should_stop())
                    {
                            break;
                    }
    
            }
    
            return 0;
    }
    static int __init practice_call(void)
    {
            printk("%s:\n",__func__);
    
            practice_task_p = kthread_run(my_kernel_thread,NULL,"practice task");    
    
            return 0;
    }
    
    static void __exit practice_call_exit(void)
    {
            printk("%s:\n",__func__);
            kthread_stop(practice_task_p);
    }
    
    module_init(practice_call);
    module_exit(practice_call_exit);

    注意:kernel_thread()的参数fn,以及kthread_create()/kthread_run()的参数threadfn即使是一样的函数,只要创建的线程不一样(线程名字不一样),那么fn,threadfn函数在不同的线程里面,运行的空间地址是不一样的。


                                                                    线程状态


      一、线程park状态

    (1)park与stop的区别:

    线程的stop(kthread_stop())状态指线程终止,线程的生命周期结束
    线程的park状态(kthread_park())指线程暂时停止(可以理解就是挂起),当执行换醒线程(kthread_unpark())后,线程从挂起状态唤醒,接着运行

    (2)park的挂起与唤醒函数

    挂起kthread_park
    唤醒kthread_unpark

    (3)使用例子

    #include <linux/module.h>
    #include <linux/moduleparam.h>
    #include <linux/init.h>
    #include <linux/kmod.h>
    #include <linux/sched.h>
    #include <linux/delay.h>
    #include <linux/kthread.h>
    
    MODULE_AUTHOR("zimu");
    MODULE_LICENSE("GPL");
    
    #define CLONE_KERNEL    (CLONE_FS | CLONE_FILES | CLONE_SIGHAND)
    
    int my_kernel_thread(void *arg)
    {
            int n = 0;
    
            while(1)
            {
                    printk("%s: %d\n",__func__,n++);
                    ssleep(3);
    
            if(kthread_should_park())
                kthread_parkme();
    
            if(kthread_should_stop())
                    {
                            break;
                    }
    
            }
    
            return 0;
    }
    static int __init practice_call(void)
    {
            printk("%s:\n",__func__);
            practice_task_p = kthread_run(my_kernel_thread,NULL,"practice task");    
    
            return 0;
    }
    
    static void __exit practice_call_exit(void)
    {
            printk("%s:\n",__func__);
            kthread_stop(practice_task_p);
    }
    
    module_init(practice_call);
    module_exit(practice_call_exit);

    (4)park状态判断

    if(kthread_should_park())
        kthread_park();

    kthread_should_park()函数判断了调用kthread_park()函数的该线程是否应该挂起,返回true就挂起,false就是不挂起

    二、线程的freez状态

    1、进程(线程)冻结技术(freezing of tasks)是指在系统hibernate或者suspend的时候,将用户进程和部分内核线程置于“可控”的暂停状态。
    2、当系统进入hibernate或者suspend的时候,线程如果要响应,那么线程需要使用相应接口将线程冻结。

    (1)接口函数

    #include <linux/freezer.h>
    
    static inline bool try_to_freeze(void);
    static inline bool freezing(struct task_struct *p);
    
    #include <linux/kthread.h>
    
    bool kthread_freezable_should_stop(bool *was_frozen);

    (2)使用方法:

    第一种:kthread_freezable_should_stop(bool *was_frozen)函数

    int my_kernel_thread(void *arg)
    {
            int n = 0;
            bool free;
    
            while(1)
            {
                    printk("%s: %d\n",__func__,n++);
                    ssleep(3);
    
    //会一直阻塞在这里,知道系统被唤醒
    //kthread_freezable_should_stop函数会判断这个线程唤醒后是否需要停止
            if(kthread_freezable_should_stop())
            {
                break;
            }
    
            }
    
            return 0;
    }
    kthread_freezable_should_stop如果系统进入hibernate或者suspend,将当前线程挂起,并置位PF_FROZEN标志,调用schedule()放弃CPU控制全,直到系统退出hibernate或者suspend,或者其他唤起,kthread_freezable_should_stop才会返回,否则将一直不返回。
    kthread_freezable_should_stop为了安全,返回的是线程是否需要退出真值(true,false),返回的was_frozen值,true表示线程是从冻结后唤醒退出的,false表示没有被冻结。

    第二种:

    int my_kernel_thread(void *arg)
    {
            int n = 0;
            bool free;
    
            while(1)
            {
                    printk("%s: %d\n",__func__,n++);
                    ssleep(3);
    
            if(freezing(current))
            {
                try_to_freeze();
            }
            if(kthread_should_stop())
                    {
                            break;
                    }
    
            }
    
            return 0;
    }
    
    freezing()判断系统是否进入冻结,ture冻结,false没有冻结
    try_to_freeze()将当前线程冻结,冻结后将不会返回,直到解冻,或者其他唤起,否则一直不返回

    总结:线程是否要响应系统的冻结状态,需要根据情况,看系统冻结后,驱动模块是否需要运行

    三、线程绑定

    #include <linux/kthread.h>
    
    void kthread_bind(struct task_struct *k, unsigned int cpu);
    功能将线程和CPU绑定,这个线程只在绑定的CPU上运行,在多核CPU上用
    k线程结构体指针
    cpu要绑定的CPU号

     

     

    最后总结:在驱动程序中创建一个线程,首先使用线程创建函数生产一个线程,然后使用线程执行函数后者结束函数控制线程开始于停止,也可以使用状态函数让线程处于挂起状态和运行状态,在线程的执行函数中使用状态函数获取线程的当前状态,用于确定具体要执行的任务。线程的执行函数中是一个无线循环体,在循环体里面加入线程的状态判断或获取函数,结合需要,在对应的条件下执行操作,比如停止线程操作就是一个跳出循环的break语句,改变或判断线程状态就是先使用线程的kthread_should_stop或kthread_should_park函数作为执行操作的条件,如果条件符合,就在这个条件的代码段使用线程的控制函数。

    展开全文
  • windows驱动中加 线程

    2013-11-19 10:35:29
    在windows提供的PASSTHRU程序中增加简单的线程,并同步。
  • 资源名称:键盘监听驱动程序编写视频教程(20集)资源目录:【】097ff94c7fc6fdc019cb97e151f578fe【】键盘监听驱动程序编写10、工作者线程的创建【】键盘监听驱动程序编写11、工作者线程对象指针的获取【】键盘监听...
  • 应用程序与驱动程序通讯演示,通过应用程序创建一个Event传到驱动程序中,在Event中用KeSetEvet()激发事件对象,应用程序中的线程WaifXXXXX函数即可收到此事件。用于驱动程序接收到中断信号后通知应用程序。
  • 21-Aug-2020 11:05:58.506 警告 [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesJdbc Web应用程序 [ROOT] 注册了JDBC驱动程序 [com.mysql.cj.jdbc.Driver],但在Web应用...

    报错信息

    21-Aug-2020 11:05:58.506 警告 [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesJdbc Web应用程序 [ROOT] 注册了JDBC驱动程序 [com.mysql.cj.jdbc.Driver],但在Web应用程序停止时无法注销它。 为防止内存泄漏,JDBC驱动程序已被强制取消注册。
    21-Aug-2020 11:05:58.507 警告 [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads Web应用程序[ROOT]似乎启动了一个名为[Timer-0]的线程,但未能停止它。这很可能会造成内存泄漏。线程的堆栈跟踪:[
     java.lang.Object.wait(Native Method)
     java.util.TimerThread.mainLoop(Timer.java:552)
     java.util.TimerThread.run(Timer.java:505)]
    21-Aug-2020 11:05:58.508 警告 [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads Web应用程序[ROOT]似乎启动了一个名为[com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#0]的线程,但未能停止它。这很可能会造成内存泄漏。线程的堆栈跟踪:[
     java.lang.Object.wait(Native Method)
     com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:534)]
    21-Aug-2020 11:05:58.508 警告 [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads Web应用程序[ROOT]似乎启动了一个名为[com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#1]的线程,但未能停止它。这很可能会造成内存泄漏。线程的堆栈跟踪:[
     java.lang.Object.wait(Native Method)
     com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:534)]
    21-Aug-2020 11:05:58.509 警告 [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads Web应用程序[ROOT]似乎启动了一个名为[com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#2]的线程,但未能停止它。这很可能会造成内存泄漏。线程的堆栈跟踪:[
     java.lang.Object.wait(Native Method)
     com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:534)]
    21-Aug-2020 11:05:58.509 警告 [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads Web应用程序[ROOT]似乎启动了一个名为[Abandoned connection cleanup thread]的线程,但未能停止它。这很可能会造成内存泄漏。线程的堆栈跟踪:[
     java.lang.Object.wait(Native Method)
     java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
     com.mysql.cj.jdbc.AbandonedConnectionCleanupThread.run(AbandonedConnectionCleanupThread.java:43)]
    21-Aug-2020 11:05:58.525 信息 [main] org.apache.coyote.AbstractProtocol.stop 正在停止ProtocolHandler ["http-nio-8080"]
    21-Aug-2020 11:05:58.528 信息 [main] org.apache.coyote.AbstractProtocol.destroy 正在摧毁协议处理器 ["http-nio-8080"]
    Disconnected from server
    

    解决方法

    一、tomcat服务器关闭后,jdbc驱动程序不会与web应用程序同步停止,需要手动注销程序。可以编写ContextFinalizer类

    package cn.itcast.tools;
    
    import com.mysql.cj.jdbc.AbandonedConnectionCleanupThread;
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    import javax.servlet.annotation.WebListener;
    import java.sql.Driver;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    import java.util.Enumeration;
    
    @WebListener
    public class ContextFinalizer implements ServletContextListener {
    
        public void contextInitialized(ServletContextEvent sce) {
        }
        public void contextDestroyed(ServletContextEvent sce) {
            Enumeration<Driver> drivers = DriverManager.getDrivers();
            Driver d = null;
            while (drivers.hasMoreElements()) {
            try {
                   d = drivers.nextElement();
                   DriverManager.deregisterDriver(d);
                   System.out.println(String.format("ContextFinalizer:Driver %s deregistered", d));
            } catch (SQLException ex) {
                   System.out.println(String.format("ContextFinalizer:Error deregistering driver %s", d) + ":" + ex);
            }
            }
            try {
                AbandonedConnectionCleanupThread.shutdown();
                } catch (InterruptedException e) {
                System.out.println("ContextFinalizer:SEVERE problem cleaning up: " + e.getMessage());
                e.printStackTrace();
                }
             }
    }
    

    在web.xml中配置监听器

      <listener>
        <listener-class>cn.itcast.tools.ContextFinalizer</listener-class>
      </listener>
    

    二、c3p0连接池线程的关闭
    在配置文件中加入销毁方法

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
    
    展开全文
  • linux驱动-线程

    千次阅读 2017-03-05 14:32:30
    linux驱动模块中可以用kernel_thread(),kthread_create()/kthread_run()两种方式创建内核线程,另外还可以用第三方库(如pthread,除此之外还有其他的第三方库),在驱动模块中创建线程(pthread也可以用在用户空间...

    简述

    linux驱动模块中可以用kernel_thread(),kthread_create()/kthread_run()两种方式创建内核线程,另外还可以用第三方库(如pthread,除此之外还有其他的第三方库),在驱动模块中创建线程(pthread也可以用在用户空间)


    一、kernel_thread
    kernel_thread()声明在include/linux/sched.h里面:

    extern pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);

    参数说明:
    fn:线程函数地址
    arg:线程函数的形参,没有,可以是NULL
    flags:标志,一般用CLONE_KERNEL(定义在linux/sched.h中,注意有的版本中,没用定义),其他标志及含义见uapi/linux/sched.h中。
    返回值:返回线程ID值。

    注意:kernel_thread()由于没有用EXPORT_SYMBOL导出来,所以用kernel_thread()这能用在和内核一起编译的驱动代码中,如用在ubuntu系统上,不随内核一起编译,单独的驱动程序时,可以编译过,但是用insmod加载驱动模块时,会报未知符号错误”Unknown symbol in module”,而不能加载。

    kernel_thread()用法例子:

    #include <linux/module.h>
    #include <linux/moduleparam.h>
    #include <linux/init.h>
    #include <linux/kmod.h>
    #include <linux/sched.h>
    #include <linux/delay.h>
    
    MODULE_AUTHOR("zimu");
    MODULE_LICENSE("GPL");
    
    #define CLONE_KERNEL    (CLONE_FS | CLONE_FILES | CLONE_SIGHAND)
    
    int my_kernel_thread(void *arg)
    {
            int n = 0;
    
            while(1)
            {
                    printk("%s: %d\n",__func__,n++);
                    ssleep(3);
            }
    
            return 0;
    }
    static int __init practiceCall(void)
    {
            printk("%s:\n",__func__);
            kernel_thread(my_kernel_thread,NULL,CLONE_KERNEL);    
    
            return 0;
    }
    
    static void __exit practiceCallExit(void)
    {
            printk("%s:\n",__func__);
    }
    
    module_init(practiceCall);
    module_exit(practiceCallExit);
    

    这个例子运行,会每隔3秒n加1,并打印出来。


    二、kthread_create():

    kthread_create()定义在include/linux/kthread.h里面,下如:

    __printf(4, 5)
    struct task_struct *kthread_create_on_node(
                       int (*threadfn)(void *data), 
                       void *data,int node,
                       const char namefmt[], ...);
    
    /**
     * kthread_create - create a kthread on the current node
     * @threadfn: the function to run in the thread
     * @data: data pointer for @threadfn()
     * @namefmt: printf-style format string for the thread name
     * @...: arguments for @namefmt.
     *
     * This macro will create a kthread on the current node, leaving it in
     * the stopped state.  This is just a helper for kthread_create_on_node();
     * see the documentation there for more details.
     */
    #define kthread_create(threadfn, data, namefmt, arg...) \
            kthread_create_on_node(threadfn,
                                   data,
                                   namefmt, ##arg)

    参数说明:
    threadfn:线程函数地址
    data:线程函数形参,如果没有可以定义为NULL
    namefmt,arg…:线程函数名字,可以格式化输出名字。

    返回值:返回线程指针(strcut task_struct *)

    注意:kthread_create()创建后,线程没有立即运行,需要将返回的值,即线程指针(struct task_struct *),作为参数传入到wake_up_process()唤起线程运行。

    用法例子:

    #include <linux/module.h>
    #include <linux/moduleparam.h>
    #include <linux/init.h>
    #include <linux/kmod.h>
    #include <linux/sched.h>
    #include <linux/delay.h>
    #include <linux/kthread.h>
    
    MODULE_AUTHOR("zimu");
    MODULE_LICENSE("GPL");
    
    #define CLONE_KERNEL    (CLONE_FS | CLONE_FILES | CLONE_SIGHAND)
    
    strcut task_struct *practice_task_p = NULL;
    
    int my_kernel_thread(void *arg)
    {
            int n = 0;
    
            while(1)
            {
                    printk("%s: %d\n",__func__,n++);
                    ssleep(3);
            if(kthread_should_stop())
                    {
                            break;
                    }
    
            }
    
            return 0;
    }
    static int __init practiceCall(void)
    {
            printk("%s:\n",__func__);
            practice_task_p = kthread_create(my_kernel_thread,NULL,"practice task");    
            if(!IS_ERR(practice_task_p))
                    wake_up_process(practice_task_p);
            return 0;
    }
    
    static void __exit practiceCallExit(void)
    {
            printk("%s:\n",__func__);
            kthread_stop(practice_task_p);
    }
    
    module_init(practiceCall);
    module_exit(practiceCallExit);

    这个例子运行,每隔3秒n加1,并输出,当退出模块时,调用了kthread_stop()函数,当my_kernel_kernel()运行到if(kthread_should_stop())时,条件为真,退出while(1){…}线程退出停止。

    注意:在编写线程循环体时,一般都要加入kthread_should_stop(),如果不加,调用kthread_stop()是没有效果的,也会导致模块退出后,线程仍然还在运行。


    三、kthread_run():

    kthread_run()声明在include/linux/kthread.h里面,如下:

    /**
     * kthread_run - create and wake a thread.
     * @threadfn: the function to run until signal_pending(current).
     * @data: data ptr for @threadfn.
     * @namefmt: printf-style name for the thread.
     *
     * Description: Convenient wrapper for kthread_create() followed by
     * wake_up_process().  Returns the kthread or ERR_PTR(-ENOMEM).
     */
    #define kthread_run(threadfn, data, namefmt, ...)                          \
    ({                                                                         \
            struct task_struct *__k                                            \
                    = kthread_create(threadfn, data, namefmt, ## __VA_ARGS__); \
            if (!IS_ERR(__k))                                                  \
                    wake_up_process(__k);                                      \
            __k;                                                               \
    })

    可以看出,kthread_run()是基于kthread_create()来实现的。

    参数说明:
    threadfn:线程函数地址
    data:线程函数形参,没有可以制定为NULL
    namefmt, …:线程名字,可以格式化输出

    返回值__k:线程结构体指针(struct task_struct * )

    注意:kthread_run()创建的线程,是立刻运行的。

    用法例子:

    #include <linux/module.h>
    #include <linux/moduleparam.h>
    #include <linux/init.h>
    #include <linux/kmod.h>
    #include <linux/sched.h>
    #include <linux/delay.h>
    #include <linux/kthread.h>
    
    MODULE_AUTHOR("zimu");
    MODULE_LICENSE("GPL");
    
    #define CLONE_KERNEL    (CLONE_FS | CLONE_FILES | CLONE_SIGHAND)
    
    int my_kernel_thread(void *arg)
    {
            int n = 0;
    
            while(1)
            {
                    printk("%s: %d\n",__func__,n++);
                    ssleep(3);
            if(kthread_should_stop())
                    {
                            break;
                    }
    
            }
    
            return 0;
    }
    static int __init practiceCall(void)
    {
            printk("%s:\n",__func__);
            practice_task_p = kthread_run(my_kernel_thread,NULL,"practice task");    
    
            return 0;
    }
    
    static void __exit practiceCallExit(void)
    {
            printk("%s:\n",__func__);
            kthread_stop(practice_task_p);
    }
    
    module_init(practiceCall);
    module_exit(practiceCallExit);

    例子运行后,也是每隔3秒n加1,并且打印出来。卸载模块时,kthread_stop()通知线程退出。

    注意:kernel_thread()的参数fn,以及kthread_create()/kthread_run()的参数threadfn即使是一样的函数,只要创建的线程不一样(线程名字不一样),那么fn,threadfn函数在不同的线程里面,运行的空间地址是不一样的。


    四、线程的park状态:

    park翻译成中文:停止,停车场等
    线程的stop(kthread_stop())状态,是指线程终止,线程的生命周期结束。
    线程的park状态(kthread_park()),是指线程暂时停止(可以理解就是挂起),当执行换线(kthread_unpark())后,线程从挂起状态唤醒,接着运行。

    用法例子:

    #include <linux/module.h>
    #include <linux/moduleparam.h>
    #include <linux/init.h>
    #include <linux/kmod.h>
    #include <linux/sched.h>
    #include <linux/delay.h>
    #include <linux/kthread.h>
    
    MODULE_AUTHOR("zimu");
    MODULE_LICENSE("GPL");
    
    #define CLONE_KERNEL    (CLONE_FS | CLONE_FILES | CLONE_SIGHAND)
    
    int my_kernel_thread(void *arg)
    {
            int n = 0;
    
            while(1)
            {
                    printk("%s: %d\n",__func__,n++);
                    ssleep(3);
    
            if(kthread_should_park())
                kthread_parkme();
    
            if(kthread_should_stop())
                    {
                            break;
                    }
    
            }
    
            return 0;
    }
    static int __init practiceCall(void)
    {
            printk("%s:\n",__func__);
            practice_task_p = kthread_run(my_kernel_thread,NULL,"practice task");    
    
            return 0;
    }
    
    static void __exit practiceCallExit(void)
    {
            printk("%s:\n",__func__);
            kthread_stop(practice_task_p);
    }
    
    module_init(practiceCall);
    module_exit(practiceCallExit);

    如上code加入了:

    if(kthread_should_park())
        kthread_parkme();

    当在其他某个地方,调用kthread_park(practice_task_p)后,线程将在kthread_parkme()处挂起睡眠,直到其他某个地方执行了kthread_unpark(practice_task_p)后,线程才被唤起,继续执行。


    五、线程的freeze状态:

    进程(线程)冻结技术(freezing of tasks)是指在系统hibernate或者suspend的时候,将用户进程和部分内核线程置于“可控”的暂停状态。
    当系统进入hibernate或者suspend的时候,线程如果要响应,那么线程需要使用相应接口将线程冻结。
    如下接口都声明在include/linux/freezer.h里面

    static inline bool try_to_freeze(void);
    static inline bool freezing(struct task_struct *p);

    声明在include/linux/kthread.h:

    bool kthread_freezable_should_stop(bool *was_frozen);

    两种用法:
    第一种:

    int my_kernel_thread(void *arg)
    {
            int n = 0;
            bool free;
    
            while(1)
            {
                    printk("%s: %d\n",__func__,n++);
                    ssleep(3);
    
            if(kthread_freezable_should_stop())
            {
                break;
            }
    
            }
    
            return 0;
    }

    kthread_freezable_should_stop如果系统进入hibernate或者suspend,将当前线程挂起,并置位PF_FROZEN标志,调用schedule()放弃CPU控制全,直到系统退出hibernate或者suspend,或者其他唤起,kthread_freezable_should_stop才会返回,否则将一直不返回。
    kthread_freezable_should_stop为了安全,返回的是线程是否需要退出真值(true,false),返回的was_frozen值,true表示线程是从冻结后唤醒退出的,false表示没有被冻结。

    第二种:

    int my_kernel_thread(void *arg)
    {
            int n = 0;
            bool free;
    
            while(1)
            {
                    printk("%s: %d\n",__func__,n++);
                    ssleep(3);
    
            if(freezing(current))
            {
                try_to_freeze();
            }
            if(kthread_should_stop())
                    {
                            break;
                    }
    
            }
    
            return 0;
    }

    freezing()判断系统是否进入冻结,ture冻结,false没有冻结。
    try_to_freeze()将当前线程冻结,冻结后将不会返回,直到解冻,或者其他唤起,否则一直不返回。

    线程是否要响应系统的冻结状态,需要根据情况,看系统冻结后,驱动模块是否需要运行。


    六、kthread_bind():

    kthread_bind()声明在include/linux/kthread.h,如下:

    void kthread_bind(struct task_struct *k, unsigned int cpu);

    功能:将线程和CPU绑定,这个线程只在绑定的CPU上运行,在多核CPU上用
    参数说明:
    k:线程结构体指针
    cpu:要绑定的CPU号


    七、第三方线程库pthread:

    见其它地方,待写完后,地址再放到这里。

    展开全文
  • 在一个线程中死循环等待驱动程序激活这个事件,一旦激活就调用一个函数 DWORD WINAPI DecodeWaitThreadProc(LPVOID lpParam) { while (1) { WaitForSingleObject(hDecodeEvent,INFINITE); //等待事件激活 ...
  • Android Binder驱动程序

    千次阅读 2015-06-17 17:19:22
    Binder驱动程序Binder驱动程序实现在内核中,它主要由binder.h和binder.c两个源文件组成。下面我们就开始介绍Binder驱动程序的基础知识,包括基础数据结构、初始化过程,以及设备文件/dev/binder的打开(open)、内存...

    Binder驱动程序

    Binder驱动程序实现在内核中,它主要由binder.h和binder.c两个源文件组成。下面我们就开始介绍Binder驱动程序的基础知识,包括基础数据结构、初始化过程,以及设备文件/dev/binder的打开(open)、内存映射(mmap)和内核缓冲区管理等操作。


    基础数据结构

    在Binder驱动程序中有两种类型的数据结构,其中一种是在内部使用的,另一种是在内部和外部均会使用到的。接下来,我们分别对这些数据结构进行介绍。

    首先看一下binder_work结构体的定义:

    struct binder_work {
        struct list_head entry;
        enum {
            BINDER_WORK_TRANSACTION = 1,
            BINDER_WORK_TRANSACTION_COMPLETE,
            BINDER_WORK_NODE,
            BINDER_WORK_DEAD_BINDER,
            BINDER_WORK_DEAD_BINDER_AND_CLEAR,
            BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
        } type;
    };

    结构体binder_work用来描述待处理的工作项,这些工作项有可能属于一个进程,也会有可能属于一个进程中的某一个线程。成员变量entry用了将该结构体嵌入到一个宿主结构中,成员变量type用来描述工作项的类型。根据成员变量type的取值,Binder驱动程序就可以判断出一个binder_work结构体嵌入到什么类型的宿主结构中。
    接下来,我们看一下binder_node结构体的定义:

    struct binder_node {
        int debug_id;
        struct binder_work work;
        union {
            struct rb_node rb_node;
            struct hlist_node dead_node;
        };
        struct binder_proc *proc;
        struct hlist_head refs;
        int internal_strong_refs;
        int local_weak_refs;
        int local_strong_refs;
        void __user *prt;
        void __user *cookie;
        unsigned has_strong_ref:1;
        unsigned pending_strong_ref:1;
        unsigned has_weak_ref:1;
        unsigned pending_weak_ref:1;
        unsigned has_async_transaction:1;
        unsigned accpet_fds:1;
        unsigned min_priority:8;
        struct list_head async_todo;
    };

    结构体binder_node用来描述一个Binder实体对象。每一个Service组件在Binder驱动程序中都对应一个Binder实体对象,用来描述它在内核中的状态。Binder驱动程序通过强引用计数和弱引用计数技术来维护它们的生命周期。
    成员变量proc指向一个Binder实体对象的宿主进程。在Binder驱动程序中,这些宿主进程通过一个binder_proc结构体来描述。宿主进程使用一个红黑树来维护它内部所有的Binder实体对象,而每一个Binder实体对象的成员变量rb_node就正好是这个红黑树中的一个节点。如果一个Binder实体对象的宿主进程已经死亡了,那么这个Binder实体对象就会通知它的成员变量dead_node保存在一个全局的hash列表中。

    展开全文
  •  驱动建立线程的是内核线程 跟普通进程一样都是可以调度的,然而udelay是靠死循环来实现的延迟,当你的内核线程没有占用cpu时,很可能超过1ms都不会执行你的程序,100us是小于进程可能的最小时
  • 内核模式驱动程序和用户模式应用程序通信项目。 由于存在加载到内核并与用户模式应用程序交换数据的驱动程序,因此在较低级别与操作系统本身进行交互非常有用。 可用的插件 流程浏览器:列出流程信息,直接从...
  • 驱动程序的同步处理

    千次阅读 2017-01-09 20:14:37
    驱动程序运行在系统的内核地址空间,而所有进程共享这2GB的虚拟地址空间,所以绝大多数驱动程序是运行在多线程环境中,有的时候需要对程序进行同步处理,使某些操作是严格串行化的,这就要用到同步的相关内容。...
  • 动态加载驱动程序源代码

    热门讨论 2011-06-14 19:45:49
    源代码包含三种不同的驱动加载方法,使用ZwSetSystemInformation函数加载驱动,使用NtLoadDriver函数加载驱动,使用服务控制管理器加载驱动,还包括三种线程注入技术,使用RtlCreateUserThread 函数注入线程,使用...
  • 用MFC实现多线程应用程序

    千次阅读 2012-11-06 11:05:44
    线程应用程序    当使分开的任务并发执行能够带来性能的提升时,你可以在你的应用程序中使用多线程。例如:考虑一个文字处理软件,它每5分钟备份一次当前的文档。用户经应用程序主窗口到文档的输入由主线程...
  • 驱动程序如何发通知给应用程序

    千次阅读 2008-06-12 14:09:00
    这里介绍一下常见的两种办法。 1、驱动程序调用API ...要注意的是不要在参数中传递指针(虚拟地址),因为执行驱动程序线程和应用程序并不在同一个进程空间中。解决办法可以利用内存映射文件技术,比如在驱动程序
  • 驱动开发之 用DeviceIoControl实现应用程序与驱动程序通信 1. readfile和writefile可以实现应用程序与驱动程序通信,另外一个Win32 API 是DeviceIoControl。 应用程序自定义一中IO控制码,然后调用DeviceIoControl...
  •  一个DriverEntry例程初始化一个驱动程序,所有的驱动程序必须有一个DriverEntry例程.当装载驱动程序的时候,PNP管理器为每个驱动程序调用一次DriverEntry.在驱动程序初始化之后,PNP管理器能够调用驱动程序的...
  • 大话USB驱动之总线驱动程序

    千次阅读 2014-05-06 16:54:45
    总线驱动是不用改的,内核都帮我们做好了,为了了解整个USB驱动的体系,我们来分析一下总线驱动程序
  • 驱动程序与应用程序之间共享内存

    千次阅读 2015-11-10 14:12:47
    如应层程序和驱动程序之间共享事件来完成同步,事件可以有应用程序来创建然后将其句柄下发到驱动程序中,驱动程序进行引用等操作,就可以实现共享事件了。这里就不说这个了,主要说说驱动和应用程序之间的
  • 部分摘自 ... ... 事件驱动编程是一种编程范式,这里程序的执行流由外部事件来决定。它的特点是包含一个事件循环,当外部事件发生时使用回调机制来触发相应的处理。另外两种常见的编程范式是
  • 在上一篇文章中提到了 Windows Vista 及之后版本的 Windows 操作系统在驱动程序加载完成后,驱动中调用的一些系统回调函数(如 ObRegisterCallbacks,可用来监控系统中对进线程句柄的操作,如打开进程、复制线程句柄...
  • Qt学习 之 多线程程序设计

    千次阅读 2016-01-01 10:40:48
    这使得开发轻巧的多线程Qt程序更为容易,并能充分利用多处理器机器的优势。多线程编程也是一个有用的模式,它用于解决执行较长时间的操作而不至于用户界面失去响应。在Qt的早期版本中,在构建库时有不选择线程支持的...
  • Qt 多线程程序设计

    千次阅读 2011-08-16 16:11:44
    看到一篇好文章,特地转载下来,很...原文地址: http://blog.21ic.com/user1/1425/archives/2009/64057.htmlQT 多线程程序设计QT通过三种形式提供了对线程的支持。它们分别是,一、平台无关的线程类,二、线程安全
  • Windows驱动开发之线程与同步事件

    千次阅读 2016-07-07 09:12:45
    Windows驱动开发 1) 使用系统线程 2) 线程中睡眠 3) 使用同步事件
  • 常见驱动程序相关知识

    万次阅读 2011-05-26 11:17:00
    其实那只是一种假相:高版本的Windows光盘中包含了老型号显卡、声卡等硬件的驱动程序,所以在安装Windows的同时,也安装了驱动。不过,我们还是需要学习驱动的知识,因为硬件的更新总是领先于Windows版本的更新的!...
  • 项目中遇到500多个线程并发执行,并将线程执行所生成的数据插入MySql数据库,按设想,500个线程,数据库中应有序号连续的500条记录。然而,郁闷的是数据库中的记录在第450条左右就开始不连续,部分记录缺失。500多个...
  • Windows驱动开发(10) - 驱动程序的同步处理(一)1、基本概念1.1 可重入与不可重入可重入,是指函数的执行结果不和执行顺序有关。反之,如果执行结果和执行顺序有关,则称这个函数是“不可重入”的。1.2 同步与异步1) ...
  • 线程的主要是需要处理大量的IO操作或者处理的情况需要花大量的时间等等,比如读写文件,网络数据接收,视频图像的采集,处理显示保存等操作缓慢的情形和需大幅度的提高性能的程序中使用。 但也不是都使用多线程,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 216,006
精华内容 86,402
关键字:

线程驱动程序