2012-01-28 23 views
2

私は次のコードを何度も試してみました。カーネルモジュールからのデバイスファイルへの書き込みと読み取りのコードは?

#include<linux/module.h> 
#include<linux/kernel.h> 
#include<linux/fs.h> 
#include<linux/cdev.h> 
#include<asm/uaccess.h> 
#include<linux/semaphore.h> 

MODULE_LICENSE("DUAL BSD/GPL"); 
static int dev_open(struct inode *,struct file *); 
static int dev_release(struct inode *,struct file *); 
ssize_t dev_read(struct file *,char *, size_t ,loff_t *); 
ssize_t dev_write(struct file *,const char *,size_t ,loff_t *); 

static int major; 
int dev_major = 0; 
int dev_minor = 0; 
struct cdev *cdev; 

struct device { 
    char array[100]; 
    struct semaphore sem; 
}chr_arr; 

struct file_operations dev_ops = { 
    .owner = THIS_MODULE, 
    .read = dev_read, 
    .write = dev_write, 
    .open = dev_open, 
    .release = dev_release 
}; 

ssize_t dev_read(struct file *filp,char *buf,size_t count,loff_t *offset) 
{ 
    int i; 
    i=copy_to_user(buf,chr_arr.array,count); 
    printk(KERN_ALERT"buff:%s",buf); 
    return i; 
} 

ssize_t dev_write(struct file *filp,const char *buf,size_t count,loff_t *offset) 
{ 
    //printk(KERN_ALERT"\nsorry,byebye"); 
    int j; 
    //msg_ptr = kmalloc(count,GFP_KERNEL); 
    //for(j=0;j<count;j++) 
    if(count>100) 
     return -1; 
    j = copy_from_user(chr_arr.array,buf,count); 
    //printk(KERN_ALERT"msg_ptr:%s",msg_ptr); 
    return j; 
} 

static int dev_open(struct inode *inode,struct file *filp) 
{ 
    filp->private_data = inode->i_cdev; 
    if(down_interruptible(&chr_arr.sem)) 
    { 
     printk(KERN_INFO " could not hold semaphore"); 
     return -1; 
    } 
    //printk(KERN_ALERT"ah ha the device is open !now we can go further"); 
    return 0; 
} 

static int dev_release(struct inode *inode,struct file *filp) 
{ 
    up(&chr_arr.sem); 
    //module_put(THIS_MODULE); 
    return 0; 
} 

static int init_device(void) 
{ 
    int result; 
    dev_t dev_no,dev; 
    result = alloc_chrdev_region(&dev_no,0,1,"chr_dev"); 
    if(result < 0) 
    { 
     printk("sorry no major number left"); 
     return result; 
    } 
    major = MAJOR(dev_no); 
    dev = MKDEV(major,0); 
    cdev = cdev_alloc(); 
    cdev->ops = &dev_ops; 
    sema_init(&chr_arr.sem,1); 
    printk("the major number allocated is %d\n",major); 
    result = cdev_add(cdev,dev,1); 
    if(result < 0) 
    { 
     printk(KERN_INFO "Unable to allocate cdev"); 
     return result; 
    } 
    return 0; 
} 

static void clean_device(void) 
{ 
    cdev_del(cdev); 
    unregister_chrdev_region(major,1); 
} 

module_init(init_device); 
module_exit(clean_device); 

しかし、次の警告が表示されます。

CC [M] /home/karan/practice/scrw/scrw1.o 
In file included from /usr/src/linux-2.6.34.10-0.6/arch/x86/include/asm/uaccess.h:571:0, 
      from /home/karan/practice/scrw/scrw1.c:4: 
In function ‘copy_from_user’,inlined from ‘write’ at /home/karan/practice/scrw/scrw1.c:43:6: 
/usr/src/linux-2.6.34.10-0.6/arch/x86/include/asm/uaccess_32.h:212:26: warning: call to ‘copy_from_user_overflow’ declared with attribute warning: copy_from_user() buffer size is not provably correct 
Building modules, stage 2. 
MODPOST 1 modules 
CC  /home/karan/practice/scrw/scrw1.mod.o 
LD [M] /home/karan/practice/scrw/scrw1.ko 

、その後、私は30秒ほど後にエコーハイ>は/ dev/my_dev画面がフリーズを書いてみます。

+2

カウント<100でテストしないでください。 – ypnos

+0

@ypnos thats okしかし、私はechoコマンドを置くたびに動作しません。数秒後にハングします.... – karan421

+0

問題は恐らくどこかにあります。もっとコードを表示できますか?また、デバッグオプションを有効にしてカーネルを再コンパイルしてみると、フリーズが発生したときにスタックトレースが得られる可能性があります。 – ldx

答えて

6

問題は、読み取り/書き込みメソッドで読み書きされたバイト数を返す必要があることです。すべてがうまくいくと、copy_ {from、from} _user()の戻り値は0になります。例:コピーが成功した場合、あなたの書き込み方法でカウント:

unsigned long ret; 
printk(KERN_INFO "Inside write \n"); 
if (count > sizeof(char_arr.array) - 1) 
    return -EINVAL; 
ret = copy_from_user(char_arr.array, buff, count); 
if (ret) 
    return -EFAULT; 
char_arr.array[count] = '\0'; 
return count; 

また、確認する必要があり、その終端の「\ 0」(あなたが文字列でのみ対処したい場合)、あなたのバッファにコピーしたときに文字が追加されます。バイナリデータの場合は、構造体の長さも格納します。

例読み取る方法:

ssize_t dev_read(struct file *filp,char *buf,size_t count,loff_t *offset) 
{ 
    int len = count >= strlen(chr_arr.array) ? strlen(chr_arr.array) : count; 

    if (*offset >= strlen(chr_arr.array)) 
     return 0; 

    if (copy_to_user(buf,chr_arr.array,len)) 
     return -EFAULT; 

    return len; 
} 

編集:それを固定し、コード例を台無し。

Edit2:読み取り方法の例。

+0

関数私はcat/dev/my_devを使用するたびに、私は読み返してカウントアップしていますが、それも..... .....助けてください。 – karan421

+0

あなたは一度ユーザーを返すべきですあなたのデバイスの終わりに到達します。オフセットを使用して現在の位置を保存することができます。 – ldx

+0

私はデバイスファイルの末尾に移動しないでください(私は間違っている場合は私を修正してください)....とどのように私はオフセットを使用することができますすべてのユーザーがハイ(エコーhi>/dev/my_dev)あなたはコードで私を見せてくれますか...本当に熱意と関心をお寄せいただきありがとうございます。 – karan421

関連する問題