2013-11-20 2 views
0
/* 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. 엔트리 포인트가 항상 함수 포인터를 사용하여 쓰여지는 이유는 무엇입니까?

답변

2
  1. 당신은 당신의 init_module 기능에 register_chrdev을 callng 있습니다. 함수 포인터의 구조 fops이 커널에 전달됩니다. fops 필드 중 하나는 my_read으로 초기화 된 read입니다.
  2. 기능의 간접 참조를위한 깨끗한 메커니즘이므로 C++ 가상 테이블과 동일합니다. 커널이 장치 드라이버와 통신하여 읽기/쓰기를 요청하는 다른 방법은 무엇입니까? 커널은 함수 코드 (0 = 읽기, 1 = 쓰기)를 전달할 수 있지만 함수 포인터 메커니즘은보다 직접적입니다. 대부분의 장치는 열기, 읽기 및 쓰기를 지원할 것으로 예상되므로 함수 포인터로 구현하는 것이 더 직접적이고 코드가 적습니다. 그렇지만 ioctl을 사용하면 기능 코드를 장치 드라이버에 보낼 수 있지만 일반적으로 장치 드라이버 구현이 열기, 읽기, 쓰기 등으로 모델화 할 수없는 경우가 아니면이 방법을 피하는 것이 가장 좋습니다.
관련 문제