링크 ux 장치 드라이버 문자 장치 드라이버

7278 단어
먼저 연락 처 를 남 겨 두 고 드라이버 를 배 우 는 플러스 qq 295699450 이 있 습 니 다.
문자 장치 드라이버:
이 편 은 비교적 화가 난다.불 러 오 는 데 성 공 했 지만 데 이 터 를 읽 을 수 없습니다. 어떻게 된 일 인지 아 는 사람 이 있 으 면 메 시 지 를 남 겨 서 같이 토론 합 시다.
데이터 구조
struct scull_mem{
      void *data;
      struct scull_mem *next;
};

 
struct scull_dev{
      struct cdev cdev;
      unsigned long size;
      struct scull_mem *data;
}*dev;

전체 드라이버 코드 는 다음 과 같 습 니 다.
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <asm/uaccess.h>

#define BUFFERSIZE 4096

ssize_t scull_read (struct file *filp,char __user* buf,size_t count,loff_t *offset);
ssize_t scull_write(struct file *filp,const char __user*buf,size_t count,loff_t *offset);
int scull_open(struct inode *inode,struct file *filp);
int scull_release(struct inode *inode,struct file *filp);

struct scull_mem{
      void *data;
      struct scull_mem *next;
};
struct scull_dev{
      struct cdev cdev;
      unsigned long size;
      struct scull_mem *data;
}*dev;
dev_t scull_dev_num=0;
int major,minor;
int cdev_registered=0;

void scull_trim(void)
{
      struct scull_mem *ptr,*tmp;
      for(ptr=dev->data;ptr!=NULL;ptr=tmp){
          tmp=ptr->next;
          if(ptr->data!=NULL){
              kfree(ptr->data);
          }
          kfree(ptr);
      }
      dev->data=NULL;
      dev->size=0;
}
int scull_open(struct inode *inode,struct file *filp)
{
      printk(KERN_ALERT "Scull is opened!
"); if((filp->f_flags&O_ACCMODE)==O_WRONLY) scull_trim(); return 0; } int scull_release(struct inode *inode,struct file *filp) { printk(KERN_ALERT "Scull is released!
"); return 0; } struct scull_mem * scull_follow(int item) { struct scull_mem *tmp,*ptr=NULL; int times=item; for(tmp=dev->data;item-->=0;tmp=tmp->next){ if(tmp==NULL){ if((tmp=(struct scull_mem *)kmalloc(sizeof(struct scull_mem),GFP_KERNEL))==NULL) return NULL; tmp->next=NULL; if((tmp->data=kmalloc(BUFFERSIZE,GFP_KERNEL))==NULL){ return NULL; } memset(tmp->data,0,BUFFERSIZE); if(times==0){ dev->data=tmp; times++; } } ptr=tmp; } return ptr; } ssize_t scull_read (struct file *filp,char __user* buf,size_t count,loff_t *offset) { ssize_t retval=0; size_t item,pos; struct scull_mem *ptr; item=*offset / BUFFERSIZE; pos=*offset % BUFFERSIZE; ptr=scull_follow(item); if(ptr==NULL||ptr->data==NULL){ goto out; } if(*offset+count>dev->size) count=dev->size-*offset; count=count > (BUFFERSIZE-pos)? (BUFFERSIZE-pos):count; if(copy_to_user(buf,ptr->data+pos,count)){ retval=-EFAULT; goto out; } *offset+=count; retval=count; out: return retval; } ssize_t scull_write(struct file *filp,const char __user*buf,size_t count,loff_t *offset) { ssize_t retval=0; size_t item,pos; struct scull_mem *ptr; item=*offset / BUFFERSIZE; pos=*offset % BUFFERSIZE; ptr=scull_follow(item); if(ptr==NULL||ptr->data==NULL){ goto out; } count=count > (BUFFERSIZE-pos)? (BUFFERSIZE-pos):count; if(copy_from_user(ptr->data+pos,buf,count)){ retval=-EFAULT; goto out; } *offset+=count; retval=count; dev->size+=count; out: return retval; } loff_t scull_llseek(struct file *filp,loff_t offset,int start) { loff_t new; switch(start) { case 0: new=offset; break; case 1: new=filp->f_pos+offset; break; case 2: new=dev->size+offset; break; default: return -EINVAL; } if(new<0) return -EINVAL; filp->f_pos=new; return new; } struct file_operations scull_ops={ .owner=THIS_MODULE, .open=scull_open, .read=scull_read, .write=scull_write, .release=scull_release, .llseek=scull_llseek, .unlocked_ioctl=NULL, }; void cleanup(void) { if(cdev_registered) cdev_del(&dev->cdev); if(dev!=NULL){ scull_trim(); kfree(dev); } if(scull_dev_num!=0) unregister_chrdev_region(scull_dev_num,1); } static int __init scull_init(void) { int retval=0; /*first,requset device number*/ if((retval=alloc_chrdev_region(&scull_dev_num,0,1,"scull_jakilll"))<0) goto fail; major=MAJOR(scull_dev_num); minor=MINOR(scull_dev_num); /*then alloc device structure*/ if((dev=kmalloc(sizeof(struct scull_dev),GFP_KERNEL))==NULL){ retval=-ENOMEM; goto fail; } dev->size=0; dev->data=NULL; /*finally,register cdev*/ cdev_init(&dev->cdev,&scull_ops); dev->cdev.owner=THIS_MODULE; dev->cdev.ops=&scull_ops; if((retval=cdev_add(&dev->cdev,scull_dev_num,1))<0) goto fail; cdev_registered=1; printk(KERN_ALERT "Scull inited ok!
"); return retval; fail: cleanup(); return retval; } static void __exit scull_exit(void) { cleanup(); printk(KERN_ALERT "Scull cleanuped!
"); } module_init(scull_init); module_exit(scull_exit); MODULE_LICENSE("GPL");

초기 화:
장치 이름 에 따라 alloc 사용chrdev_region () 장치 번호 신청, sculldev 메모리 할당, cdev 사용init () cdev 장 치 를 초기 화하 고 dev 의 각 구성원 을 초기 화 합 니 다. 이어서 cdevadd () dev 의 cdev 를 커 널 에 추가 하여 초기 화 끝
마 운 트 해제:
먼저 커 널 에서 sucldev - > cdev 구조, 그리고 kfree  scull_dev 구조, 마지막 으로 unregister 사용chrdev_region () 장치 마 운 트 해제
위의 절차 와 같이 읽 기와 쓰기 프로그램 을 마음대로 쓰 는 것 이다.
 

좋은 웹페이지 즐겨찾기