阻塞操作Demo
发布日期:2021-05-07 13:26:43 浏览次数:27 分类:原创文章

本文共 5557 字,大约阅读时间需要 18 分钟。

—-头文件—-

#define GLOBALFIFO_SIZE 0x1000 /全局fifo最大4K字节/

/ CDEV字符设备相关***
int CDRIVER_MAJOR=0; 
int CDRIVER_MINOR=0; 
int count=1;

#define CDRIVER_NAME “simple_chrdev”

struct cdev *simple_cdev; //字符设备结构体 
dev_t simple_dev; //设备 
static struct device *dev; 
static struct class *simple_class;

struct mhrfifo_dev 

unsigned int current_len; /fifo有效数据长度
unsigned char mem[GLOBALFIFO_SIZE]; /全局内存
struct mutex mutex; /并发控制用的互斥体
wait_queue_head_t r_wait; /阻塞读用的等待队列头
wait_queue_head_t w_wait; /阻塞写用的等待队列头
};

struct mhrfifo_dev *mhrfifo_devp;

static ssize_t mac_read(struct file *filp, char *buffer, size_t count, loff_t *ppos) 

struct mhrfifo_dev *dev = filp->private_data; 
//定义等待队列 
DECLARE_WAITQUEUE(wait,current); 
mutex_lock(&dev->mutex);

//添加到等待队列add_wait_queue(&dev->r_wait, &wait);//如果访问资源为空while(dev->current_len == 0){        //如果是非阻塞访问        if(filp->f_flags & O_NONBLOCK){            mutex_unlock(&dev->mutex);            return -EAGAIN;            }        //阻塞访问        //进行进程状态切换,设置当前进程状态为 浅睡眠,并没有真正睡眠        __set_current_state(TASK_INTERRUPTIBLE);        //当前进程切换出去之前释放互斥体 让给写进程        mutex_unlock(&dev->mutex);        schedule(); //调度当前读进程出去 此时读进程进入睡眠状态        if(signal_pending(current))            {                remove_wait_queue(&dev->r_wait, &wait);//从附属的等待队列移除                set_current_state(TASK_RUNNING);                return - ERESTARTSYS;            }        //获取互斥体        mutex_lock(&dev->mutex);    }//从用户空间拷贝到内核空间if(count > GLOBALFIFO_SIZE - dev->current_len)    count = dev->current_len;if(copy_to_user(buffer, dev->mem, count))    {            //读操作失败            mutex_unlock(&dev->mutex);            return - EFAULT;    }    else{         //读操作成功后 进行fifo数据空间移位        memcpy(dev->mem, dev->mem+count, dev->current_len - count); //fifo数据前移        dev->current_len -= count;//有效数据长度减少        printk(KERN_INFO "read %ld bytes(s),current_len:%d\n", count, dev->current_len);        wake_up_interruptible(&dev->w_wait);//唤醒可能阻塞的写进程    }

return 0; 
}

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

struct mhrfifo_dev *dev = filp->private_data; 
DECLARE_WAITQUEUE(wait,current); 
mutex_lock(&dev->mutex); 
add_wait_queue(&dev->w_wait, &wait);

if(dev->current_len == GLOBALFIFO_SIZE){        if(filp->f_flags & O_NONBLOCK)            {                mutex_unlock(&dev->mutex);                return EAGAIN;              }        __set_current_state(TASK_INTERRUPTIBLE);        mutex_unlock(&dev->mutex);        schedule();        if(signal_pending(current))            {                remove_wait_queue(&dev->w_wait,&wait);                set_current_state(TASK_RUNNING);                return - ERESTARTSYS;               }        mutex_lock(&dev->mutex);    }if(count > GLOBALFIFO_SIZE - dev->current_len)    count = dev->current_len;if(copy_from_user(dev->mem + dev->current_len, buf, count)){        mutex_lock(&dev->mutex);        return EFAULT;    }    else{        dev->current_len += count;        wake_up_interruptible(&dev->r_wait);    }    return 0;   

}

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

filp->private_data = mhrfifo_devp; 
return 0; 
}

struct file_operations simple_fops= 

.owner=THIS_MODULE, 
.open=mac_open, 
.read=mac_read, 
.write = mac_write, 
};

/* 本代码自动生成了/dev/simple */ 
static int init_mycdev(void) 

int ret; 
printk( KERN_DEBUG “Module skeleton init\n” ); 
/register major and minor
if(CDRIVER_MAJOR!=0) 

simple_dev=MKDEV(CDRIVER_MAJOR,CDRIVER_MINOR); 
ret=register_chrdev_region(simple_dev,count,CDRIVER_NAME); 

else 

/dynamic assign major
ret=alloc_chrdev_region(&simple_dev,CDRIVER_MINOR,count,CDRIVER_NAME); 
CDRIVER_MAJOR=MAJOR(simple_dev); 

if(ret<0) 

printk(KERN_ERR”cannot get major %d \n”,CDRIVER_MAJOR); 
return -1; 

/分配一个字符设备结构体
simple_cdev=cdev_alloc();

if(simple_cdev!=NULL){    cdev_init(simple_cdev,&simple_fops);    simple_cdev->ops=&simple_fops;    simple_cdev->owner=THIS_MODULE;    //向系统 添加字符设备    if(cdev_add(simple_cdev,simple_dev,count)!=0)    {        printk(KERN_NOTICE "something wrong when adding simple_cdev!\n");    }    else    {        printk("success adding simple_cdev!\n");    }}else{    printk(KERN_ERR "register simple_dev error!\n");    return -1;}simple_class = class_create(THIS_MODULE, "zusaiceshi");if (IS_ERR(simple_class)){    printk( KERN_DEBUG "class_create error\n" );    return -1;}printk(KERN_ERR "devno is %d \n",simple_dev);     dev=device_create(simple_class, NULL, simple_dev,NULL,"zusaiceshi");mhrfifo_devp = kzalloc(sizeof(struct mhrfifo_dev), GFP_KERNEL);mutex_init(&mhrfifo_devp->mutex);init_waitqueue_head(&mhrfifo_devp->r_wait); init_waitqueue_head(&mhrfifo_devp->w_wait);return 0;

}

static void exit_mycdev(void) 

printk( KERN_DEBUG “Module skeleton exit\n” ); 
device_destroy(simple_class, simple_dev); 
class_destroy(simple_class);

cdev_del(simple_cdev);unregister_chrdev_region(simple_dev,count);

}

module_init(init_mycdev); 
module_exit(exit_mycdev);

MODULE_DESCRIPTION(“a test of char device driver”); 
MODULE_AUTHOR(“Jerry”); 
MODULE_LICENSE(“GPL”);

用户程序:

int main() 

int *buffer; 
int i; 
int fd; 
fd = open(“/dev/zusaiceshi”,O_RDWR); 
if(fd == -1){ 
printf(“open device error”); 
return 0; 

buffer = malloc(10*sizeof(int)); 
for(i = 0;i < 10;i ++){ 
*(buffer+i) = i; 

write(fd, buffer,i*sizeof(int)); 
return 0; 
}

int main() 

unsigned int buffer[100]; 
int i; 
int fd; 
fd = open(“/dev/zusaiceshi”,O_RDWR); 
if(fd == -1){ 
printf(“open device error”); 
return 0; 

read(fd,buffer,5); 
for(i = 0;i < 5; i ++){ 
//printf(“buffer[%d] = %d\n”, i, buffer[i]); 
printf(“%d\n”,buffer[i]); 

return 0; 
}


上一篇:list_for_each_entry解析
下一篇:设备驱动之阻塞

发表评论

最新留言

很好
[***.229.124.182]2025年04月07日 15时47分31秒