Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 为什么这个字符驱动程序总是只复制一个字节?_C_Linux_Linux Device Driver - Fatal编程技术网

C 为什么这个字符驱动程序总是只复制一个字节?

C 为什么这个字符驱动程序总是只复制一个字节?,c,linux,linux-device-driver,C,Linux,Linux Device Driver,我在摆弄一个scull驱动程序代码,然后又试图让它打印输入的所有字符,而不是一个。即: # insmod memory.ko # chmod 666 /dev/memory $ echo -n abcdef >/dev/memory $ cat /dev/memory 应该打印abcdef,但只打印f 为此,我对scull代码进行了如下修改: ssize_t memory_read(struct file *filp, char *buf, si

我在摆弄一个scull驱动程序代码,然后又试图让它打印输入的所有字符,而不是一个。即:

# insmod memory.ko
# chmod 666 /dev/memory
$ echo -n abcdef >/dev/memory
$ cat /dev/memory
应该打印abcdef,但只打印f

为此,我对scull代码进行了如下修改:

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

  /* Transfering data to user space */ 
  copy_to_user(buf,memory_buffer,5);

  /* Changing reading position as best suits */ 
  if (*f_pos == 0) { 
    *f_pos+=1; 
    return 1; 
  } else { 
    return 0; 
  }
}

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

  char *tmp;

  tmp=buf+count-1;
  copy_from_user(memory_buffer,tmp,5);
  return 1;
}

int memory_init(void) {
  int result;

  /* Registering device */
  result = register_chrdev(memory_major, "memory", &memory_fops);
  if (result < 0) {
    printk(
      "<1>memory: cannot obtain major number %d\n", memory_major);
    return result;
  }

  /* Allocating memory for the buffer */
  memory_buffer = kmalloc(5, GFP_KERNEL); 
  if (!memory_buffer) { 
    result = -ENOMEM;
    goto fail; 
  } 
  memset(memory_buffer, 0, 5);

  printk("<1>Inserting memory module\n"); 
  return 0;

  fail: 
    memory_exit(); 
    return result;
}
读取未正确执行。它不应该写超过计数字节给用户,他可以有更小的缓冲区。更相关的是,它应该返回写入用户的字节数,并且只有在文件结束时才返回0。它还可以在出现错误时以负数形式返回错误代码,如-EIO

您写入5个字符,但返回1,因此cat认为它是未完成读取,读取1个字节。我再次尝试读取并得到0,所以它将其解释为文件结尾

write也有类似的问题,它还应该检查用户缓冲区的大小和返回的字节数

这或多或少是我为固定大小缓冲区实现读取的方式:

ssize_t memory_read(struct file *filp, char *buf, 
                    size_t count, loff_t *f_pos) { 
  ssize_t retval;

  if(down_interruptible(&sem)) // some mutex is probably necessary
    return -ERESTARTSYS;
  count = MIN(count, MEMORY_SIZE - *f_pos);
  if(count == 0) { // this if is probably not necessary
    retval = 0;
    goto out;
  }
  /* Transfering data to user space */ 
  if(copy_to_user(buf, memory_buffer + *f_pos, count)) {
    retval = -EFAULT;
    goto out;
  }
  *f_pos += count;
  retval = count;
out:
  up(&sem);
  return retval;
}
读取未正确执行。它不应该写超过计数字节给用户,他可以有更小的缓冲区。更相关的是,它应该返回写入用户的字节数,并且只有在文件结束时才返回0。它还可以在出现错误时以负数形式返回错误代码,如-EIO

您写入5个字符,但返回1,因此cat认为它是未完成读取,读取1个字节。我再次尝试读取并得到0,所以它将其解释为文件结尾

write也有类似的问题,它还应该检查用户缓冲区的大小和返回的字节数

这或多或少是我为固定大小缓冲区实现读取的方式:

ssize_t memory_read(struct file *filp, char *buf, 
                    size_t count, loff_t *f_pos) { 
  ssize_t retval;

  if(down_interruptible(&sem)) // some mutex is probably necessary
    return -ERESTARTSYS;
  count = MIN(count, MEMORY_SIZE - *f_pos);
  if(count == 0) { // this if is probably not necessary
    retval = 0;
    goto out;
  }
  /* Transfering data to user space */ 
  if(copy_to_user(buf, memory_buffer + *f_pos, count)) {
    retval = -EFAULT;
    goto out;
  }
  *f_pos += count;
  retval = count;
out:
  up(&sem);
  return retval;
}

我把它改为:int bytes=copy_to_userbuf,memory_buffer,5;返回内存中读取的字节和挂起程序的内存中写入的相同类型的返回。如果您对我所说的有不同意见,请告诉我们。“你是说其他方式吗?”@kingsmasher1-没那么简单。如果copy_to_user返回非零,则应返回-EFAULT。如果成功,您应该返回传输的字节数,这取决于您的逻辑。如果您将返回5,那么在这种情况下它可以工作;应该更改为tmp=buf,对吗?不使用此选项:n=copy_to_userbuf,memory_buffer,count;/*将读取位置更改为最佳匹配*/ifn!=0返回-默认值;否则返回计数;我把它改为:int bytes=copy_to_userbuf,memory_buffer,5;返回内存中读取的字节和挂起程序的内存中写入的相同类型的返回。如果您对我所说的有不同意见,请告诉我们。“你是说其他方式吗?”@kingsmasher1-没那么简单。如果copy_to_user返回非零,则应返回-EFAULT。如果成功,您应该返回传输的字节数,这取决于您的逻辑。如果您将返回5,那么在这种情况下它可以工作;应该更改为tmp=buf,对吗?不使用此选项:n=copy_to_userbuf,memory_buffer,count;/*将读取位置更改为最佳匹配*/ifn!=0返回-默认值;否则返回计数;那些认为这一点太幼稚的人否决了这一点,他们实际上可以指出解决办法,而我面临的问题与我昨天回答的问题非常接近:那些认为这一点太幼稚的人否决了这一点,他们可以指出解决办法,而我面临的问题与我昨天回答的问题非常接近: