微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > Linux内核开发之异步通知与异步I/O(二)

Linux内核开发之异步通知与异步I/O(二)

时间:12-09 来源:互联网 点击:

“曾经有一份真挚的爱情摆在面前,我却不懂珍惜;曾经有一个承诺,我却倍感珍惜,今天一定要好好讲讲..”

讲讲啥,讲讲上节说的那个异步通知的例子呗,大家喜欢看代码,咋们就先上代码:

struct globalfifo_dev

{

struct cdev cdev; /*cdev结构体*/

unsigned int current_len; /*fifo有效数据长度*/

unsigned char mem[GLOBALFIFO_SIZE]; /*全局内存*/

struct semaphore sem; /*并发控制用的信号量*/

wait_queue_head_t r_wait; /*阻塞读用的等待队列头*/

wait_queue_head_t w_wait; /*阻塞写用的等待队列头*/

struct fasync_struct *async_queue; /* 异步结构体指针,用于读 */

};

/*文件释放函数*/

int globalfifo_release(struct inode *inode, struct file *filp)

{

/* 将文件从异步通知列表中删除 */

globalmem_fasync( - 1, filp, 0);

return 0;

}

static int globalfifo_fasync(int fd, struct file *filp, int mode)

{

struct globalfifo_dev *dev = filp->private_data;

return fasync_helper(fd, filp, mode, &dev->async_queue);

}

/*globalfifo写操作*/

static ssize_t globalfifo_write(struct file *filp, const char __user *buf,

size_t count, loff_t *ppos)

{

struct globalfifo_dev *dev = filp->private_data; //获得设备结构体指针

int ret;

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

down(&dev->sem); //获取信号量

add_wait_queue(&dev->w_wait, &wait); //进入写等待队列头

/* 等待FIFO非满 */

if (dev->current_len == GLOBALFIFO_SIZE)

{

if (filp->f_flags &O_NONBLOCK)

//如果是非阻塞访问

{

ret = - EAGAIN;

goto out;

}

__set_current_state(TASK_INTERRUPTIBLE); //改变进程状态为睡眠

up(&dev->sem);

schedule(); //调度其他进程执行

if (signal_pending(current))

//如果是因为信号唤醒

{

ret = - ERESTARTSYS;

goto out2;

}

down(&dev->sem); //获得信号量

}

/*从用户空间拷贝到内核空间*/

if (count > GLOBALFIFO_SIZE - dev->current_len)

count = GLOBALFIFO_SIZE - dev->current_len;

if (copy_from_user(dev->mem + dev->current_len, buf, count))

{

ret = - EFAULT;

goto out;

}

else

{

dev->current_len += count;

printk(KERN_INFO "written %d bytes(s),current_len:%d\n", count, dev

->current_len);

wake_up_interruptible(&dev->r_wait); //唤醒读等待队列

/* 产生异步读信号 */

if (dev->async_queue)

kill_fasync(&dev->async_queue, SIGIO, POLL_IN);

ret = count;

}

out: up(&dev->sem); //释放信号量

out2:remove_wait_queue(&dev->w_wait, &wait); //从附属的等待队列头移除

set_current_state(TASK_RUNNING);

return ret;

}

下面再给出测试程序:

#include ...

//接收到异步读信号的动作

void input_handler(int signum)

{

printf("Receive a signal from globalfifo,signalnum:%d\n",signum);

}

int main()

{

int fd, oflags;

fd = open("/dev/globalfifo", O_RDWR, S_IRUSR | S_IWUSR);

if (fd != - 1)

{

//启动信号驱动机制

signal(SIGIO, input_handler); //让input_handler()处理SIGIO信号

fcntl(fd, F_SETOWN, getpid());

oflags = fcntl(fd, F_GETFL);

fcntl(fd, F_SETFL, oflags | FASYNC);

while(1)

{

sleep(100);

}

}

else

{

printf("device open failure\n");

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top