加入收藏 | 设为首页 | 会员中心 | 我要投稿 PHP编程网 - 黄冈站长网 (http://www.0713zz.com/)- 数据应用、建站、人体识别、智能机器人、语音技术!
当前位置: 首页 > 教程 > 正文

Linux内核线程的创建及在QEMU上的测试技巧

发布时间:2021-11-24 17:44:40 所属栏目:教程 来源:互联网
导读:本文主要介绍一个linux内核线程的实例,以及在QEMU平台上测试的过程。 一、内核线程的创建 编写一个字符设备驱动,在驱动注册时,开启一个内核线程。在用户向设备写入数据时,字符设备的wirte方法能够激活此内核线程,并在线程中实现打印用户输入的数据。 驱

本文主要介绍一个linux内核线程的实例,以及在QEMU平台上测试的过程。
一、内核线程的创建
    编写一个字符设备驱动,在驱动注册时,开启一个内核线程。在用户向设备写入数据时,字符设备的wirte方法能够激活此内核线程,并在线程中实现打印用户输入的数据。
 
 
 
    驱动代码如下(在2.6.22内核上测试通过),关键部分加上了注释:
 
 
#include <linux/module.h>  
#include <linux/moduleparam.h>  
#include <linux/kernel.h> /* printk(), min() */  
#include <linux/slab.h>       /* kmalloc() */  
#include <linux/fs.h>     /* everything... */  
#include <linux/errno.h>  /* error codes */  
#include <linux/types.h>  /* size_t */  
#include <linux/fcntl.h>  
#include <linux/cdev.h>  
#include <asm/uaccess.h>  
#include <linux/device.h>  
#include <linux/kthread.h>  
#include <linux/spinlock.h>   
static int kthread_major = 0;  
module_param(kthread_major, int, 0);  
MODULE_AUTHOR("farsight");  
MODULE_LICENSE("Dual BSD/GPL");  
struct kthread_dev {  
        struct task_struct *thread;  
        struct cdev cdev;    
        char* name;  
         int data_size;  
        char data[100];  
        spinlock_t queue_lock;  
  
};  
int kthread_open(struct inode *inode,struct file *filp)  
{  
    return 0;  
}  
ssize_t kthread_read(struct file *file, char __user *buff, size_t count, loff_t *offp)   
{   
    return 0;   
}  
ssize_t kthread_write(struct file *file, const char __user *buff, size_t count, loff_t *offp)  
{  
    int ret;  
    ret=sizeof(kthread_dev_obj->data);  
    if(count>(ret-1))  
        count=ret-1;  
    if(copy_from_user(kthread_dev_obj->data,buff,count)<0)//获取用户数据   
    {  
        goto out1;  
    }  
    spin_lock(&kthread_dev_obj->queue_lock);  
    kthread_dev_obj->data_size=count;  
    spin_unlock(&kthread_dev_obj->queue_lock);  
    wake_up_process(kthread_dev_obj->thread);//唤醒内核线程   
    return count;  
out1:  
    return 0;  
}  
  
static int kthread_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)  
{  
    return 0;  
}  
  
static int kthread_release(struct inode *node, struct file *file)  
{  
    return 0;  
}  
  
/*
 * Set up the cdev structure for a device.
 */  
static void kthread_setup_cdev(struct cdev *dev, int minor,  
        struct file_operations *fops)  
{  
    int err, devno = MKDEV(kthread_major, minor);  
  
    cdev_init(dev, fops);  
    dev->owner = THIS_MODULE;  
    err = cdev_add (dev, devno, 1);  
    /* Fail gracefully if need be */  
    if (err)  
        printk (KERN_NOTICE "Error %d adding kthread%d", err, minor);  
}  
  
static struct file_operations kthread_remap_ops = {  
    .owner   = THIS_MODULE,  
    .open    = kthread_open,  
    .release = kthread_release,  
    .read    = kthread_read,  
    .write   = kthread_write,  
    .ioctl   = kthread_ioctl,     
};  
  
static int kthread_fun(void * arg) //内核线程运行函数   
{  
     while (!kthread_should_stop()) {  
        spin_lock(&kthread_dev_obj->queue_lock);  
        if(kthread_dev_obj->data_size){  
            spin_unlock(&kthread_dev_obj->queue_lock);  
            kthread_dev_obj->data[kthread_dev_obj->data_size]='/0';  
            printk(kthread_dev_obj->data);//打印出用户空间数据   
            printk("in kthread/n");  
            kthread_dev_obj->data_size=0;  
        }  
        else{  
            set_current_state(TASK_INTERRUPTIBLE);  
            spin_unlock(&kthread_dev_obj->queue_lock);  
            schedule();  
        }  
    }  
    return 0;  
}  
  
static int kthread_init(void)  
{  
    int result;  
    dev_t dev = MKDEV(kthread_major, 0);  
  
    /* Figure out our device number. */  
    if (kthread_major)  
        result = register_chrdev_region(dev, 1, "kthread");  
    else {  
        result = alloc_chrdev_region(&dev, 0, 1, "kthread");  
        kthread_major = MAJOR(dev);  
    }  
    if (result < 0) {  
        printk(KERN_WARNING "kthread: unable to get major %d/n", kthread_major);  
        return result;  
    }  
    if (kthread_major == 0)  
        kthread_major = result;  
  
    kthread_dev_obj= kmalloc(sizeof(struct kthread_dev), GFP_KERNEL);  
    kthread_setup_cdev(&kthread_dev_obj->cdev, 0,&kthread_remap_ops);  
    printk("kthread device installed, with major %d/n", kthread_major);  
    my_class= class_create(THIS_MODULE, "kthread");  
//  device_create(my_class, NULL, MKDEV(kthread_major, 0),NULL, "kthread");   
    device_create(my_class, NULL, MKDEV(kthread_major, 0), "kthread");//for   
//  2.6.22   
    kthread_dev_obj->name="kthreadtest";//内核线程的名称   
    spin_lock_init(&kthread_dev_obj->queue_lock);  
    kthread_dev_obj->thread=kthread_run(kthread_fun,kthread_dev_obj,"%sd",kthread_dev_obj->name);//创建并运行内核线程   
    return 0;  
}  
static void kthread_cleanup(void)  
{  
    kthread_stop(kthread_dev_obj->thread);//停止内核线程   
    cdev_del(&kthread_dev_obj->cdev);  
    unregister_chrdev_region(MKDEV(kthread_major, 0), 1);  
    device_destroy(my_class,MKDEV(kthread_major,0));  
    class_destroy(my_class);  
    kfree(kthread_dev_obj);  
    printk("kthread device uninstalled/n");  
}  
module_init(kthread_init);  
module_exit(kthread_cleanup);   
二、在QEMU平台上的测试方法
    QEMU可以模拟很多硬件平台,使用QEMU适用于你手边没用硬件平台,或没用很好的内核调试工具的情况。
 
    这里主要介绍使用QEMU模拟ARM开发环境,并运行linux系统的过程。
 
1、系统环境
操作系统平台:Ubuntu 10.10
 
交叉工具:arm-softfloat-linux-gnu
 
测试内核:Linux2.6.22
 
测试平台:RealView-EB  (QEMU 模拟)
 
 
 
2、安装QEMU的方法
    使用新立得获取安装包

(编辑:PHP编程网 - 黄冈站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读