2014-04-03 74 views
0

我想爲我的內核程序做一個讀取功能。首先用戶必須輸入一些數字(輸入數字0停止輸入)。數字輸入已經完成了我的工作是做閱讀功能。讀取功能必須跟蹤輸入的數量,並且它具有一個緩衝器,其中包含自模塊激活後輸入的數字。 我一直在從summer.c中讀取緩衝區和chars數到test-summer.c並打印它們。Linux內核讀取功能

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文件中,您沒有爲緩衝區分配內存並將其傳遞給讀取函數。這可能是你沒有得到正確的返回值,也沒有得到你想要的數據填充緩衝區的原因。