
本文共 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;
}
发表评论
最新留言
关于作者
