微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > Linux驱动总结3

Linux驱动总结3

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

if(_IOC_NR(cmd)>

ioarg = &mem_devp->

wait->

spin_lock_irqsave(&q->

if (list_empty(&wait->

spin_unlock_irqrestore(&q->

spin_lock_irqsave(&q->

spin_unlock_irqrestore(&q->

list_for_each_entry_safe(curr, next, &q->

unsigned flags = curr->

if (curr->

_t wrqueue;

};

2、然后在模块初始化中初始化队列头:

/*初始化函数*/

static int memdev_init(void)

{

....

for(i = 0; i < MEMDEV_NR_DEVS; i)

{

mem_devp[i].size = MEMDEV_SIZE;

/*对设备的数据空间分配空间*/

mem_devp[i].data = kmalloc(MEMDEV_SIZE,GFP_KERNEL);

/*问题,没有进行错误的控制*/

memset(mem_devp[i].data,0,MEMDEV_SIZE);

/*初始化定义的互信息量*/

//初始化定义的自旋锁ua

spin_lock_init(&(mem_devp[i].lock));

/*初始化两个等待队列头,需要注意必须用括号包含起来,使得优先级正确*/

init_waitqueue_head(&(mem_devp[i].rdqueue));

init_waitqueue_head(&(mem_devp[i].wrqueue));

}

...

}

3、确定一个具体的条件,比如数据有无,具体的条件根据实际的情况设计。

/*等待条件*/

static bool havedata = false;

4、在需要堵塞的读函数,写函数中分别实现堵塞,首先定义等待队列的节点,并添加到队列中去,然后等待事件的唤醒进程。但是由于读写操作的两个等待队列都是基于条件havedata的,所以在读完成以后需要唤醒写,写完成以后需要唤醒读操作,同时更新条件havedata,最后还要移除添加的等待队列节点。

/*read函数的实现*/

static ssize_t mem_read(struct file *filp,char __user *buf, size_t size,loff_t *ppos)

{

unsigned long p = *ppos;

unsigned int count = size;

int ret = 0;

struct mem_dev *dev = filp->private_data;

/*参数的检查,首先判断文件位置*/

if(p >= MEMDEV_SIZE)

return 0;

/*改正文件大小*/

if(count > MEMDEV_SIZE - p)

count = MEMDEV_SIZE - p;

#if 0

/*添加一个等待队列节点到当前进程中*/

DECLARE_WAITQUEUE(wait_r,current);

/*将节点添加到等待队列中*/

add_wait_queue(&dev->rdqueue,&wait_r);

/*添加等待队列,本来采用if即可,但是由于信号等可能导致等待队列的唤醒,因此采用循环,确保不会出现误判*/

#endif

while(!havedata)

{

/*判断用户是否设置为非堵塞模式读,告诉用户再读*/

if(filp->f_flags & O_NONBLOCK)

return -EAGAIN;

/*依据条件havedata判断队列的状态,防止进程被信号唤醒*/

wait_event_interruptible(dev->rdqueue,havedata);

}

spin_lock(&dev->lock);

/*从内核读数据到用户空间,实质就通过private_data访问设备*/

if(copy_to_user(buf,(void *)(dev->data p),count))

{

/*出错误*/

ret = -EFAULT;

}

else

{

/*移动当前文件光标的位置*/

*ppos = count;

ret = count;

printk(KERN_INFO "read %d bytes(s) from %d",count,p);

}

spin_unlock(&dev->lock);

#if 0

/*将等待队列节点从读等待队列中移除*/

remove_wait_queue(&dev->rdqueue,&wait_r);

#endif

/*更新条件havedate*/

havedata = false;

/*唤醒写等待队列*/

wake_up_interruptible(&dev->wrqueue);

return ret;

}

/*write函数的实现*/

static ssize_t mem_write(struct file *filp,const char __user *buf,size_t size,loff_t *ppos)

{

unsigned long p = *ppos;

unsigned int count = size;

int ret = 0;

/*获得设备结构体的指针*/

struct mem_dev *dev = filp->private_data;

/*检查参数的长度*/

if(p >= MEMDEV_SIZE)

return 0;

if(count > MEMDEV_SIZE - p)

count = MEMDEV_SIZE - p;

#if 0

/*定义并初始化一个等待队列节点,添加到当前进程中*/

DECLARE_WAITQUEUE(wait_w,current);

/*将等待队列节点添加到等待队列中*/

add_wait_queue(&dev->wrqueue,&wait_w);

#endif

/*添加写堵塞判断*/

/*为何采用循环是为了防止信号等其他原因导致唤醒*/

while(havedata)

{

/*如果是以非堵塞方式*/

if(filp->f_flags & O_NONBLOCK)

return -EAGAIN;

/*分析源码发现,wait_event_interruptible 中存在DECLARE_WAITQUE

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

网站地图

Top