函数指针作为任何设备操作的入口点

时间:2013-11-20 17:48:39

标签: c unix linux-device-driver

/* angus - Simple program to open,release,read,write */
#include<linux/fs.h>
#include<linux/uaccess.h>
#include<linux/slab.h>
#include<linux/gfp.h>

char *my_buff;
int major = -1;

int my_open(struct inode *inodes, struct file *files);
int my_release(struct inode *inodes, struct file *files);
ssize_t my_read(struct file *file, char __user *buf, size_t len, loff_t *ppos);
ssize_t my_write(struct file *file, const char __user *buf, size_t len, loff_t *ppos);

static const struct file_operations fops = {
        .open = my_open,
        .release = my_release,
        .read = my_read,
        .write = my_write
};


int init_module(void){
        printk("Hi Angus \n");
        major = register_chrdev(0,"hello",&fops);
        printk("Major no : %d \n",major);
        return 0;
}

void cleanup_module(void){
        kfree(my_buff);
        unregister_chrdev(major,"hello");
        printk("Bye Angus \n");
}

int my_open(struct inode *inodes, struct file *files){
        printk("my_open Angus \n");
        return 0;
}

int my_release(struct inode *inodes, struct file *files){
        printk("my_release Angus \n");
        return 0;
}

ssize_t my_read(struct file *file, char __user *buf, size_t len, loff_t *ppos){
        if(copy_to_user(buf,my_buff,len)){ // On success returns 0 and failure returns no of bytes not copied
                return -1;
        }
        printk("my_read Angus \n");
        return len;
}

ssize_t my_write(struct file *file, const char __user *buf, size_t len, loff_t *ppos){
        ssize_t size = len;
        my_buff = kmalloc(100,GFP_KERNEL);
        if(copy_from_user(my_buff,buf,len)){
                return -1;
        }
        printk("my_write Angus \n");
        return size;
}

/* Output */

/* Step : 1 
[ 9079.100187] Hi Angus 
[ 9079.100193] Major no : 250 
[ 9081.321078] my_open Angus 
[ 9081.321157] my_read Angus 
[ 9081.321170] my_write Angus 
[ 9081.321206] my_release Angus 
[ 9131.037905] Bye Angus 
*/

/*Step : 2
mknod hello c 250 0
$cat /proc/devices
*/

我尝试了上面的程序来理解在驱动程序级别发生的读取,写入入口点。

  1. 但是我无法从调用my_read的read()函数指针到达的地方调用。
  2. 为什么始终使用函数指针写入入口点?

1 个答案:

答案 0 :(得分:2)

  1. 您的register_chrdev功能中有init_module个问号。这将函数指针的结构fops传递给内核。 fops的其中一个字段read已初始化为my_read
  2. 因为它是一种间接功能的干净机制,相当于C ++虚拟表。内核如何与您的设备驱动程序通信以请求它进行读/写?内核可以传递一个函数代码(0 =读,1 =写)但函数指针机制更直接。由于大多数设备都支持开放,读取和写入,因此将它们作为函数指针实现它们更直接,代码更少。话虽如此,ioctl允许您将功能代码发送到设备驱动程序,但这通常是最好的避免,除非您的设备驱动程序实现的操作不能很好地建模为打开,读取,写入等。