Linux下字符型驱动程序完整源码入门示例

本文中的程序在redhat9.0下通过。参考O'Reilly《linux设备驱动程序》,及网上的一些参考资料,与网上所能搜索到的资料大体相同,把它贴出来,是自己学习的一个总结,和作为笔记记录,以供初学者一个完整的源代码。

/* firstdriver.c  起始 */

#define __NO_VERSION__
#include <linux/module.h>
#include <linux/version.h>

char kernel_version[] = UTS_RELEASE;

#ifndef __KERNEL__
#define __KERNEL__
#endif

#include <linux/kernel.h>   /* printk() */
#include <linux/fs.h>          /* everything, e.g. file_operations, file */
#include <linux/errno.h>
#include <linux/types.h>    /* ssize_t */
#include <asm-i386/uaccess.h>    /* verify_area, __put_user */

#define TEST_MAJOR 0

int test_major = TEST_MAJOR; /* the major of the test driver */


/* open function */
static int test_open(struct inode* inode, struct file* filp)
{
     MOD_INC_USE_COUNT; /* defined in <linux/module.h> */
     return 0; /* success */
}

/* release function */
static int test_release(struct inode *inode, struct file* filp)
{
     MOD_DEC_USE_COUNT;
     return 0;
}

/* read function */
static ssize_t test_read(struct file* filp, char* buf, size_t count, loff_t* fpos)
{
     int i;
     if(verify_area(VERIFY_WRITE, buf, count) == -EFAULT)
          return -EFAULT;

    for(i=count; i>0; i--)
   {
        __put_user(1, buf);
        buf++;
   }
    return count;
}

/* write function */
static ssize_t test_write(struct file* filp, const char* buf, size_t count, loff_t* fpos)
{
     return count;
}

#if 0
struct file_operations test_fops = {
     NULL,          /* struct module */
     NULL,          /* llseek */
     test_read,  /* read */
     test_write, /* write */
     NULL,         /* readdir */
     NULL,         /* poll */
     NULL,         /* ioctl */
     NULL,         /* mmap */
     test_open, /* open */
     NULL,         /* flush */
     test_release, /* release */
     NULL,
};
#else
struct file_operations test_fops = {
        owner:          NULL,
        read:           test_read,
        write:          test_write,
        open:           test_open,
        release:        test_release,
};
#endif

#ifdef MODULE

#if 0
int init_module(void)
#else    //new format
int __init firstdriver_init(void)
#endif
{
     MODULE_LICENSE("GPL");
 
     int result = register_chrdev(test_major, "firstdriver", &test_fops);
     if(result < 0)
     {
           printk(KERN_WARNING "testdriver: can't get major %d/n", test_major);
           return result;
     }
     if(test_major == 0)
          test_major = result; /* dynamic */
    }

#if 0
void cleanup_module(void)
#else    // new format
void __exit firstdriver_exit(void)
#endif
{
    unregister_chrdev(test_major, "firstdriver");
}

// new format
module_init(firstdriver_init);
module_exit(firstdriver_exit);


#endif  /* end of MODULE */

/* firstdriver.c  结束 */

/*test.c 测试程序 起始*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
     int testdev;
     int i;
     char buf[10];
     testdev = open("/dev/firstdriver", O_RDWR);
     if(testdev == -1)
    {
          printf("can't open file/n");
          exit(0);
    }
 
     read(testdev, buf, 10);
     for(i=0; i<10; i++)
          printf("%d", buf[i]);
     printf("/n");
     close(testdev);
}
/*test.c 测试程序 结束*/

/* Makefile  起始*/
CC = gcc
FLAGS = -O2 -D__KERNEL__ -DMODULE -I /usr/src/linux-2.4/include

all : firstdriver.o   test

# build the driver
firstdriver.o : firstdriver.c
    $(CC) $(FLAGS) -c firstdriver.c

# build the test program
test : test.o
    $(CC) -o test test.o
test.o :test.c
    $(CC) -c test.c

clean:
     @-rm -f firstdriver.o
     @-rm -f test.o test
/* Makefile 结束 */

/* load.sh  加载脚本 起始*/
# !/bin/sh
module="firstdriver"
device="firstdriver"

/sbin/insmod  ${module}.o

major=`cat /proc/devices | awk "//$2==/"$module/" {print //$1}"`
#注,此处是`(~那个键),而不是'(单引号)
rm  -f  /dev/${device}
mknod  /dev/${device}  c  $major 0
/* load.sh  加载脚本 结束*/

/* unload.sh  卸载脚本 起始*/
# !/bin/sh
module="firstdriver"
device="firstdriver"

/sbin/rmmod  ${module}

# Remove  device file
rm  -f  /dev/${device}
/* unload.sh  卸载脚本 结束*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值