等待队列与工作队列实例

论坛 期权论坛 脚本     
已经匿名di用户   2022-5-29 19:16   977   0

demo.c:

#include <linux/errno.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/cdev.h>
#include <linux/version.h>
#include <linux/slab.h>
#include <linux/ctype.h>
#include <linux/pagemap.h>
#include <linux/delay.h>

#include "demo.h"

MODULE_AUTHOR("fgj");
MODULE_LICENSE("Dual BSD/GPL");

struct simple_dev *simple_devices;
static unsigned char simple_inc=0;
static u8 demoBuffer[256];

static struct work_struct task;
static struct workqueue_struct *my_workqueue;
static int flag = 0;

static void DemoTask(void *p)
{
printk("DemoTask run...\n");
memset(demoBuffer,0x31,256);
wake_up_interruptible(&simple_devices->wq);
flag = 1;
printk("DemoTask end...\n");
}
int simple_open(struct inode *inode, struct file *filp)
{
struct simple_dev *dev;
simple_inc++;

dev = container_of(inode->i_cdev, struct simple_dev, cdev);
filp->private_data = dev;
return 0;
}

int simple_release(struct inode *inode, struct file *filp)
{
simple_inc--;
return 0;
}

ssize_t simple_read(struct file *filp, char __user *buf, size_t count,loff_t *f_pos)
{
struct simple_dev *dev = filp->private_data;

//等待数据可获得
if(wait_event_interruptible(dev->wq, flag != 0))
{
return - ERESTARTSYS;
}

flag = 0;

if (down_interruptible(&dev->sem))
return -ERESTARTSYS;

if (copy_to_user(buf,demoBuffer,count))
{
count=-EFAULT; /* 把数据写到应用程序空间 */
goto out;
}
out:
up(&dev->sem);
return count;
}

ssize_t simple_write(struct file *filp, const char __user *buf, size_t count,loff_t *f_pos)
{
return 0;
}

struct file_operations simple_fops = {
.owner = THIS_MODULE,
.read = simple_read,
.write = simple_write,
.open = simple_open,
.release = simple_release,
};

/*******************************************************
MODULE ROUTINE
*******************************************************/
void simple_cleanup_module(void)
{
dev_t devno = MKDEV(simple_MAJOR, simple_MINOR);

if (simple_devices)
{
cdev_del(&simple_devices->cdev);
kfree(simple_devices);
}
destroy_workqueue(my_workqueue);

unregister_chrdev_region(devno,1);
}

int simple_init_module(void)
{
int result;
dev_t dev = 0;

dev = MKDEV(simple_MAJOR, simple_MINOR);
result = register_chrdev_region(dev, 1, "DEMO");
if (result < 0)
{
printk(KERN_WARNING "DEMO: can't get major %d\n", simple_MAJOR);
return result;
}

simple_devices = kmalloc(sizeof(struct simple_dev), GFP_KERNEL);
if (!simple_devices)
{
result = -ENOMEM;
goto fail;
}
memset(simple_devices, 0, sizeof(struct simple_dev));

sema_init(&simple_devices->sem,1);
cdev_init(&simple_devices->cdev, &simple_fops);
simple_devices->cdev.owner = THIS_MODULE;
simple_devices->cdev.ops = &simple_fops;
result = cdev_add (&simple_devices->cdev, dev, 1);
if(result)
{
printk(KERN_NOTICE "Error %d adding DEMO\n", result);
goto fail;
}
init_waitqueue_head(&simple_devices->wq);

my_workqueue = create_workqueue("MYQUENU");
INIT_WORK(&task,DemoTask);
queue_work(my_workqueue, &task);
return 0;

fail:
simple_cleanup_module();
return result;
}

module_init(simple_init_module);
module_exit(simple_cleanup_module);

demo.h


#ifndef _simple_H_
#define _simple_H_

#include <linux/ioctl.h> /* needed for the _IOW etc stuff used later */

/********************************************************
* Macros to help debugging
********************************************************/
#undef PDEBUG /* undef it, just in case */
#ifdef simple_DEBUG
#ifdef __KERNEL__
# define PDEBUG(fmt, args...) printk( KERN_DEBUG "DEMO: " fmt, ## args)
#else//usr space
# define PDEBUG(fmt, args...) fprintf(stderr, fmt, ## args)
#endif
#else
# define PDEBUG(fmt, args...) /* not debugging: nothing */
#endif

#undef PDEBUGG
#define PDEBUGG(fmt, args...) /* nothing: it's a placeholder */

//设备号
#define simple_MAJOR 224
#define simple_MINOR 0
#define COMMAND1 1
#define COMMAND2 2

//设备结构
struct simple_dev
{
struct semaphore sem; /* mutual exclusion semaphore */
wait_queue_head_t wq;
struct cdev cdev; /* Char device structure */
};

//函数申明
ssize_t simple_read(struct file *filp, char __user *buf, size_t count,
loff_t *f_pos);
ssize_t simple_write(struct file *filp, const char __user *buf, size_t count,
loff_t *f_pos);
loff_t simple_llseek(struct file *filp, loff_t off, int whence);
int simple_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);


#endif /* _simple_H_ */

makefile:

ifneq ($(KERNELRELEASE),)
obj-m := demo.o
else
KERNELDIR := /opt/FriendlyARM/mini6410/linux/linux-2.6.38 //这个地方需要根据自己的区改变
PWD:=$(shell pwd)
all:
make -C $(KERNELDIR) M=$(PWD) modules
clean:
rm -rf *.ko *.o *.mod.c *.mod.o *.symvers
endif

测试函数read.c

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <fcntl.h>
void main()
{
int fd;
char buf[2];

fd = open("/dev/fgj", O_RDWR, S_IRUSR | S_IWUSR);
if (fd != - 1)
{
read(fd, &buf,2);
buf[2]=0;
printf("The data is %s\n", buf);
}
else
{
printf("device open failed\n");
}
close(fd);
}

运行结果:

[root@FriendlyARM /]# insmod demo.ko
DemoTask run...
DemoTask end...
[root@FriendlyARM /]# mknod /dev/fgj c 224 0
[root@FriendlyARM /]# ./read
The data is 11
[root@FriendlyARM /]#

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:81
帖子:4969
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP