易网时代-编程资源站
Welcome
微信登录
编程资源
图片资源库
蚂蚁家优选
PDF转换器
软件资源
软件开发
、
小程序制作
、
系统集成与运维
、
空间租用
、
硬件开发
、
视频监控
、
技术咨询与支持
——联系电话:0311-88999002/88999003
首页
/
操作系统
/
Linux
/
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的方法
使用新立得获取安装包
收藏该网址
版权所有©石家庄振强科技有限公司2024
冀ICP备08103738号-5
网站地图