等待队列与工作队列实例

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 /]#

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值