简单的LINUX字符设备驱动及编译进Linux内核

转载 2016年06月01日 00:27:40

简单的LINUX字符设备驱动及编译进Linux内核…  

2010-07-06 11:23:00|  分类: 嵌入式linux|举报|字号 订阅

驱动代码:

 

#include <linux/init.h>
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/fcntl.h>
#include <asm/system.h>
#include <asm/uaccess.h>


#ifndef MODULE
#define MOD_INC_USE_COUNT
#define MOD_DEC_USE_COUNT
#endif


#define MAJOR_NUM 253

MODULE_LICENSE("GPL");

 

int dev_test_open(struct inode *, struct file *);
ssize_t dev_test_read(struct file *, char *, size_t, loff_t *);
ssize_t dev_test_write(struct file *, const char *, size_t, loff_t *);
int dev_test_release(struct inode *, struct file *);

struct file_operations hello_fops =
{
        open:dev_test_open,
        read:dev_test_read,
        write:dev_test_write,
        release:dev_test_release,
};

char *pBuff;

 

static int __init dev_test_init(void)
{
    printk("<1>hello dev test\r\n");
   
    if (register_chrdev(MAJOR_NUM, "dev_test", &hello_fops))
        printk("<1>register failed\r\n");

    return 0;
}

static void __exit dev_test_exit(void)
{
    printk("<1>bye dev_test\r\n");
   
    if (unregister_chrdev(MAJOR_NUM, "dev_test"))
        printk("<1>unregiter failed\r\n");
}

int dev_test_open(struct inode *pInode, struct file *pFile)
{
    pBuff = (char*)kmalloc(128, GFP_KERNEL);

    if (pBuff == NULL)
        printk("<1>kmalloc memory failed\r\n");

    return 0;
}

int dev_test_release(struct inode *pInode, struct file *pFile)
{
    kfree(pBuff);
    return 0;
}

ssize_t dev_test_read(struct file *pFile, char *buff, size_t len, loff_t *pOff)
{
    if (copy_to_user(buff, pBuff, len))
    {

        printk("<1>copy_from_user failed\r\n");
        return -EFAULT;
    }

    return len;
}

ssize_t dev_test_write(struct file *pFile, const char *buff, size_t len, loff_t *pOff)
{
    int i = 0;

    if (copy_from_user(pBuff, buff, len))
    {
        printk("<1>copy_to_user failed\r\n");
        return -EFAULT;
    }
   
    while (pBuff[i] != '\0')
    {
        if (pBuff[i] > 0x40 && pBuff[i] < 0x60)
            pBuff[i] += 0x20;
        else if (pBuff[i] > 0x60 && pBuff[i] < 0x80)
            pBuff[i] -= 0x20;

        i++;
    }

    return len;
}


module_init(dev_test_init);


module_exit(dev_test_exit);

=========================================================

把该代码保存为/usr/local/src/linux-2.x.x/driver/char/dev_test.c

(假设内核代码的目录为/usr/local/src/linux-2.x.x)

=========================================================

下面就是编译模块,按动态加载和静态加载进内核分为两种编译模式.

(1) 动态加载到内核模式,这个比较简单, 但是uClinux不支持这种方式, 所以以linux为例.

    A. 用 gcc -D__KERNEL__ -DMODULE -DLINUX -I /usr/local/src/linux-2.x.x/include -c -o dev_test.o dev_test.c

    B. 在/usr/local/src/linux-2.x.x/driver/char/上用shell 输入 insmod dev_test.o

    C. 在shell上使用 mknod /dev/dev_test c 253 0 创建设备文件

到这里就搞定了, 用户就可以在用户层使用open read write 等函数对"/dev/dev_test"这个文件进行操作, 内核就会调用相应的函数处理用户层的请求.

当用户不需要使用这个驱动模块时,可以用rmmod dev_test进行卸载.

--------------------------------------------------------------------------------------------------------

(2) 静态编入内核,通过 这种方法编译的,只要内核一启动,模块就会自动加载到内核

    A. 在/usr/local/src/linux-2.x.x/driver/char/下的Makefile文件中加入以下代码

        ifeq ($(CONFIG_DEV_TEST),y)
            obj-y += dev_test.o

        endif

    B. 在/usr/local/src/linux-2.x.x/driver/char/下的Makefile文件中加入以下代码

        bool 'support for dev_test' CONFIG_DEV_TEST y

        如果没有该文件, 就在/usr/local/src/linux-2.x.x/arch/xxxnommu/目录下的config.in文件中的字符驱动部分加入.

    C. 在shell上使用mknod /dev/dev_test c 253 0 创建设备文件

        (如果是uClinux, 则使用mknod /xxx/romdist/dev/dev_test c 253 0, /xxx/romdist为嵌入式文件系统的目录)

    D. 编译固件和文件系统镜像后烧到目标版上就可以了.

===========================================================

下面是用户层的应用程序代码, 它使用open, read, write等函数来调用内核实现的驱动代码.

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main()
{
        int fd;
        char buff[128];

        fd = open("/dev/dev_test", O_RDWR);

        while(1)
        {
                printf("enter the string:");
                scanf("%s", buff);

                write(fd, buff, 128);

                memset(buff, 0, 128);

                read(fd, buff, 128);

                printf("%s\r\n", buff);
        }
        return 0;
}

相关文章推荐

Linux内核编程七:字符设备驱动

个人总结PDF截图,特此声明!

Linux内核学习-字符设备驱动学习(一)

Linux内核学习-字符驱动学习(一) 现在学习一下Linux的字符设备驱动,参考的样本应该就是ldd3这书大概第3章的内容吧。下面的所说的字符设备都是基于2.6内核的,一般的流程都是,呵呵,其实也不...

Linux内核学习-字符设备驱动学习(二)

在Linux内核学习-字符设备驱动学习(一)中编写字符设备驱动的一种方法,但是需要手动创建设备节点。有没有能够自动的创建设备节点的呢?有!使用class_create()和device_create(...

Linux内核分析(五)----字符设备驱动实现

Linux内核分析(五) 昨天我们对linux内核的子系统进行简单的认识,今天我们正式进入驱动的开发,我们今后的学习为了避免大家没有硬件的缺陷,我们都会以虚拟的设备为例进行学习,所以大家不必害怕没有...

linux内核字符设备驱动相关的函数以及结构体

1. struct cdev {          struct kobject kobj;          struct modul...

Linux2.6内核下简单的字符设备驱动及测试

Linux2.6内核下的简单字符设备 1.自定设备符结构体 struct VirtualDisk{  struct cdev cdev;  unsigned char mem[VIRTUALD...

[linux设备驱动程序]scull字符设备驱动编译在新内核编译问题解决方案

最近在看《LINUX设备驱动程序》,给出的字符设备驱动程序scull,在linux 2.6.32-22内核上make编译时出现了下面的问题:make -C /lib/modules/2.6.32-22...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)