Linux内核线程的创建及在QEMU上的测试技巧
发布时间:2021-12-18 14:55:04 所属栏目:教程 来源:互联网
导读:本文主要介绍一个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的方法 使用新立得获取安装包 (编辑:我爱故事小小网_铜陵站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |