ssize_t scull_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { /* dev之前在open函数中已经保存在flip->private_data中,这里直接取 */ struct scull_dev *dev = filp->private_data; struct scull_qset *dptr; /* the first listitem */ /* 计算量子集的byte大小,默认4000000*/ int quantum = dev->quantum, qset = dev->qset; int itemsize = quantum * qset; /* how many bytes in the listitem */ int item, s_pos, q_pos, rest; ssize_t retval = 0; /* 获得互斥锁 */ if (down_interruptible(&dev->sem)) return -ERESTARTSYS; if (*f_pos >= dev->size) goto out; if (*f_pos + count > dev->size) count = dev->size - *f_pos; printk(KERN_ALERT "Debug by andrea:scull_read()/n"); /* find listitem, qset index, and offset in the quantum */ /* item代表要读的数据起始点在哪个量子集中,s_pos代表要读的数据起始点在哪个量子中。q_pos代表要读的数据的起始点在量子的具体哪个位置 */ item = (long)*f_pos / itemsize; rest = (long)*f_pos % itemsize; s_pos = rest / quantum; q_pos = rest % quantum; /* follow the list up to the right position (defined elsewhere) */ /* 根据item找到量子集,如果存在则返回地址,如果不存在,则创建指定的量子集然后返回地址*/ dptr = scull_follow(dev, item); /* 如果指定的scull_qset不存在,或者量子指针数组不存在,或者量子不存在,都退出 */ if (dptr == NULL || !dptr->data || ! dptr->data[s_pos]) goto out; /* don't fill holes */ /* read only up to the end of this quantum */ /* 设置scull_read一次最多只能读一个量子, 如果不这样做就会越界*/ if (count > quantum - q_pos) count = quantum - q_pos; if (copy_to_user(buf, dptr->data[s_pos] + q_pos, count)) { retval = -EFAULT; goto out; } /* 读取完成后,新的文件指针位置向前移动count个字节 */ *f_pos += count; /* 返回读取到的字节数,即count*/ retval = count; out: up(&dev->sem); return retval; }
ssize_t scull_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) { struct scull_dev *dev = filp->private_data; struct scull_qset *dptr; int quantum = dev->quantum, qset = dev->qset; int itemsize = quantum * qset; int item, s_pos, q_pos, rest; ssize_t retval = -ENOMEM; /* value used in "goto out" statements */ if (down_interruptible(&dev->sem)) return -ERESTARTSYS; /* find listitem, qset index and offset in the quantum */ item = (long)*f_pos / itemsize; rest = (long)*f_pos % itemsize; s_pos = rest / quantum; q_pos = rest % quantum; /* follow the list up to the right position */ dptr = scull_follow(dev, item); if (dptr == NULL) goto out; if (!dptr->data) { dptr->data = kmalloc(qset * sizeof(char *), GFP_KERNEL); if (!dptr->data) goto out; memset(dptr->data, 0, qset * sizeof(char *)); } if (!dptr->data[s_pos]) { dptr->data[s_pos] = kmalloc(quantum, GFP_KERNEL); if (!dptr->data[s_pos]) goto out; } /* write only up to the end of this quantum */ if (count > quantum - q_pos) count = quantum - q_pos; if (copy_from_user(dptr->data[s_pos]+q_pos, buf, count)) { retval = -EFAULT; goto out; } *f_pos += count; retval = count; /* update the size */ if (dev->size < *f_pos) dev->size = *f_pos; out: up(&dev->sem); return retval; }
ssize_t scull_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { struct scull_dev *dev = filp->private_data; struct scull_qset *dptr; /* the first listitem */ int quantum = dev->quantum, qset = dev->qset; int itemsize = quantum * qset; /* how many bytes in the listitem */ int item, s_pos, q_pos, rest; ssize_t retval = 0; if (down_interruptible(&dev->sem)) return -ERESTARTSYS; if (*f_pos >= dev->size) goto out; if (*f_pos + count > dev->size) count = dev->size - *f_pos; /* find listitem, qset index, and offset in the quantum */ item = (long)*f_pos / itemsize; rest = (long)*f_pos % itemsize; s_pos = rest / quantum; q_pos = rest % quantum; /* follow the list up to the right position (defined elsewhere) */ dptr = scull_follow(dev, item); if (dptr == NULL || !dptr->data || ! dptr->data[s_pos]) goto out; /* don't fill holes */ /* read only up to the end of this quantum */ if (count > quantum - q_pos) count = quantum - q_pos; if (copy_to_user(buf, dptr->data[s_pos] + q_pos, count)) { retval = -EFAULT; goto out; } *f_pos += count; retval = count; out: up(&dev->sem); return retval; }
ssize_t scull_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { struct scull_dev *dev = filp->private_data; struct scull_qset *dptr; /* the first listitem */ int quantum = dev->quantum, qset = dev->qset; int itemsize = quantum * qset; /* how many bytes in the listitem */ int item, s_pos, q_pos, rest; ssize_t retval = 0; if (down_interruptible(&dev->sem)) return -ERESTARTSYS; if (*f_pos >= dev->size) //操作位置到文件尾,或超出文件尾了 goto out; if (*f_pos + count > dev->size) //在当前位置所要读的数目超过文件尾了 count = dev->size - *f_pos; //减小这次的期望读取数目 /* find listitem, qset index, and offset in the quantum */ item = (long)*f_pos / itemsize; //确定是哪个链表项下,即哪个节点下; rest = (long)*f_pos % itemsize; //在这个链表项的什么位置(偏移量),用于下面找qset索引和偏移量; s_pos = rest / quantum; //在这个节点里**data这个指针数组的第几行; q_pos = rest % quantum; //在这行,即这个量子里的偏移量; /* follow the list up to the right position (defined elsewhere) */ dptr = scull_follow(dev, item); //找到这个链表项 if (dptr == NULL || !dptr->data || ! dptr->data[s_pos]) goto out; /* don't fill holes */ //以一个量子为单位传,简化了代码; /* read only up to the end of this quantum */ if (count > quantum - q_pos) count = quantum - q_pos; /* * 上面为这步准备了具体在哪个链表项的指针数组的第几行的第几列(即dptr->data[s_pos] + q_pos) * 从这个位置的内核态的buf中拷给用户态 */ //关键一步,将数据拷给用户空间 if (copy_to_user(buf, dptr->data[s_pos] + q_pos, count)) { retval = -EFAULT; goto out; } *f_pos += count; //更新文件指针 retval = count; out: up(&dev->sem); return retval; }
inline ssize_t scull_write(int tid, file filp, char buf, size_t count, loff_t f_pos) { scull_dev dev = filp; //struct scull_dev *dev = filp->private_data scull_qset_type dptr; int quantum = dev_quantum, qset = dev_qset; int itemsize = quantum * qset; int item, s_pos, q_pos, rest; ssize_t retval = -ENOMEM; /* value used in "goto out" statements */ if (down_interruptible(tid)) return -ERESTARTSYS; /* find listitem, qset index and offset in the quantum */ item = f_pos / itemsize; rest = f_pos; s_pos = rest / quantum; q_pos = rest; /* follow the list up to the right position */ dptr = scull_follow(dev, item); if (dptr == NULL) goto out; /* write only up to the end of this quantum */ if (count > quantum - q_pos) count = quantum - q_pos; __X__ = 1; /* check mutual exclusion */ if (copy_from_user(dev_data+s_pos+q_pos, buf, count)) { retval = -EFAULT; goto out; } f_pos += count; retval = count; /* update the size */ if (dev_size < f_pos) dev_size = f_pos; assert(__X__ == 1); /* check mutual exclusion */ out: up(); return retval; }
inline ssize_t scull_read(int tid, file filp, char buf, size_t count, loff_t f_pos) { scull_dev dev = filp; //struct scull_dev *dev = filp->private_data scull_qset_type dptr; /* the first listitem */ int quantum = dev_quantum, qset = dev_qset; int itemsize = quantum * qset; /* how many bytes in the listitem */ int item, s_pos, q_pos, rest; ssize_t retval = 0; if (down_interruptible(tid)) return -ERESTARTSYS; __X__ = 0; /* check mutual exclusion */ if (f_pos >= dev_size) goto out; if (f_pos+count >= dev_size) count = dev_size - f_pos; /* find listitem, qset index, and offset in the quantum */ item = f_pos / itemsize; rest = f_pos; s_pos = rest / quantum; q_pos = rest; /* follow the list up to the right position (defined elsewhere) */ dptr = scull_follow(dev, item); /* read only up to the end of this quantum */ if (count > quantum - q_pos) count = quantum - q_pos; if (copy_to_user(buf, dev_data + s_pos + q_pos, count)) { retval = -EFAULT; goto out; } f_pos += count; retval = count; assert(__X__ <= 0); /* check mutual exclusion */ out: up(); return retval; }
ssize_t hello_read(struct file *filp, char __user *buf,\ size_t count , loff_t *f_ops) { struct scull_dev *dev = filp->private_data; struct scull_qset *current_qset; int qset = dev->qset; int quantum = dev->quantum; int itemsize = qset*quantum; int item, s_pos, q_pos, reset; ssize_t retval = -ENOMEM; DEBUG (7, "hello_read.\n"); item = (long)*f_ops / itemsize; reset = (long)*f_ops % itemsize; s_pos = reset / quantum; q_pos = reset % quantum; current_qset = scull_follow(dev, item); if (!current_qset || !current_qset->data || !current_qset->data[s_pos]) { DEBUG (1, "err_back_scull_follow"); goto err_back_scull_follow; } /* ensure count */ if (count > (quantum - q_pos)) count = quantum - q_pos; /* copy from user */ if (copy_to_user(buf, current_qset->data[s_pos] + q_pos, count)) { DEBUG (1, "err_copy_to_user."); retval = -EFAULT; goto err_copy_to_user; } /* update */ retval = count; *f_ops += count; err_copy_to_user: err_back_scull_follow: return retval; }
ssize_t scull_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { struct scull_dev *dev = filp->private_data; struct scull_qset *dptr; int quantum = dev->quantum; int qset = dev->qset; int itemsize = quantum * qset; int item, s_pos, q_pos, rest; ssize_t retval = 0; printk(KERN_ALERT "scull_read"); printk(KERN_ALERT "qset = %d; count = %d; f_pos = %d", qset, count, *f_pos); printk(KERN_ALERT "dev->size = %ld", dev->size); if (*f_pos >= dev->size) goto out; if (*f_pos + count > dev->size) count = dev->size - *f_pos; item = (long)*f_pos / itemsize; // f_pos 中有多少个 scull_qset rest = (long)*f_pos % itemsize; // 再加多少个字节 s_pos = rest / quantum; // rest 中有多少个 quantum q_pos = rest % quantum; // 再加多少个字节 dptr = scull_follow(dev, item); // 找到链表中第 item 个 scull_qset if (NULL == dptr || NULL == dptr->data || NULL == dptr->data[s_pos]) goto out; if (count > quantum - q_pos) count = quantum - q_pos; if (copy_to_user(buf, dptr->data[s_pos] + q_pos, count)) { retval = -EFAULT; goto out; } printk(KERN_INFO "buf = %s", buf); *f_pos += count; retval = count; out: return retval; }
read_write_t scull_write (struct inode *inode, struct file *filp, const char *buf, count_t count) { Scull_Dev *dev = filp->private_data; Scull_Dev *dptr; int quantum = dev->quantum; int qset = dev->qset; int itemsize = quantum * qset; unsigned long f_pos = (unsigned long)(filp->f_pos); int item, s_pos, q_pos, rest; /* find listitem, qset index and offset in the quantum */ item = f_pos / itemsize; rest = f_pos % itemsize; s_pos = rest / quantum; q_pos = rest % quantum; /* follow the list up to the right position */ dptr = scull_follow(dev, item); if (!dptr->data) { dptr->data = kmalloc(qset * sizeof(char *), GFP_KERNEL); if (!dptr->data) return -ENOMEM; memset(dptr->data, 0, qset * sizeof(char *)); } if (!dptr->data[s_pos]) { dptr->data[s_pos] = kmalloc(quantum, GFP_KERNEL); if (!dptr->data[s_pos]) return -ENOMEM; } if (count > quantum - q_pos) count = quantum - q_pos; /* write only up to the end of this quantum */ dev->usage++; /* the following call may sleep */ copy_from_user(dptr->data[s_pos]+q_pos, buf, count); dev->usage--; /* update the size */ if (dev->size < f_pos + count) dev-> size = f_pos + count; filp->f_pos += count; return count; }
/* * Data management: read and write */ ssize_t scull_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { struct scull_dev *dev = filp->private_data; struct scull_qset *dptr; /*ADD:链表中的第一项*/ int quantum = dev->quantum,qset = dev->qset; int itemsize = quantum * qset; int item,s_pos,q_pos,rest; ssize_t retval = 0; if (down_interruptible(&dev->sem)) return -ERESTARTSYS; if (*f_pos >= dev->size) goto out; if (*f_pos + count > dev->size) count = dev->size - *f_pos; //ADD:计算位置 item = (long)*f_pos /itemsize; //链表中的第几项 rest = (long)*f_pos % itemsize; s_pos = rest / quantum; //该项中的第几个量子 q_pos = rest % quantum; //量子(char 数组)中的第几个单元 dptr = scull_follow(dev,item); //遍历到正确的位置 if (dptr == NULL || !dptr->data || !dptr->data[s_pos]) goto out; //各种空,什么时候发生? if (count > quantum -q_pos) //量子化处理,每次最多读到量子尾(即最多4000,默认时) count = quantum -q_pos; if (copy_to_user(buf, dev->data + *f_pos, count)) { retval = -EFAULT; goto out; } *f_pos += count; retval = count; out: up(&dev->sem); return retval; }
read_write_t scull_read (struct inode *inode, struct file *filp, char *buf, count_t count) { Scull_Dev *dev = filp->private_data; /* the first listitem */ int quantum = dev->quantum; int qset = dev->qset; int itemsize = quantum * qset; /* how many bytes in the listitem */ unsigned long f_pos = (unsigned long)(filp->f_pos); int item, s_pos, q_pos, rest; if (f_pos > dev->size) return 0; if (f_pos + count > dev->size) count = dev->size - f_pos; /* find listitem, qset index and offset in the quantum */ item = f_pos / itemsize; rest = f_pos % itemsize; s_pos = rest / quantum; q_pos = rest % quantum; /* follow the list up to the right position (defined elsewhere) */ dev = scull_follow(dev, item); if (!dev->data) return 0; /* don't fill holes */ if (!dev->data[s_pos]) return 0; if (count > quantum - q_pos) count = quantum - q_pos; /* read only up to the end of this quantum */ dev->usage++; /* the following call may sleep */ copy_to_user(buf, dev->data[s_pos]+q_pos, count); dev->usage--; filp->f_pos += count; return count; }
ssize_t scull_write( struct file *filp, const char __user *buf, size_t count, loff_t *offset ) { ssize_t ret = 0; struct scull_dev *dev = filp->private_data; int quantum = dev->quantum; int qset = dev->qset; int itemsize = quantum * qset; /* 量子列表中有多少字节数据 */ int item, s_pos, q_pos, rest; struct scull_qset *dptr; if ( down_interruptible( &dev->sem ) ) return(-ERESTARTSYS); if ( *offset > dev->size ) goto out; /* * 查找量子列表,索引量子集,定位位置 */ item = (long) *offset / itemsize; /* 量子列表中的哪一项 */ rest = (long) *offset % itemsize; /* 量子列表中还剩余多少量子项 */ q_pos = rest / quantum; /* 在量子中的位置 */ s_pos = rest % quantum; /* 剩余多少量子 */ dptr = scull_follow( dev, item ); if ( dptr == NULL ) goto out; if ( !dptr->data ) { dptr->data = kmalloc( qset * sizeof(char *), GFP_KERNEL ); if ( !dptr->data ) goto out; memset( dptr->data, 0, qset * sizeof(char *) ); } if ( !dptr->data[s_pos] ) { dptr->data[s_pos] = kmalloc( quantum, GFP_KERNEL ); if ( !dptr->data[s_pos] ) goto out; } /* 如果大于量子的长度 */ if ( count > quantum - q_pos ) count = quantum - q_pos; if ( copy_from_user( dptr->data[s_pos] + q_pos, buf, count ) ) { ret = -EFAULT; goto out; } *offset += count; ret = count; /* 更新大小 */ if ( dev->size < *offset ) dev->size = *offset; out: up( &dev->sem ); return(ret); }
ssize_t hello_write(struct file *filp, const char __user *buf,\ size_t count, loff_t *f_ops) { struct scull_dev *dev = filp->private_data; struct scull_qset *current_qset; int qset = dev->qset; int quantum = dev->quantum; int itemsize = qset*quantum; int item, s_pos, q_pos, reset; ssize_t retval = -ENOMEM; DEBUG (7, "hello_write."); item = (long)*f_ops / itemsize; reset = (long)*f_ops % itemsize; s_pos = reset / quantum; q_pos = reset % quantum; current_qset = scull_follow(dev, item); if (!current_qset) { DEBUG (1, "err_back_scull_follow"); goto err_back_scull_follow; } /* kmalloc qset */ if (!current_qset->data) { current_qset = kmalloc (qset * sizeof (char *), GFP_KERNEL); if (!current_qset) { DEBUG (1, "err_kmalloc_qset"); goto err_kmalloc_qset; } memset(current_qset, 0, qset * sizeof (char *)); } /* kmalloc quantum */ if (!current_qset->data[s_pos]) { current_qset->data[s_pos] = kmalloc (quantum, GFP_KERNEL); if (!current_qset->data[s_pos]) { DEBUG (1, "err_kmalloc_quantum"); goto err_kmalloc_quantum; } memset (current_qset->data[s_pos], 0, quantum); } /* ensure count */ if (count > (quantum - q_pos)) count = quantum - q_pos; /* copy from user */ if (copy_from_user(current_qset->data[s_pos] + q_pos, buf, count)) { DEBUG (1, "err_copy_form_user."); retval = -EFAULT; goto err_copy_form_user; } /* update */ retval = count; *f_ops += count; //dev->size += count; if (dev->size < *f_ops) dev->size = *f_ops; err_copy_form_user: err_kmalloc_quantum: err_kmalloc_qset: err_back_scull_follow: return retval; }
ssize_t scull_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos) { struct scull_dev *dev = filp->private_data; struct scull_qset *qset_ptr; int quantum = dev->quantum; int qset = dev->qset; int itemsize = quantum * qset; ssize_t retval = -ENOMEM; int item; int rest; int s_pos; int q_pos; int offset = (int)*f_pos; #ifdef __DEBUG_INFO printk(KERN_ALERT "I am Write proccess! I am %i\n", (get_current())->pid); #endif if(down_interruptible(&dev->sem)) return -ERESTARTSYS; #ifdef __DEBUG_INFO printk(KERN_ALERT "In scull_write()\n"); #endif item = offset / itemsize; rest = offset % itemsize; s_pos = rest / quantum; q_pos = rest % quantum; qset_ptr = scull_follow(dev, item); if(!qset_ptr){ goto out; } if(!(qset_ptr->data)){ qset_ptr->data = kmalloc(qset * sizeof(char *), GFP_KERNEL); if(!(qset_ptr->data)){ goto out; } memset(qset_ptr->data, 0, qset * sizeof(char *)); } if(!((qset_ptr->data)[s_pos])){ qset_ptr->data[s_pos] = kmalloc(quantum, GFP_KERNEL); if(!qset_ptr->data[s_pos]) goto out; } if(count > quantum - q_pos) count = quantum - q_pos; if(copy_from_user((qset_ptr->data[s_pos]) + q_pos, buf, count)){ retval = -EFAULT; goto out; } *f_pos += count; retval = count; if(dev->size < *f_pos) dev->size = *f_pos; out: up(&dev->sem); complete(&dev->comp); return retval; }
ssize_t scull_read(struct file *filp, char *buf, size_t count, loff_t *f_pos) { struct scull_dev *dev = filp->private_data; struct scull_qset *qset_ptr = dev->data; int quantum = dev->quantum; int qset = dev->qset; int itemsize = quantum * qset; unsigned long res; int item; int rest; int s_pos; int q_pos; int offset = (int)(*f_pos); ssize_t retval = 0; #ifdef __DEBUG_INFO printk(KERN_ALERT "Waiting for Write proccess! I am %i\n", (get_current())->pid); #endif wait_for_completion(&dev->comp); if(down_interruptible(&dev->sem)) return -ERESTARTSYS; #ifdef __DEBUG_INFO printk(KERN_ALERT "In scull_read()\n"); #endif if(offset >= dev->size) goto out; if((offset + count) > dev->size) count = dev->size - offset; item = offset / itemsize; rest = offset % itemsize; s_pos = rest / quantum; q_pos = rest % quantum; qset_ptr = scull_follow(dev, item); if(!qset_ptr || !(qset_ptr->data) || !(qset_ptr->data[s_pos])) goto out; if(count > (quantum - q_pos)) count = quantum - q_pos; res = copy_to_user(buf, qset_ptr->data[s_pos] + q_pos, count); if(res != 0){ retval = -EFAULT; goto out; } *f_pos += count; retval = count; out: up(&dev->sem); return retval; }
ssize_t scull_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) { struct scull_dev *dev = filp->private_data; struct scull_qset *dptr; int quantum = dev->quantum, qset = dev->qset; int itemsize = quantum * qset; int item, s_pos, q_pos, rest; ssize_t retval = -ENOMEM; /* value used in "goto out" statements */ /* 获得互斥锁 */ if (down_interruptible(&dev->sem)) return -ERESTARTSYS; printk(KERN_ALERT "Debug by andrea:scull_write()/n"); /* find listitem, qset index and offset in the quantum */ /* item代表要写入的位置在哪一个量子集中,s_pos代表要写入的位置在哪个量子中,q_pos代表要写入的的位置在量子中的位置*/ item = (long)*f_pos / itemsize; rest = (long)*f_pos % itemsize; s_pos = rest / quantum; q_pos = rest % quantum; /* follow the list up to the right position */ /* 取出量子 */ dptr = scull_follow(dev, item); if (dptr == NULL) goto out; /* 如果量子集中的数组不存在,分配内存*/ if (!dptr->data) { dptr->data = kmalloc(qset * sizeof(char *), GFP_KERNEL); if (!dptr->data) goto out; memset(dptr->data, 0, qset * sizeof(char *)); } /* 如果指定的量子不存在,创建量子*/ if (!dptr->data[s_pos]) { dptr->data[s_pos] = kmalloc(quantum, GFP_KERNEL); if (!dptr->data[s_pos]) goto out; } /* write only up to the end of this quantum */ /* 限制一次write最多写满一个量子,否则会越界 */ if (count > quantum - q_pos) count = quantum - q_pos; /* 把数据写入量子 */ if (copy_from_user(dptr->data[s_pos]+q_pos, buf, count)) { retval = -EFAULT; goto out; } /* 文件指针后移count个字节 */ *f_pos += count; /* 返回写入的count */ retval = count; /* update the size */ /* 更新文件大小 */ if (dev->size < *f_pos) dev->size = *f_pos; out: up(&dev->sem); return retval; }