1、字符设备两种驱动框架

 

 2、实现file_operation后,如何告诉内核?

实际上就是把file_ops注册到内核:major = register_chrdev(0, "first_drv", &first_drv_fops); // 注册, 告诉内核

例如内核实际上有一个很大的数组,把fops放到空的数组中的某一个项中,然后返回下标(主设备号)。

major = register_chrdev(0, "first_drv", &first_drv_fops); // 注册, 告诉内核

firstdrv_class = class_create(THIS_MODULE, "firstdrv");

firstdrv_class_dev = class_device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xyz"); /* /dev/xyz */return 0;

 

 

3、写一个hello程序

#include <linux/module.h>

#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>

//1、确定主设备号
static int major;
static char kernel_buff[1024];
struct class hello_class;
#define MIN(a,b)    (a<b?a:b)

//3、实现fops
int hello_drv_open (struct inode *node, struct file *filep)
{
    printf("%s %s line %d\n",__FILE__,__FUNCTION__,__LINE__);
}
int hello_drv_release (struct inode *node, struct file *filep)
{
    printf("%s %s line %d\n",__FILE__,__FUNCTION__,__LINE__);
}
ssize_t hello_drv_write (struct file *file, char __user *buff, size_t size, loff_t * offet)
{
    printf("%s %s line %d\n",__FILE__,__FUNCTION__,__LINE__);
    copy_from_user(kernel_buff, buff, MIN(size,1024));
    return MIN(size,1024);
}
ssize_t hello_drv_read (struct file *file, const char __user * buf, size_t size, loff_t * offset)
{
    printf("%s %s line %d\n",__FILE__,__FUNCTION__,__LINE__);
    copy_to_user(buff,, kernel_buff, MIN(1024,size));
    return MIN(size,1024);
}


//2、定义自己的fops
static struct file_operations hello_drv ={
    .owner        = THIS_MODULE,
    .open        = hello_drv_open,
    .read        = hello_drv_read,
    .write        = hello_drv_write,
    .release    = hello_drv_release,
}


static int __init hello_init(void)
{
    major=register_chrdev(0,"hello", &hello_drv);
    class_create(THIS_MODULE,"hello_class");
    device_create(hello_class,NULL,MKDEV(major,0),NULL,"hello");//dev/hello
    return 0;
}

static void __exit hello_exit(void)
{
    unregister_chrdev(major, "hello");
    class_destroy(hello_class);
    unregister_chrdev(major,"hello");
}

MODULE_LICENSE("GPL");

用户态:

int main(int argc, char **argv)
{
    int fd;
    char buf[1024];
    int len;
    
    if(argc <2)
    {
        printf("usage:%s -w <string>\n",argv[0]);
        printf("      %s -r\n",argv[0])
        return -1;
    }
    
    fd=open("/dev/hello",O_RDWR);
    if(fd == -1)
    {
        printf("can not open file\n");
        return -1;
    }
    
    if((0==strcmp(argv[1],"-w")) && (argc == 3))
    {
        len=strlen(argv[2])+1;
        len = len < 1024 ? len:1024;
        write(fd, argv[2],len);
    }
    else
    {
        len = read(fd, buf, 1024);
        buf[1023]='\0';
        printf("APP read: %s\n", buf);
    }
    
    close(fd);
}

 

 

KERN_DIR = /home/...

all:
    make -C $(KERN_DIR) M=`pwd` modules
clean:
    make -C $(KERN_DIR) M=`pwd` clean