Linux内核线程的创建及在QEMU上的测试方法
Linux内核线程的创建及在QEMU上的测试方法
本文主要介绍一个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的方法
使用新立得获取安装包
|
评论暂时关闭