c - 为什么这个 char 驱动程序总是只复制一个字节?

标签 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, 
                    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;
}

最佳答案

read 未正确实现。它不应该向用户写入超过 count 个字节(他可以有更小的缓冲区)。更相关的是,它应该返回写入用户的字节数,并且仅在文件结束时才返回 0。如果出现错误,它还可以将错误代码作为负数返回,如 -EIO

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

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

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

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;
}

关于c - 为什么这个 char 驱动程序总是只复制一个字节?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17047581/

相关文章:

在运行时在 c 中创建某个结构

linux - copy_to_user 在内核模块中不起作用

c - gtk 网络教程/资源/示例

c - 输入带有不可打印字符的字符串

linux - 如何杀死不存在的程序进程

linux - 如何检查 XFCE 中的任何窗口是否最大化?

c - IPC FIFO 生产者-消费者死锁

linux - 在 Linux 中如何知道哪条中断线是共享的,哪条中断线是空闲的?

linux - 一些Linux设备驱动程序是如何自动加载/卸载的?

c++ - 关于 OMP barrier 和动态数组