2017-04-21 3 views
0

my_moduleという名前のcharドライバを作成しようとしています。私は初めてのデバイスのファイルを開く場合私のcharドライバを使用中にセグメンテーションエラーが発生しました

  • は、私は「PRIVATE_DATA」フィールドデバイスのファイルで、構造体のためのメモリ を割り当てています:私は次のように行動したいすべてのデバイスのための後で指し示す。

  • 私はその後、デバイスのファイルを開くと、私は「PRIVATE_DATA」のポイントへ

問題と同じ構造体を使用し続ける:私は二度目のファイルを開いたとき、私はセグメンテーションを持っています失敗。私が "open"を使うたびにstructのメモリを再割り当てすると、エラーは発生しません。

どうしたのですか?

/* my_module.c: Example char device module. 
    * 
    */ 
    /* Kernel Programming */ 
    #define MODULE 
    #define LINUX 
    #define __KERNEL__ 

    #include <linux/kernel.h> 
    #include <linux/module.h> 
    #include <linux/fs.h>    
    #include <asm/uaccess.h> 
    #include <linux/errno.h> 
    #include<linux/slab.h> /* included for the purpose of using kmalloc and kfree */ 

    #include "my_module.h" 

    #define CAN_READ 1 

    #define CANT_READ -1 

    #define CAN_WRITE 1 

    #define CANT_WRITE -1 

    #define MY_DEVICE "my_device" 

    MODULE_LICENSE("GPL"); 
    MODULE_AUTHOR("Anonymous"); 

    #define BUF_LEN 4096 


    /* globals */ 
    int my_major = 0; /* will hold the major # of my device driver */ 
    int can_read = CANT_READ; 
    int can_write = CANT_WRITE; 
    char * buffp = NULL; 




    struct file_operations my_fops = { 
    .open = my_open, 
    .release = my_release, 
    .read = my_read, 
    .write = my_write, 
    .ioctl = my_ioctl, 
    .owner = THIS_MODULE 
    }; 

    typedef struct driver_t { 
    int can_read; 
    int can_write; 
    int curr_index_write_d; 
    int curr_index_read_d; 
    char * d_ptr; 
    } Driver; 



    Driver * driverCreate(char * buffer, int can_read_arg, int can_write_arg) { 

    Driver * driver = (Driver*)kmalloc(sizeof(*driver),GFP_KERNEL); 

    if(!driver){ 
     return NULL; 
    } 
    driver->curr_index_write_d=0; 
    driver->curr_index_read_d=0; 
    driver->d_ptr=buffer; 
    driver->can_read=can_read_arg; 
    driver->can_write=can_write_arg; 
    return driver; 
    } 










    int init_module(void) 
    { 
    //printk(KERN_WARNING "start of module! "); 
    my_major = register_chrdev(my_major, MY_DEVICE, &my_fops); 

    if (my_major < 0) 
    { 
    //printk(KERN_WARNING "can't get dynamic major\n"); 
     return my_major; 
    } 

    // 
    // do_init(); 
    // 
    return 0; 
    } 


    void cleanup_module(void) 
    { 
    //printk(KERN_WARNING "end of module! "); 
    unregister_chrdev(my_major, MY_DEVICE); 

    // 
    // do clean_up(); 
    // 
    return; 
    } 


    int my_open(struct inode *inode, struct file *filp) 
    { 
    if(MOD_IN_USE>1) { 
     return 0; 
    } 
    if (filp->f_mode & FMODE_READ) 
    { 
     can_read = CAN_READ; 

    } 

    if (filp->f_mode & FMODE_WRITE) 
    { 
     can_write = CAN_WRITE; 
    } 
    char * ptr = kmalloc(BUF_LEN, GFP_KERNEL); 
    if (!ptr) { 
     return my_major; 
    } 
    Driver * driver = driverCreate(ptr,can_read,can_write); 
    if (!driver) { 
     return my_major; 
    } 
    filp->private_data = driver; 
    MOD_INC_USE_COUNT; 
    return 0; 
    } 










    int my_release(struct inode *inode, struct file *filp) 
    { 
     /* 
    if(MOD_IN_USE>1) { 
     printk(KERN_WARNING "\nclose: MOD IN USE: %d\n", (int)MOD_IN_USE); 
     MOD_DEC_USE_COUNT; 
     return 0; 
    } 
    printk(KERN_WARNING "\nclose:(suupose to be 1) MOD IN USE: %d\n", (int)MOD_IN_USE); 
    Driver * d_ptr = (Driver*)(filp->private_data); 
    char * ptr = d_ptr->d_ptr; 

    if (filp->f_mode & FMODE_READ) 
    { 
     d_ptr->can_read = CANT_READ; 
     can_read = CANT_READ; 
    // 
    // handle read closing 
    // 
    } 

    if (filp->f_mode & FMODE_WRITE) 
    { 
     d_ptr->can_write = CANT_WRITE; 
     can_write = CANT_WRITE; 
     // 
     // handle write closing 
     // 
    } 

    if(ptr != NULL) { 
     kfree(ptr); 
     kfree(filp->private_data); 
     filp->private_data=NULL; 
     printk(KERN_WARNING "Memory is now free "); 
    } 
    else { 
     printk(KERN_WARNING "No memory to free "); 
    } 
    */ 
    return 0; 
    } 












    ssize_t my_read(struct file *filp, char *buf, size_t count, loff_t *f_pos) 
    { 

    Driver * d_ptr = (Driver*)(filp->private_data); 
    char * ptr = d_ptr->d_ptr; 

    int curr_index_write = d_ptr->curr_index_write_d; 
    int curr_index_read = d_ptr->curr_index_read_d; 

    if(d_ptr->can_read == CANT_READ) { 
     return 0; 
    } 



    if(curr_index_write - curr_index_read == 0) { 

     return 0; 
    } 

    int length = (count >= (curr_index_write - curr_index_read) ? 
     (curr_index_write - curr_index_read) : count ); 

    copy_to_user((char*)buf,(ptr+curr_index_read),length); 


    d_ptr->curr_index_read_d = curr_index_write; 


    return length; 
    // 
    // Do read operation. 
    // Return number of bytes read. 

    } 


    ssize_t my_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos) 
    { 
    Driver * d_ptr = (Driver*)(filp->private_data); 

    int curr_index_write = d_ptr->curr_index_write_d; 

    char * ptr = d_ptr->d_ptr;  

    if(can_write == CANT_WRITE) { 
     return 0; 
    } 

    if(BUF_LEN < curr_index_write + count) { 
     return -ENOMEM; 
    } 

    copy_from_user((ptr+curr_index_write),(char*)buf,count); 

    d_ptr->curr_index_write_d = curr_index_write + count; 

    return count; 

    // 
    // Do write operation. 
    // Return number of bytes written. 
    } 


    int my_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) 
    { 

    if(filp->private_data==NULL) { 
     return 0; 
    } 
    Driver * d_ptr = (Driver*)(filp->private_data); 

    switch(cmd) 
    { 
     case MY_RESET: 

     d_ptr->curr_index_write_d = 0; 
     d_ptr->curr_index_read_d = 0; 
    // 
    // handle OP 1. 
    // 
     break; 
     case MY_RESTART: 

     d_ptr->curr_index_read_d = 0; 
    // 
    // handle OP 1. 
    // 
     break; 

     default: 
     return -ENOTTY; 
    } 

    return 0; 
    } 
+0

2番目のプロセスが最初のプロセスでオープンされている間にデバイスファイルを開く場合、何が起こる必要があるか考えてください。 – zwol

+0

(あなたのコードを実際に読むことができるようにインデントを修正してください) – zwol

+0

@zwol私は競合状態を起こしたくありません。私はそれを前に閉じてからデバイスを再び開くことができます。前からの構造体 –

答えて

0

代わりのこのライン

driver->d_ptr=buffer; 

d_ptrはcharへのポインタであることを覚えておいてください

driver->d_ptr=strdup(buffer); 

を試してみてください。最初にメモリの割り当てが必要で、それにコピーする必要があります。 strdup()はその仕事をします。

関連する問題