2014-04-03 5 views
0

커널 프로그램을 읽기 위해 노력하고 있습니다. 먼저 사용자가 숫자를 입력해야합니다 (입력 번호 0은 입력을 중지합니다). 숫자 입력은 이미 저에게 제 일은 읽기 기능을 만드는 것이 었습니다. 읽기 기능은 입력 된 숫자의 양을 추적해야하며 모듈이 활성화 된 이후 입력 된 숫자가있는 버퍼가 있습니다. summer.c에서 읽은 버퍼 및 문자 수를 test-summer.c로 가져 와서 인쇄합니다.리눅스 커널 읽기 기능

Summer.c 코드 :

/* example of a character device using ioctl 
    */ 

    #include <linux/kernel.h> 
    #include <linux/module.h> 
    #include <linux/errno.h> 
    #include <linux/fs.h> 
    #include <asm/uaccess.h> 
    #include "summer.h" 

    #define BUF_LEN 80   /* Max length of the message from the device */ 

    /* the memory of the device*/ 
    int total; 

    /* Global variables declared as staic, so are global within the file.*/ 
    static char *msg_Ptr; 
    static char msg[BUF_LEN]; 

    /* called after the device is opened*/ 
    int device_open(struct inode *inode, struct file *file) 
    { 
    printk("\nsummer device is open\n"); 
    total = 0; 

    // sprintf(msg); 
    printk(msg); 
    msg_Ptr = msg; 

    return 0; 
    } 

    /* called after the device is closed 
    */ 
    int device_close(struct inode *inode, struct file *file) 
    { 
    printk("\nsummer device is closed\n"); 
    return 0; 
} 

/* handling of ioctl events 
*/ 
long device_ioctl(struct file *file, unsigned int ioctl_num, unsigned long ioctl_param) 
{ 
    int number; 
    switch(ioctl_num) 
    { 
    case SUMMER_SET: 
     __get_user(number, (int*)ioctl_param); 
     total += number; 
     break; 
    case SUMMER_GET: 
     __put_user(total, (int*)ioctl_param); 
     break; 
    } 
    return 0; 
} 

/* Read function */ 
static ssize_t device_read(struct file *filep, char *buffer, size_t length, loff_t *offset){ 

/* Number of bytes actually written to the buffer */ 
int bytes_read = 0; 

/* If we're at the end of the message, return 0 signifying end of file */ 
if (*msg_Ptr == 0) return 0; 

/* Actually put the data into the buffer */ 
while (length && *msg_Ptr) { 

    /* The buffer is in the user data segment, not the kernel segment; 
     * assignment won't work. We have to use put_use which copies data from 
     * the kernel data segment to the user data segment. */ 
    put_user(*(msg_Ptr++), buffer++); 

    length--; 
    bytes_read++; 
} 
/* Most read functions return the number of bytes put into the buffer */ 
return bytes_read; 
} 


/* table of event handlers of the device 
*/ 
struct file_operations fops = 
{ 
    read: device_read, 
// write: device_write, 
    open: device_open, 
    release: device_close, 
    unlocked_ioctl: device_ioctl, 
    compat_ioctl: device_ioctl 
}; 

/* called after the kernelmodule is opened 
*/ 
int init_module(void) 
{ 
/* register the device 
    ** after registration the device is known to linux by its major number 
    ** example: mknod /dev/summer0 c 240 0 
    ** this creates the device /dev/summer0 
    ** which is a character device (c) with major number 240 and minor number 0 
    */ 
    int retval = register_chrdev(MAJOR_NUM, DEVICE_NAME, &fops); 
    if(retval < 0) 
    { 
    printk("character device not registered\n"); 
    return retval; 
    } 
    printk("summer kernel module loaded\n"); 
    return 0; 
} 

/* called after the module is closed 
*/ 
void cleanup_module(void) 
{ 
/* unregister the device 
    */ 
    unregister_chrdev(MAJOR_NUM, DEVICE_NAME); 
    printk("summer kernel module unloaded\n"); 
} 

테스트 - summer.c 코드

/* example of use of a character device through ioctl 
*/ 

#include <stdio.h> 
#include <fcntl.h> 
#include <sys/ioctl.h> 
#include "../summer.h" 

int main(void) 
{ 
    int sum; 
    char* buffer; 
    /* open character device */ 
    int fd = open("/dev/summer0", O_RDWR); // open device 
    if(fd < 0) 
    { 
    printf("no device found\n"); 
    return; 
    } 
    /* read from device */ 
    int nc = read(fd,buffer,4,0); 

    for(;;) 
    { 
    int num; 
    printf("Number (exit with 0) = "); 
    while(scanf("%d", &num) != 1) 
     ; 
    printf("-- %d --\n", num); 
    if(num <= 0) break; 

    /* use ioctl to pass a value to the character device  */ 
    ioctl(fd, SUMMER_SET, &num); 
    } 

    /* use ioctl to get a value from the character device */ 
    ioctl(fd, SUMMER_GET, &sum); 
    printf("Result = %d\n", sum); 

    /* print num of chars + the buffer as a string with the amount of numbers read since the kernel is active. */ 
    printf("#char = %d\n", nc); 
    printf("Buffer: %s\n" , buffer); 

    close(fd);       // close device 
    return 0; 
} 
+0

simple_read()를 사용하지 않는 이유가 있습니까? –

+0

내가 이것을 읽는 이유는 인터넷에서이 함수를 가진 예제를 발견했다는 것입니다 – Sybren

답변

0

그것은 오래된 질문이지만 답을 마칠 수있었습니다.

test-summers.c 파일에서 버퍼에 메모리를 할당하지 않았으며 읽기 기능에 전달했습니다. 이것이 반환 값이 정확하지 않고 버퍼가 원하는 데이터로 채워지지 않는 이유입니다.