linux阻塞和非阻塞,阻塞和非阻塞

# 等待队列

## 基本函数

```

wait_queue_head_t my_queue; 定义

init_waitqueue_head(&my_queue); 初始化等待队列

DECLARE_WAIT_QUEUE_HEAD(name) 定义并初始化等待队列头

void add_wait_queue(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry);

void add_wait_queue_exclusive(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry);

void remove_wait_queue(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry);

void wait_event(queue, condition)

void wait_event_interruptible(queue, condition) 可以被信号打断

void wait_event_timeout(queue, condition, timeout)

void wait_event_interruptible_timeout(queue, condition, timeout) jiffy为单位

void wake_up(wait_queue_head_t *queue);

void wake_up_interruptible(wait_queue_head_t *queue);

```

## 自动等待

```

ssize_t sleepy_read (struct file *filp, char __user *buf, size_t count, loff_t *pos)

{

printk(KERN_DEBUG "process %i (%s) going to sleep\n",

current->pid, current->comm);

wait_event_interruptible(wq, flag != 0);

flag = 0;

printk(KERN_DEBUG "awoken %i (%s)\n", current->pid, current->comm);

return 0; /* EOF */

}

ssize_t sleepy_write (struct file *filp, const char __user *buf, size_t count,

loff_t *pos)

{

printk(KERN_DEBUG "process %i (%s) awakening the readers...\n",

current->pid, current->comm);

flag = 1;

wake_up_interruptible(&wq);

return count; /* succeed, to avoid retrial */

}

```

## 手动等待

```

#if 0

/* 加入等待队列,等待被唤醒, 也就是有按键按下 */

ret = wait_event_interruptible(dev->r_wait,

atomic_read(&dev->releasekey));

if (ret) {

goto wait_error;

}

#endif

DECLARE_WAITQUEUE(wait, current); /* 定义一个等待队列 */

if(atomic_read(&dev->releasekey) == 0) { /* 没有按键按下 */

add_wait_queue(&dev->r_wait, &wait); /* 添加到等待队列头 */

__set_current_state(TASK_INTERRUPTIBLE);/* 设置任务状态 */

schedule(); /* 进行一次任务切换 */

if(signal_pending(current)) { /* 判断是否为信号引起的唤醒 */

ret = -ERESTARTSYS;

goto wait_error;

}

__set_current_state(TASK_RUNNING); /* 设置为运行状态 */

remove_wait_queue(&dev->r_wait, &wait); /* 将等待队列移除 */

}

```

```

static ssize_t imx6uirq_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)

{

int ret = 0;

unsigned char keyvalue = 0;

unsigned char releasekey = 0;

struct imx6uirq_dev *dev = (struct imx6uirq_dev *)filp->private_data;

if (filp->f_flags & O_NONBLOCK){ /* 非阻塞访问 */

if(atomic_read(&dev->releasekey) == 0)/* 没有按键按下,返回-EAGAIN */

return -EAGAIN;

} else {/* 阻塞访问 */

/* 加入等待队列,等待被唤醒,也就是有按键按下 */

ret = wait_event_interruptible(dev->r_wait, atomic_read(&dev->releasekey));

if (ret) {

goto wait_error;

}

}

keyvalue = atomic_read(&dev->keyvalue);

releasekey = atomic_read(&dev->releasekey);

if (releasekey) { /* 有按键按下 */

if (keyvalue & 0x80) {

keyvalue &= ~0x80;

ret = copy_to_user(buf, &keyvalue, sizeof(keyvalue));

} else {

goto data_error;

}

atomic_set(&dev->releasekey, 0);/* 按下标志清零 */

} else {

goto data_error;

}

return 0;

wait_error:

return ret;

data_error:

return -EINVAL;

}

void timer_function(unsigned long arg)

{

unsigned char value;

unsigned char num;

struct irq_keydesc *keydesc;

struct imx6uirq_dev *dev = (struct imx6uirq_dev *)arg;

num = dev->curkeynum;

keydesc = &dev->irqkeydesc[num];

value = gpio_get_value(keydesc->gpio); /* 读取IO值 */

if(value == 0){ /* 按下按键 */

atomic_set(&dev->keyvalue, keydesc->value);

}

else{ /* 按键松开 */

atomic_set(&dev->keyvalue, 0x80 | keydesc->value);

atomic_set(&dev->releasekey, 1);/* 标记松开按键,即完成一次完整的按键过程 */

}

/* 唤醒进程 */

if(atomic_read(&dev->releasekey)) {/* 完成一次按键过程 */

/* wake_up(&dev->r_wait); */

wake_up_interruptible(&dev->r_wait);

}

}

```

## 说明

```

```

# 轮训 Poll

## 基本函数

```

unsigned int(*poll) (struct file *filp, struct poll_table *wait);

//添加wait到等待队列, 作用L让参数queue对应的等待队列可以唤醒select睡眠进程

void poll_wait(struct file *filp, wait_queue_heat_t *queue, poll_table *wait);

```

## 实例

```

static struct file_operations imx6uirq_fops = {

.owner = THIS_MODULE,

.open = imx6uirq_open,

.read = imx6uirq_read,

.poll = imx6uirq_poll,

.release = imx6uirq_release,

};

unsigned int imx6uirq_poll(struct file *filp, struct poll_table *wait)

{

unsigned int mask = 0;

struct imx6uirq_dev *dev = (struct imx6uirq_dev *)filp->private_data;

poll_wait(filp, &dev->r_wait, wait);/* 将等待队列头添加到poll_table中 */

if(atomic_read(&dev->releasekey)) {/* 按键按下 */

mask = POLLIN | POLLRDNORM;/* 返回PLLIN */

}

return mask;

}

```

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值