Linux Driver互斥、异步通知、阻塞与非阻塞综合实例
来源:互联网 发布:软件图标下载 编辑:程序博客网 时间:2024/06/08 16:26
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/irq.h>
#include <asm/uaccess.h>
#include <linux/interrupt.h>
#include <plat/gpio-cfg.h>
#include <plat/gpio-fns.h>
#include <mach/gpio-nrs.h>
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/poll.h>
#include <linux/semaphore.h>
static dev_t dev;
static struct cdev *my_cdev = NULL;
static struct class *cdev_class = NULL;
static struct device *cdev_class_device = NULL;
static unsigned char key_val;
static volatile int condition = 0;
static DECLARE_WAIT_QUEUE_HEAD(wq);
static DEFINE_SEMAPHORE(button_lock);
struct key_desc
{
int pin;
char value;
};
static struct key_desc my_desc[4] = {
{ S3C2410_GPF(1), 0x01 },
{ S3C2410_GPF(4), 0x02 },
{ S3C2410_GPF(2), 0x03 },
{ S3C2410_GPF(0), 0x04 },
};
MODULE_LICENSE("GPL");
static irqreturn_t key_irq(int irq, void *dev_id)
{
struct key_desc *tmp = (struct key_desc *)dev_id;
if(!s3c2410_gpio_getpin(tmp->pin))
{
key_val = tmp->value;
}
else
{
key_val = 0x10|tmp->value;
}
condition = 1;
wake_up_interruptible(&wq);
return IRQ_HANDLED;
}
static int key_open(struct inode *inode, struct file *file)
{
if(file->f_flags & O_NONBLOCK)
{
if(down_trylock(&button_lock))
return -EBUSY;
}
else
{
down(&button_lock);
}
request_irq(IRQ_EINT1 , key_irq, IRQ_TYPE_EDGE_BOTH, "K1", &my_desc[0]);
request_irq(IRQ_EINT4 , key_irq, IRQ_TYPE_EDGE_BOTH, "K2", &my_desc[1]);
request_irq(IRQ_EINT2 , key_irq, IRQ_TYPE_EDGE_BOTH, "K3", &my_desc[2]);
request_irq(IRQ_EINT0 , key_irq, IRQ_TYPE_EDGE_BOTH, "K4", &my_desc[3]);
return 0;
}
static ssize_t key_close(struct inode *inode, struct file *file)
{
free_irq(IRQ_EINT1, &my_desc[0]);
free_irq(IRQ_EINT4, &my_desc[1]);
free_irq(IRQ_EINT2, &my_desc[2]);
free_irq(IRQ_EINT0, &my_desc[3]);
up(&button_lock);
return 0;
}
static ssize_t key_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
{
if(count != 1)
{
return -EINVAL;
}
if(file->f_flags & O_NONBLOCK)
{
if(!condition)
return -EAGAIN;
}
else
{
wait_event_interruptible(wq, condition);
}
copy_to_user(buf, &key_val, 1);
condition = 0;
return 1;
}
static unsigned key_poll(struct file *file, poll_table *wait)
{
unsigned int mask = 0;
poll_wait(file, &wq, wait);
if(condition)
mask |= POLLIN|POLLRDNORM;
return mask;
}
static struct file_operations fops = {
.owner = THIS_MODULE,
.open = key_open,
.release= key_close,
.read = key_read,
.poll = key_poll,
};
static int key_drv_init(void)
{
int ret = 0;
ret = alloc_chrdev_region(&dev, 0, 4, "mykey");
if(ret < 0)
{
printk("alloc_chrdev_region\n");
}
my_cdev = cdev_alloc();
cdev_init(my_cdev, &fops);
my_cdev->owner = THIS_MODULE;
cdev_add(my_cdev, dev, 4);
cdev_class = class_create(THIS_MODULE, "mykey");
cdev_class_device = device_create(cdev_class, NULL, dev, NULL, "keybutton");
return 0;
}
static void key_drv_exit(void)
{
device_destroy(cdev_class, dev);
class_destroy(cdev_class);
cdev_del(my_cdev);
kzfree(my_cdev);
unregister_chrdev_region(dev, 4);
return ;
}
module_init(key_drv_init);
module_exit(key_drv_exit);
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/irq.h>
#include <asm/uaccess.h>
#include <linux/interrupt.h>
#include <plat/gpio-cfg.h>
#include <plat/gpio-fns.h>
#include <mach/gpio-nrs.h>
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/poll.h>
#include <linux/semaphore.h>
static dev_t dev;
static struct cdev *my_cdev = NULL;
static struct class *cdev_class = NULL;
static struct device *cdev_class_device = NULL;
static unsigned char key_val;
static volatile int condition = 0;
static DECLARE_WAIT_QUEUE_HEAD(wq);
static DEFINE_SEMAPHORE(button_lock);
struct key_desc
{
int pin;
char value;
};
static struct key_desc my_desc[4] = {
{ S3C2410_GPF(1), 0x01 },
{ S3C2410_GPF(4), 0x02 },
{ S3C2410_GPF(2), 0x03 },
{ S3C2410_GPF(0), 0x04 },
};
MODULE_LICENSE("GPL");
static irqreturn_t key_irq(int irq, void *dev_id)
{
struct key_desc *tmp = (struct key_desc *)dev_id;
if(!s3c2410_gpio_getpin(tmp->pin))
{
key_val = tmp->value;
}
else
{
key_val = 0x10|tmp->value;
}
condition = 1;
wake_up_interruptible(&wq);
return IRQ_HANDLED;
}
static int key_open(struct inode *inode, struct file *file)
{
if(file->f_flags & O_NONBLOCK)
{
if(down_trylock(&button_lock))
return -EBUSY;
}
else
{
down(&button_lock);
}
request_irq(IRQ_EINT1 , key_irq, IRQ_TYPE_EDGE_BOTH, "K1", &my_desc[0]);
request_irq(IRQ_EINT4 , key_irq, IRQ_TYPE_EDGE_BOTH, "K2", &my_desc[1]);
request_irq(IRQ_EINT2 , key_irq, IRQ_TYPE_EDGE_BOTH, "K3", &my_desc[2]);
request_irq(IRQ_EINT0 , key_irq, IRQ_TYPE_EDGE_BOTH, "K4", &my_desc[3]);
return 0;
}
static ssize_t key_close(struct inode *inode, struct file *file)
{
free_irq(IRQ_EINT1, &my_desc[0]);
free_irq(IRQ_EINT4, &my_desc[1]);
free_irq(IRQ_EINT2, &my_desc[2]);
free_irq(IRQ_EINT0, &my_desc[3]);
up(&button_lock);
return 0;
}
static ssize_t key_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
{
if(count != 1)
{
return -EINVAL;
}
if(file->f_flags & O_NONBLOCK)
{
if(!condition)
return -EAGAIN;
}
else
{
wait_event_interruptible(wq, condition);
}
copy_to_user(buf, &key_val, 1);
condition = 0;
return 1;
}
static unsigned key_poll(struct file *file, poll_table *wait)
{
unsigned int mask = 0;
poll_wait(file, &wq, wait);
if(condition)
mask |= POLLIN|POLLRDNORM;
return mask;
}
static struct file_operations fops = {
.owner = THIS_MODULE,
.open = key_open,
.release= key_close,
.read = key_read,
.poll = key_poll,
};
static int key_drv_init(void)
{
int ret = 0;
ret = alloc_chrdev_region(&dev, 0, 4, "mykey");
if(ret < 0)
{
printk("alloc_chrdev_region\n");
}
my_cdev = cdev_alloc();
cdev_init(my_cdev, &fops);
my_cdev->owner = THIS_MODULE;
cdev_add(my_cdev, dev, 4);
cdev_class = class_create(THIS_MODULE, "mykey");
cdev_class_device = device_create(cdev_class, NULL, dev, NULL, "keybutton");
return 0;
}
static void key_drv_exit(void)
{
device_destroy(cdev_class, dev);
class_destroy(cdev_class);
cdev_del(my_cdev);
kzfree(my_cdev);
unregister_chrdev_region(dev, 4);
return ;
}
module_init(key_drv_init);
module_exit(key_drv_exit);
- Linux Driver互斥、异步通知、阻塞与非阻塞综合实例
- Linux Driver中阻塞与非阻塞
- 同步、互斥 阻塞与非阻塞
- linux驱动-阻塞_非阻塞_异步通知
- 阻塞与非阻塞 异步非阻塞
- 同步、异步、互斥、信号量、阻塞、非阻塞
- 同步、异步、互斥、信号量、阻塞、非阻塞
- 同步、异步、互斥、信号量、阻塞、非阻塞
- 并发,同步,异步,互斥,阻塞,非阻塞的理解
- 同步、异步、互斥、信号量、阻塞、非阻塞
- 并发 并行 阻塞 非阻塞 同步 异步 互斥
- 并发,同步,异步,互斥,阻塞,非阻塞的理解
- 07-S3C2440驱动学习(一)嵌入式linux字符设备驱动-按键驱动程序之异步通知机制+原子操作+互斥信号量+阻塞与非阻塞+定时器去抖
- 信号量与互斥、阻塞与非阻塞的概念
- linux 中阻塞与非阻塞 同步与异步
- linux 中阻塞与非阻塞 同步与异步
- verilog阻塞与非阻塞的综合
- Linux 网络I/O: 同步、异步、阻塞与非阻塞
- c语言控制台输出制作推箱子游戏
- TOJ 3018 ZOJ 1655 Transport Goods / dijkstra
- Batch update returned unexpected row count from update; actual row count: 0; expected: 1
- java中jni的使用。
- 时间在流逝
- Linux Driver互斥、异步通知、阻塞与非阻塞综合实例
- C++中成员初始化列表的使用
- jQuery的事件绑定命名空间
- 中国智能高清视频监控未来发展趋势
- Red Hat 配置ip地址
- MsChart的使用
- c标签获取集合的长度
- VMware中Ubuntu10.10下建立samba服务器与Windows共享文件
- centos6.2安装及网络配置手记