阻塞操作Demo

—-头文件—-

#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; 
}


猜你喜欢

转载自blog.csdn.net/linuxarmbiggod/article/details/79160215