Linux内核线程的创建及在QEMU上的测试方法


本文主要介绍一个linux内核线程的实例,以及在QEMU平台上测试的过程。

一、内核线程的创建

    编写一个字符设备驱动,在驱动注册时,开启一个内核线程。在用户向设备写入数据时,字符设备的wirte方法能够激活此内核线程,并在线程中实现打印用户输入的数据。

 

    驱动代码如下(在2.6.22内核上测试通过),关键部分加上了注释:

 
  1. #include <linux/module.h>  
  2. #include <linux/moduleparam.h>  
  3. #include <linux/kernel.h> /* printk(), min() */  
  4. #include <linux/slab.h>       /* kmalloc() */  
  5. #include <linux/fs.h>     /* everything... */  
  6. #include <linux/errno.h>  /* error codes */  
  7. #include <linux/types.h>  /* size_t */  
  8. #include <linux/fcntl.h>  
  9. #include <linux/cdev.h>  
  10. #include <asm/uaccess.h>  
  11. #include <linux/device.h>  
  12. #include <linux/kthread.h>  
  13. #include <linux/spinlock.h>   
  14. static int kthread_major = 0;  
  15. module_param(kthread_major, int, 0);  
  16. MODULE_AUTHOR("farsight");  
  17. MODULE_LICENSE("Dual BSD/GPL");  
  18. struct kthread_dev {  
  19.         struct task_struct *thread;  
  20.         struct cdev cdev;    
  21.         char* name;  
  22.          int data_size;  
  23.         char data[100];  
  24.         spinlock_t queue_lock;  
  25.   
  26. };  
  27. int kthread_open(struct inode *inode,struct file *filp)  
  28. {  
  29.     return 0;  
  30. }  
  31. ssize_t kthread_read(struct file *file, char __user *buff, size_t count, loff_t *offp)   
  32. {   
  33.     return 0;   
  34. }  
  35. ssize_t kthread_write(struct file *file, const char __user *buff, size_t count, loff_t *offp)  
  36. {  
  37.     int ret;  
  38.     ret=sizeof(kthread_dev_obj->data);  
  39.     if(count>(ret-1))  
  40.         count=ret-1;  
  41.     if(copy_from_user(kthread_dev_obj->data,buff,count)<0)//获取用户数据   
  42.     {  
  43.         goto out1;  
  44.     }  
  45.     spin_lock(&kthread_dev_obj->queue_lock);  
  46.     kthread_dev_obj->data_size=count;  
  47.     spin_unlock(&kthread_dev_obj->queue_lock);  
  48.     wake_up_process(kthread_dev_obj->thread);//唤醒内核线程   
  49.     return count;  
  50. out1:  
  51.     return 0;  
  52. }  
  53.   
  54. static int kthread_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)  
  55. {  
  56.     return 0;  
  57. }  
  58.   
  59. static int kthread_release(struct inode *node, struct file *file)  
  60. {  
  61.     return 0;  
  62. }  
  63.   
  64. /* 
  65.  * Set up the cdev structure for a device. 
  66.  */  
  67. static void kthread_setup_cdev(struct cdev *dev, int minor,  
  68.         struct file_operations *fops)  
  69. {  
  70.     int err, devno = MKDEV(kthread_major, minor);  
  71.   
  72.     cdev_init(dev, fops);  
  73.     dev->owner = THIS_MODULE;  
  74.     err = cdev_add (dev, devno, 1);  
  75.     /* Fail gracefully if need be */  
  76.     if (err)  
  77.         printk (KERN_NOTICE "Error %d adding kthread%d", err, minor);  
  78. }  
  79.   
  80. static struct file_operations kthread_remap_ops = {  
  81.     .owner   = THIS_MODULE,  
  82.     .open    = kthread_open,  
  83.     .release = kthread_release,  
  84.     .read    = kthread_read,  
  85.     .write   = kthread_write,  
  86.     .ioctl   = kthread_ioctl,     
  87. };  
  88.   
  89. static int kthread_fun(void * arg) //内核线程运行函数   
  90. {  
  91.      while (!kthread_should_stop()) {  
  92.         spin_lock(&kthread_dev_obj->queue_lock);  
  93.         if(kthread_dev_obj->data_size){  
  94.             spin_unlock(&kthread_dev_obj->queue_lock);  
  95.             kthread_dev_obj->data[kthread_dev_obj->data_size]='/0';  
  96.             printk(kthread_dev_obj->data);//打印出用户空间数据   
  97.             printk("in kthread/n");  
  98.             kthread_dev_obj->data_size=0;  
  99.         }  
  100.         else{  
  101.             set_current_state(TASK_INTERRUPTIBLE);  
  102.             spin_unlock(&kthread_dev_obj->queue_lock);  
  103.             schedule();  
  104.         }  
  105.     }  
  106.     return 0;  
  107. }  
  108.   
  109. static int kthread_init(void)  
  110. {  
  111.     int result;  
  112.     dev_t dev = MKDEV(kthread_major, 0);  
  113.   
  114.     /* Figure out our device number. */  
  115.     if (kthread_major)  
  116.         result = register_chrdev_region(dev, 1, "kthread");  
  117.     else {  
  118.         result = alloc_chrdev_region(&dev, 0, 1, "kthread");  
  119.         kthread_major = MAJOR(dev);  
  120.     }  
  121.     if (result < 0) {  
  122.         printk(KERN_WARNING "kthread: unable to get major %d/n", kthread_major);  
  123.         return result;  
  124.     }  
  125.     if (kthread_major == 0)  
  126.         kthread_major = result;  
  127.   
  128.     kthread_dev_obj= kmalloc(sizeof(struct kthread_dev), GFP_KERNEL);  
  129.     kthread_setup_cdev(&kthread_dev_obj->cdev, 0,&kthread_remap_ops);  
  130.     printk("kthread device installed, with major %d/n", kthread_major);  
  131.     my_class= class_create(THIS_MODULE, "kthread");  
  132. //  device_create(my_class, NULL, MKDEV(kthread_major, 0),NULL, "kthread");   
  133.     device_create(my_class, NULL, MKDEV(kthread_major, 0), "kthread");//for   
  134. //  2.6.22   
  135.     kthread_dev_obj->name="kthreadtest";//内核线程的名称   
  136.     spin_lock_init(&kthread_dev_obj->queue_lock);  
  137.     kthread_dev_obj->thread=kthread_run(kthread_fun,kthread_dev_obj,"%sd",kthread_dev_obj->name);//创建并运行内核线程   
  138.     return 0;  
  139. }  
  140. static void kthread_cleanup(void)  
  141. {  
  142.     kthread_stop(kthread_dev_obj->thread);//停止内核线程   
  143.     cdev_del(&kthread_dev_obj->cdev);  
  144.     unregister_chrdev_region(MKDEV(kthread_major, 0), 1);  
  145.     device_destroy(my_class,MKDEV(kthread_major,0));  
  146.     class_destroy(my_class);  
  147.     kfree(kthread_dev_obj);  
  148.     printk("kthread device uninstalled/n");  
  149. }  
  150. module_init(kthread_init);  
  151. 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的方法

    使用新立得获取安装包

  • 1
  • 2
  • 下一页

相关内容