基于内核线程的创建、使用和退出以及延时宏的补充说明介绍

相关函数:

kthread_create():创建内核线程


复制代码 代码如下:

struct task_struct *kthread_create(int (*threadfn)(void *data), void *data, const char namefmt[], ...);  kernel thread可以用kernel_thread创建,但是在执行函数里面必须用daemonize释放资源并挂到init下,还需要用completion等待这一过程的完成。为了简化操作,定义了kthread_create。

线程创建后,不会马上运行,而是需要将kthread_create() 返回的task_struct指针传给wake_up_process(),然后通过此函数运行线程。

kthread_run():创建并启动线程的函数。


复制代码 代码如下:

struct task_struct *kthread_run(int (*threadfn)(void *data),void *data,const char *namefmt, ...);它实际上是个宏,由kthread_create()和wake_up_process()组成。

它实际上是个宏,由kthread_create()和wake_up_process()组成。


复制代码 代码如下:

#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_stop():通过发送信号给线程,使之退出。


复制代码 代码如下:

int kthread_stop(struct task_struct *thread);

线程一旦启动起来后,会一直运行,除非该线程主动调用do_exit函数,或者其他的进程调用kthread_stop函数,结束线程的运行。
但如果线程函数正在处理一个非常重要的任务,它不会被中断的。当然如果线程函数永远不返回并且不检查信号,它将永远都不会停止。

同时,在调用kthread_stop函数时,线程函数不能已经运行结束。否则,kthread_stop函数会一直进行等待。

内核线程的一般框架

int threadfunc(void *data){

while(1){

set_current_state(TASK_UNINTERRUPTIBLE);

if(kthread_should_stop()) break;

if(){//条件为真

//进行业务处理

}

else{//条件为假

//让出CPU运行其他线程,并在指定的时间内重新被调度

schedule_timeout(HZ);

}

}

return 0;

}

线程相关测试命令

  可以使用top命令来查看线程(包括内核线程)的CPU利用率。命令如下:

    top –p 线程号

  可以使用下面命令来查找线程号:

    ps aux|grep 线程名

示例程序:使用模块加载内核线程,实现每1s在内核中打印字符。

(makefile略去,和以前一篇博文一样的写法。)


复制代码 代码如下:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>   //wake_up_process()
#include <linux/kthread.h> //kthread_create(),kthread_run()
#include <linux/err.h> //IS_ERR(),PTR_ERR()
#ifndef SLEEP_MILLI_SEC
#define SLEEP_MILLI_SEC(nMilliSec)\
do { \
long timeout = (nMilliSec) * HZ / 1000; \
while(timeout > 0) \
{ \
timeout = schedule_timeout(timeout); \
} \
}while(0);
#endif

static struct task_struct *my_task = NULL;

static int my_kthread(void *data) 

    char *mydata = kmalloc(strlen(data)+1,GFP_KERNEL);
    memset(mydata,'\0',strlen(data)+1);
    strncpy(mydata,data,strlen(data));
    while(!kthread_should_stop())
    {
        SLEEP_MILLI_SEC(1000);
        printk("%s\n",mydata);
    }
    kfree(mydata);
    return 0;
}

static int __init kernel_thread_init(void)
{
    int err;
    printk(KERN_ALERT "Kernel thread initalizing...\n");
    my_task = kthread_create(my_kthread,"hello world","mythread");
    if(IS_ERR(my_task)){
        printk("Unable to start kernel thread./n");
        err = PTR_ERR(my_task);
        my_task = NULL;
        return err;
    }
    wake_up_process(my_task);
    return 0;#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>   //wake_up_process()
#include <linux/kthread.h> //kthread_create(),kthread_run()
#include <linux/err.h> //IS_ERR(),PTR_ERR()
#ifndef SLEEP_MILLI_SEC
#define SLEEP_MILLI_SEC(nMilliSec)\
do { \
long timeout = (nMilliSec) * HZ / 1000; \
while(timeout > 0) \
{ \
timeout = schedule_timeout(timeout); \
} \
}while(0);
#endif

static struct task_struct *my_task = NULL;

static int my_kthread(void *data) 

    char *mydata = kmalloc(strlen(data)+1,GFP_KERNEL);
    memset(mydata,'\0',strlen(data)+1);
    strncpy(mydata,data,strlen(data));
    while(!kthread_should_stop())
    {
        SLEEP_MILLI_SEC(1000);
        printk("%s\n",mydata);
    }
    kfree(mydata);
    return 0;
}

static int __init kernel_thread_init(void)
{
    int err;
    printk(KERN_ALERT "Kernel thread initalizing...\n");
    my_task = kthread_create(my_kthread,"hello world","mythread");
    if(IS_ERR(my_task)){
        printk("Unable to start kernel thread./n");
        err = PTR_ERR(my_task);
        my_task = NULL;
        return err;
}

static void __exit kernel_thread_exit(void)
{
    if(my_task){
        printk(KERN_ALERT "Cancel this kernel thread.\n");
        kthread_stop(my_task);
        printk(KERN_ALERT "Canceled.\n");
        }
}

module_init(kernel_thread_init);
module_exit(kernel_thread_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("anonymous");

补充说明:

  这个延时宏在一些情况下会造成内核线程CPU占用率过高的情况。根据对schedule_timeout()源码的分析,它只是周期使线程成为TASK_RUNNING状态,这个线程并没有真正的睡眠。解决办法:在while循环中的起始处加入set_current_state(TASK_INTERRUPTIBLE)即可。

时间: 2013-05-03

基于java 线程的几种状态(详解)

线程可以有六种状态: 1.New(新创建) 2.Runnable(可运行)(运行) 3.Blocked(被阻塞) 4.Waiting(等待) 5.Timed waiting(计时等待) 6.Terminated(被终止) 新创建线程: 当用new操作符创建一个新线程时,如new Thread(r),该线程还没有开始运行,它的当前状态为new,在线程运行之前还有一些基础工作要做. 可运行线程: 一旦线程调用start方法,线程处于runnable状态.在这个状态下的线程可能正在运行也可能没有运行(

简要讲解Python编程中线程的创建与锁的使用

创建线程 创建线程的两种方法: 1,直接调用threading.Thread来构造thread对象,Thread的参数如下: class threading.Thread(group=None, target=None, name=None, args=(), kwargs={})  group为None: target为线程将要执行的功能函数: name为线程的名字,也可以在对象构造后调用setName()来设定: args为tuple类型的参数,可以为多个,如果只有一个也的使用tuple的形

C++11/14 线程的创建与分离的实现

线程的创建 让我们看看示例代码(t1.cpp). #include <iostream> #include <thread> void thread_function() { std::cout << "thread function\n"; } int main() { std::thread t(&thread_function); // 线程 t 开始运行 std::cout << "main thread\n&q

node.js基于dgram数据报模块创建UDP服务器和客户端操作示例

本文实例讲述了node.js基于dgram数据报模块创建UDP服务器和客户端操作.分享给大家供大家参考,具体如下: node.js中 dgram 模块提供了udp数据包的socket实现,可以方便的创建udp服务器和客户端. 一.创建UDP服务器和客户端 服务端: const dgram = require('dgram'); //创建upd套接字 //参数一表示套接字类型,'udp4' 或 'udp6' //参数二表示事件监听函数,'message' 事件监听器 let server = dg

基于JavaScript实现动态创建表格和增加表格行数

在工作,项目需求中,有时候表格的行数不能够满足我们的需求,这时需要我们动态的增加表格的行数,下面小编通过一段代码实例给大家介绍js创建表格和增加表格的行数的方法,并且还实现了隔行变色功能.对此感兴趣的朋友可以参考一下代码: js代码如下所示: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>动态操作表格</title> </head>

python开发之基于thread线程搜索本地文件的方法

本文实例讲述了python开发之基于thread线程搜索本地文件的方法.分享给大家供大家参考,具体如下: 先来看看运行效果图: 利用多个线程处理搜索的问题,我们可以发现他很快.... 下面是代码部分: # A parallelized "find(1)" using the thread module. # This demonstrates the use of a work queue and worker threads. # It really does do more sta

python基于multiprocessing的多进程创建方法

本文实例讲述了python基于multiprocessing的多进程创建方法.分享给大家供大家参考.具体如下: import multiprocessing import time def clock(interval): while True: print ("the time is %s"% time.time()) time.sleep(interval) if __name__=="__main__": p = multiprocessing.Process

Android App在线程中创建handler的方法讲解

相关概念 1.Handler:可以看做是一个工具类,用来向消息队列中插入消息的; 2.Thread:所有与Handler相关的功能都是与Thread密不可分的,Handler会与创建时所在的线程绑定; 3.Message:消息; 4.MessageQueue:消息队列,对消息进行管理,实现了一个Message链表; 5.Looper:消息循环,从MessageQueue中取出Message进行处理: 6.HandlerThread:继承Thread,实例化时自动创建Looper对象,实现一个消息

浅析Java中线程的创建和启动

前言 线程是一个程序内部的顺序控制流.cpu实际上在一个时间点上,只执行一个.只不过我们把cup分成了多个时间片,由于速度很快,我们看起来像是多个线程.就像你的时间分成几片,这样整体看来做事情有规律,效率就会高,何况是cup呢. 线程的创建和启动: (1)定义Thread类的子类,并重写了该类的run()方法,该run()方法的方法就代表了线程需要完成的任务.因此把run()方法称为线程执行体 (2)创建Thread子类的实例,即创建了线程对象 (3)调用线程对象的start()方法来启动该线程