欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

linux下字符驱动示例helloworld

程序员文章站 2022-07-14 09:46:18
...

1:最简单的驱动框架

hello.c

/*************************************************************************
    > File Name: hello.c
    > Author: kayshi
    > Mail: aaa@qq.com
    > Created Time: Thu 24 Sep 2020 11:25:50 AM CST
 ************************************************************************/

#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>

static int hello_init(void)
{
    printk("this is hello\n");
    return 0;
}

static void hello_exit(void)
{
    printk("this is end\n");
}
MODULE_LICENSE("GPL");
module_init(hello_init);
module_exit(hello_exit);

Makefile

ifneq ($(KERNELRELEASE),)
obj-m:=hello.o
$(info "2nd")
else
KDIR := /lib/modules/$(shell uname -r)/build
PWD:=$(shell pwd)
all:
    $(info "1st")
    make -C $(KDIR) M=$(PWD) modules
clean:
    rm -f *.ko *.o *.symvers *.mod.c *.mode.o *.order
endif

加载:
sudo insmod hello.ko

查看:
lsmod
linux下字符驱动示例helloworld
删除:
sudo rmmod hello

查看打印信息:
demsg
linux下字符驱动示例helloworld

2:进行字符设备注册

补全代码hello.c

/*************************************************************************
    > File Name: hello.c
    > Author: kayshi
    > Mail: aaa@qq.com
    > Created Time: Thu 24 Sep 2020 11:25:50 AM CST
 ************************************************************************/

#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>

static int major = 300;
static int minor = 0;
static dev_t devno;
static struct cdev cdev;


static int hello_open(struct inode *inode, struct file *filep)
{
    printk("hello open\n");
    return 0;
}

static struct file_operations hello_ops=
{
    .open = hello_open,
};

static int hello_init(void)
{
    int ret;

    printk("hello_init\n");
    devno = MKDEV(major, minor);
    ret = register_chrdev_region(devno, 1, "hello");
    if(ret < 0)
    {   
        printk("register_chrdev_region faile\n");
                return ret;
    }
    cdev_init(&cdev, &hello_ops);
    ret = cdev_add(&cdev, devno, 1);
    if(ret < 0)
    {
        printk("cdev_add faile \n");
        return ret;
    }
    return 0;
}

static void hello_exit(void)
{
    cdev_del(&cdev);
    unregister_chrdev_region(devno, 1);
    printk("hello_exit\n");
}
MODULE_LICENSE("GPL");
module_init(hello_init);
module_exit(hello_exit);

编译执行后
查看信息
cat /proc/devices

linux下字符驱动示例helloworld

如果再insmod时出现了下面的情况
linux下字符驱动示例helloworld
这是因为代码中的主设备号已经被使用了。把设备号改大一点就行

此时/dev/没有出现设备
需要通过命令

sudo mknod /dev/hello c 300 0

来创建设备,再查看
linux下字符驱动示例helloworld

测试代码

/*************************************************************************
    > File Name: test.c
    > Author: kayshi
    > Mail: aaa@qq.com
    > Created Time: Thu 24 Sep 2020 02:47:37 PM CST
 ************************************************************************/

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

void main()
{
    int fd; 

    fd = open("/dev/hello", O_RDWR);
    if(fd < 0)
    {   
        perror("open faile \n");
        return ;
    }   
    close(fd);
}

执行测试代码后
再用dmesg查看log信息
linux下字符驱动示例helloworld
hello open被打印,说明hello_open这个函数被调用了

3 添加读写操作

在驱动中添加读写函数。重新生成并insmod

/*************************************************************************
    > File Name: hello.c
    > Author: kayshi
    > Mail: aaa@qq.com
    > Created Time: Thu 24 Sep 2020 11:25:50 AM CST
 ************************************************************************/

#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>

static int major = 300;
static int minor = 0;
static dev_t devno;
static struct cdev cdev;

static ssize_t hello_write(struct file *f, const char __user *u, size_t s, loff_t *l)
{   
    printk("hello write");
    return 0;
}

static ssize_t hello_read(struct file *f, char __user *u, size_t s, loff_t *l)
{   
    printk("hello read");
    return 0;
}

static int hello_open(struct inode *inode, struct file *filep)
{   
    printk("hello open\n");
    return 0;
}

static struct file_operations hello_ops=
{   
    .open = hello_open,
    .write = hello_write
    .read = hello_read,
};

static int hello_init(void)
{
    int ret;

    printk("hello_init\n");
    devno = MKDEV(major, minor);
    ret = register_chrdev_region(devno, 1, "hello");
    if(ret < 0)
    {
        printk("register_chrdev_region faile\n");
        return ret;
    }
    cdev_init(&cdev, &hello_ops);
    ret = cdev_add(&cdev, devno, 1);
    if(ret < 0)
    {
        printk("cdev_add faile \n");
        return ret;
    }
    return 0;
}

static void hello_exit(void)
{
    cdev_del(&cdev);
    unregister_chrdev_region(devno, 1);
    printk("hello_exit\n");
}
MODULE_LICENSE("GPL");
module_init(hello_init);
module_exit(hello_exit)

在测试代码中添加读写测试


/*************************************************************************
    > File Name: test.c
    > Author: kayshi
    > Mail: aaa@qq.com
    > Created Time: Thu 24 Sep 2020 02:47:37 PM CST
 ************************************************************************/

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

void main()
{
    int fd; 
    char buf[8] = {0};

    fd = open("/dev/hello", O_RDWR);
    if(fd < 0)
    {   
        perror("open faile \n");
        return ;
    }   
    write(fd, buf, sizeof(buf));
    read(fd, buf, sizeof(buf));

    close(fd);
}

dmesg查看信息
linux下字符驱动示例helloworld
读写函数的打印信息都出现了

相关标签: linux driver