linux 内核阻塞,linux内核之阻塞与非阻塞

vi btn_drv.c

#include < linux/init.h >

#include < linux/module.h >

#include < linux/fs.h >

#include < linux/cdev.h >

#include < linux/device.h >

#include < linux/irq.h >

#include < linux/interrupt.h >

#include < asm/gpio.h >

#include < plat/gpio-cfg.h >

#include < linux/access.h >

//定义按键硬件数据结构

struct button_resource

{

int gpio; //GPIO编号

int irq; //中断号

char *name ; //标签

}

//初始化按键对应的硬件信息

static struct button_resource btn_info[]=

{

[0]={

.gpio = S5PV210_GPH(0),

.irq = IRQ_EINT(0),

.name = "KEY_UP"

}

};

static int major;

static struct cdev btn_cdev;

static struct class *cls;

static wait_queue_head_t btn_wq; //分配等待队列头

static unsigned char key_val; //分配上报按键的值

static int ispress; // = 1,按键有操作,=0,表明按键无操作

static ssize_t btn_read(struct file *file, char

__user*buf,

size_t count, loff_t *ppos)

{

//1.判断按键操作是否有效,通过ispress来判断,如果有操作,则ispress =

1,这个函数立即返回,如果

//ispress = 0,没有操作,进程将进入休眠状态,等待唤醒,一旦被唤醒,就可以读取按键值给用户

printk("go to sleeping\n");

printk("process %d(%) to sleeping\n",

current->pid,current->comm);

wait_event_interruptible(&btn_wq, ispress);

ispress = 0;

//一旦被唤醒,上报按键的值

prink("I am wake up\n");

copy_to_user(buf, &key_val, 1);

return count;

}

static struct file_operations btn_fops =

{

.owner = THIS_MODULE,

.read = btn_read

}

static irqreturn_t button_isr(int irq, void*dev_id)

{

//1.获取每一个键对应的硬件信息

struct button_resource *pdata =

(structbutton_resource*)dev_id;

//2.获取按键对应的状态,设置上报的按键值

pinstate = gpio_get_value(pdata->gpio);

if(pinstate == 1)//松开按键,上报0x50

key_val = 0x50;

else if(pinstate == 0) //按下

key_val = 0x51;

//3.唤醒休眠的进程

ispress = 1;

wake_up_interruptible(&btn_wq); //唤醒休眠的进程

}

static int btn_init(void)

{

dev_t dev;

int i;

//0.判断是否采用非阻塞

if(file->flags & O_NONBLOCK)

{

//非阻塞方式

if(!ispress)

//判断是否有数据到来,如果没有,立即返回

{

printk("No data\n");

return -EAGAIN;

}

}

//阻塞方式

//1.申请设备号

alloc_chrdev_region(&dev, 0, 1, "buttons");

major = MAJOR(dev);

//2.初始化注册cdev

cdev_init(&btn_cdev, &btn_fops);

cdev_add(&btn_cdev, dev, 1);

//3.自动创建设备节点

cls = class_create(THIS_MODULE, "buttons");

device_create(cls, NULL ,dev, NULL, "mybuttons");

//4.申请GPIO资源和注册中断

for(i = 0; i < ARRAY_SIZE(btn_info); i++)

{

gpio_request(btn_info[i].gpio, btn_info.name);

request_irq(btn_info[i].irq,

button_isr,

IRQF_TRIGGER_RISING_IRQF_FAILING,

btn_info[i].name, &btn_info[i]);

}

//5.初始化等待队列头

init_waitqueue_head(&btn_wq);

return 0;

}

static void btn_exit(void)

{

dev_t dev = MKDEV(major , 0);

int i;

//释放GPIO资源和释放中断

for(i = 0; i

{

gpio_free(btn_info[i].gpio);

free_irq(btn_info[i].irq, &btn_info[i]);

}

//2.删除设备节点

device_destroy(cls, dev);

class_destroy(cls);

//3.卸载cdev

cdev_del(&btn_cdev);

//4.释放设备号

unregister_chrdev_region(dev, 1);

}

module_init(btn_init);

module_exit(btn_exit);

MODULE_LICENSE("GPL");

vi btn_test.c

#include < sys/types.h >

#include < sys/state.h >

#include < fcntl.h >

int main(void)

{

int fd;

unsigned char key_val;

fd = fopen("/dev/mybuttons", O_RDWR | O_NONBLOCK);

if(fd < 0)

{

printf(“open button failed.\n”);

return -1;

}

while(1)

{

read(fd, &key_val, 1);

printf("key_val = %#x\n",key_val);

}

close(fd);

return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值