Linux设备驱动程序学习笔记:(1) 字符设备驱动入门1

Linux设备驱动程序学习笔记:(1) 字符设备驱动入门1

 

 

// 这是一个最简单的字符设备驱动,入门专用.
// scull1.h
#ifndef _SCULL1_H
#define  _SCULL1_H

#include 
< linux / init.h >
#include 
< linux / module.h >
#include 
< linux / kernel.h >
#include 
< linux / types.h >
#include 
< linux / fs.h >
#include 
< linux / version.h >
#include 
< asm / uaccess.h >
#include 
< linux / cdev.h >
#include 
< linux / mm.h >
#include 
< linux / errno.h >


#define  SCULL_MAJOR 0
#define  SCULL_SIZE    0x1000
#define  SCULL_CMD_CLEAR    0x01


struct  scull_dev{
    
struct  cdev cDev;
    
char    mem[SCULL_SIZE];
};


int  scull_open( struct  inode *  inode, struct  file *  filp);

ssize_t scull_read(
struct  file  * filp,  char  __user  * buf, size_t count,loff_t  * f_pos);             

ssize_t scull_write(
struct  file  * filp,  const   char  __user  * buf, size_t count,loff_t  * f_pos);

int  scull_release( struct  inode *  inode, struct  file *  filp);

#endif






// scull1.c
#include  " scull1.h "

MODULE_LICENSE(
" Dual BSD/GPL " );
MODULE_AUTHOR(
" Aaron.xu " );
MODULE_DESCRIPTION(
" hello driver test " );
MODULE_VERSION(
" 0.1 " );

static   int  scull_major  =  SCULL_MAJOR;
struct  scull_dev mydev;

struct  file_operations scull_fops  =  
{
    .owner     
=  THIS_MODULE,
    .open     
=  scull_open,
    .release 
=  scull_release,
    .read     
=  scull_read,
    .write     
=  scull_write,
};



static   void  scull_setup_cdev( void )
{
    
int  err;
    dev_t devid 
=  MKDEV(scull_major, 0 );

    
    cdev_init(
& mydev.cDev, & scull_fops);
    
    printk(KERN_INFO 
" &mydev.cDev.ops:%p \n " , & mydev.cDev.ops);

    mydev.cDev.owner    
=  THIS_MODULE;
    mydev.cDev.ops        
=   & scull_fops;

    printk(KERN_INFO 
" &mydev.cDev.ops:%p \n " , & mydev.cDev.ops);

    err    
=  cdev_add( & mydev.cDev,devid, 1 );
    
if  (err != 0 )
    {
        printk(KERN_ERR 
" cdev_add Error,err:%d \n " ,err);
    }
}

static   int  scull_init( void )
{
    
int  err;
    dev_t devid 
=  MKDEV(scull_major, 0 );

    
if  (scull_major)
    {
        err 
=  register_chrdev_region(devid, 1 , " scull1 " );
    }
    
else
    {
        err 
=  alloc_chrdev_region( & devid, 0 , 1 , " scull1 " );
        scull_major 
=  MAJOR(devid);
    }

    
if  (err  != 0  )
    {
        printk(KERN_ERR 
" register chrdev region error,err:%d \n " ,err);
        
return  err;
    }

    scull_setup_cdev();
    
return   0 ;
}

static   void  scull_exit( void )
{
    cdev_del(
& mydev.cDev);
    unregister_chrdev_region(MKDEV(scull_major,
0 ), 1 );
}


int  scull_open( struct  inode *  inode, struct  file *  filp)
{
    filp
-> private_data  =   & mydev;
    
return   0 ;
}

ssize_t scull_read(
struct  file  * filp,  char  __user  * buf, size_t count,loff_t  * f_pos)               
{
    unsigned 
long  pos  =   * f_pos;
    
int  err  =   0 ;
    
int  ret  =   0 ;
    
struct  scull_dev *  p_mydev  =  filp -> private_data;

    
if  (pos  >=  SCULL_SIZE)
    {
        
return   0 ;
    }

    
if  (count  >  (SCULL_SIZE  -  pos) )
    {
        count 
=  SCULL_SIZE  -  pos;
    }

    err 
=  copy_to_user(buf,p_mydev -> mem + pos,count);
    
if  (err  != 0  )
    {
        ret 
=   - EFAULT;
    }
    
else
    {
        
* f_pos  +=  count;
        ret 
=  count;
        printk(KERN_INFO 
" read %d byte(s) from %lu \n " ,ret,pos);
    }
    
return  ret;
}

ssize_t scull_write(
struct  file  * filp,  const   char  __user  * buf, size_t count,loff_t  * f_pos)
{
    unsigned 
long  pos  =   * f_pos;
    
int  err  =   0 ;
    
int  ret  =   0 ;
    
struct  scull_dev *  p_mydev  =  filp -> private_data;

    
if  (pos  >=  SCULL_SIZE)
    {
        
return   0 ;
    }

    
if  (count  >  (SCULL_SIZE  -  pos) )
    {
        count 
=  SCULL_SIZE  -  pos;
    }

    err 
=  copy_from_user(p_mydev -> mem + pos,buf,count);
    
if  (err  != 0  )
    {
        ret 
=   - EFAULT;
    }
    
else
    {
        
* f_pos  +=  count;
        ret 
=  count;
        printk(KERN_INFO 
" write %d byte(s) from %lu \n " ,ret,pos);
    }
    
return  ret;
}

int  scull_release( struct  inode *  inode, struct  file *  filp)
{
    
return   0 ;
}


module_init(scull_init);
module_exit(scull_exit);



// Makefile
obj - m     += scull1.o
KERNELDIR    :
=   / usr / src / linux - headers - 2.6 . 32 - 5 - 686
PWD    :
= $(shell pwd)
.PHONY: test clean all
all:
    $(MAKE) 
- C $(KERNELDIR) M = $(PWD) modules
clean:
    rm 
- rf  * .o  *~  core .depend . * .cmd  * .ko  * .mod.c .tmp_versionsm  * .order  * .symvers .tmp_versions

test:
    insmod .
/ scull1.ko
    rmmod scull1
    dmesg 
- c



// 创建设备节点
make_dev_node
#
!/ bin / bash
DEVICE
= " scull1 "
MAJOR
= `awk  " \\$2==\ " $DEVICE\ "  {print \\$1} "   / proc / devices`
cmd
= " mknod /dev/$DEVICE c $MAJOR 0 "
echo $cmd
`$cmd`

 

你可能感兴趣的:(Linux设备驱动程序学习笔记:(1) 字符设备驱动入门1)