Beispiel #1
0
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;
}
Beispiel #2
0
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;
}
Beispiel #3
0
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;
}
Beispiel #4
0
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;
}
Beispiel #5
0
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;
}
Beispiel #6
0
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;
}
Beispiel #7
0
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;
}
Beispiel #8
0
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;
}
Beispiel #9
0
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;
}
Beispiel #10
0
/*
 * 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;
}
Beispiel #11
0
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;
}
Beispiel #12
0
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);
}
Beispiel #13
0
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;
}
Beispiel #14
0
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;
}
Beispiel #15
0
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;
}
Beispiel #16
0
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;
}