歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux綜合 >> Linux內核 >> Linux內核線程的創建及在QEMU上的測試方法

Linux內核線程的創建及在QEMU上的測試方法

日期:2017/3/1 10:41:21   编辑:Linux內核
本文主要介紹一個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. int kthread_open(struct inode *inode,struct file *filp)
  27. {
  28. return 0;
  29. }
  30. ssize_t kthread_read(struct file *file, char __user *buff, size_t count, loff_t *offp)
  31. {
  32. return 0;
  33. }
  34. ssize_t kthread_write(struct file *file, const char __user *buff, size_t count, loff_t *offp)
  35. {
  36. int ret;
  37. ret=sizeof(kthread_dev_obj->data);
  38. if(count>(ret-1))
  39. count=ret-1;
  40. if(copy_from_user(kthread_dev_obj->data,buff,count)<0)//獲取用戶數據
  41. {
  42. goto out1;
  43. }
  44. spin_lock(&kthread_dev_obj->queue_lock);
  45. kthread_dev_obj->data_size=count;
  46. spin_unlock(&kthread_dev_obj->queue_lock);
  47. wake_up_process(kthread_dev_obj->thread);//喚醒內核線程
  48. return count;
  49. out1:
  50. return 0;
  51. }
  52. static int kthread_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
  53. {
  54. return 0;
  55. }
  56. static int kthread_release(struct inode *node, struct file *file)
  57. {
  58. return 0;
  59. }
  60. /*
  61. * Set up the cdev structure for a device.
  62. */
  63. static void kthread_setup_cdev(struct cdev *dev, int minor,
  64. struct file_operations *fops)
  65. {
  66. int err, devno = MKDEV(kthread_major, minor);
  67. cdev_init(dev, fops);
  68. dev->owner = THIS_MODULE;
  69. err = cdev_add (dev, devno, 1);
  70. /* Fail gracefully if need be */
  71. if (err)
  72. printk (KERN_NOTICE "Error %d adding kthread%d", err, minor);
  73. }
  74. static struct file_operations kthread_remap_ops = {
  75. .owner = THIS_MODULE,
  76. .open = kthread_open,
  77. .release = kthread_release,
  78. .read = kthread_read,
  79. .write = kthread_write,
  80. .ioctl = kthread_ioctl,
  81. };
  82. static int kthread_fun(void * arg) //內核線程運行函數
  83. {
  84. while (!kthread_should_stop()) {
  85. spin_lock(&kthread_dev_obj->queue_lock);
  86. if(kthread_dev_obj->data_size){
  87. spin_unlock(&kthread_dev_obj->queue_lock);
  88. kthread_dev_obj->data[kthread_dev_obj->data_size]='/0';
  89. printk(kthread_dev_obj->data);//打印出用戶空間數據
  90. printk("in kthread/n");
  91. kthread_dev_obj->data_size=0;
  92. }
  93. else{
  94. set_current_state(TASK_INTERRUPTIBLE);
  95. spin_unlock(&kthread_dev_obj->queue_lock);
  96. schedule();
  97. }
  98. }
  99. return 0;
  100. }
  101. static int kthread_init(void)
  102. {
  103. int result;
  104. dev_t dev = MKDEV(kthread_major, 0);
  105. /* Figure out our device number. */
  106. if (kthread_major)
  107. result = register_chrdev_region(dev, 1, "kthread");
  108. else {
  109. result = alloc_chrdev_region(&dev, 0, 1, "kthread");
  110. kthread_major = MAJOR(dev);
  111. }
  112. if (result < 0) {
  113. printk(KERN_WARNING "kthread: unable to get major %d/n", kthread_major);
  114. return result;
  115. }
  116. if (kthread_major == 0)
  117. kthread_major = result;
  118. kthread_dev_obj= kmalloc(sizeof(struct kthread_dev), GFP_KERNEL);
  119. kthread_setup_cdev(&kthread_dev_obj->cdev, 0,&kthread_remap_ops);
  120. printk("kthread device installed, with major %d/n", kthread_major);
  121. my_class= class_create(THIS_MODULE, "kthread");
  122. // device_create(my_class, NULL, MKDEV(kthread_major, 0),NULL, "kthread");
  123. device_create(my_class, NULL, MKDEV(kthread_major, 0), "kthread");//for
  124. // 2.6.22
  125. kthread_dev_obj->name="kthreadtest";//內核線程的名稱
  126. spin_lock_init(&kthread_dev_obj->queue_lock);
  127. kthread_dev_obj->thread=kthread_run(kthread_fun,kthread_dev_obj,"%sd",kthread_dev_obj->name);//創建並運行內核線程
  128. return 0;
  129. }
  130. static void kthread_cleanup(void)
  131. {
  132. kthread_stop(kthread_dev_obj->thread);//停止內核線程
  133. cdev_del(&kthread_dev_obj->cdev);
  134. unregister_chrdev_region(MKDEV(kthread_major, 0), 1);
  135. device_destroy(my_class,MKDEV(kthread_major,0));
  136. class_destroy(my_class);
  137. kfree(kthread_dev_obj);
  138. printk("kthread device uninstalled/n");
  139. }
  140. module_init(kthread_init);
  141. 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的方法

使用新立得獲取安裝包

Copyright © Linux教程網 All Rights Reserved