全部博文(183)
分类: LINUX
2010-11-07 10:51:27
29 struct kfifo { 30 unsigned char *buffer; /* the buffer holding the data */ 31 unsigned int size; /* the size of the allocated buffer */ 32 unsigned int in; /* data is added at offset (in % size) */ 33 unsigned int out; /* data is extracted from off. (out % size) */ 34 spinlock_t *lock; /* protects concurrent modifications */ 35 }; 缓冲区buffer是以字节为单位的循环缓冲区 size是缓冲区的大小 in是写入数据时以 (in % size) 运算取得在buffer中的写下标 out是读取数据时以 (out % size) 运算取得在buffer中的读下标 |
...............// 点代表省略的代码 72 /* 73 * round up to the next power of 2, since our 'let the indices 74 * wrap' tachnique works only in this case. 75 */ // 这里的操作是确保size的值为2的n次方 76 if (size & (size - 1)) { 77 BUG_ON(size > 0x80000000); 78 size = roundup_pow_of_two(size); 79 } ............... 105 /* 106 * __kfifo_put - puts some data into the FIFO, no locking version 107 * @fifo: the fifo to be used. 108 * @buffer: the data to be added. 109 * @len: the length of the data to be added. 110 * 111 * This function copies at most 'len' bytes from the 'buffer' into 112 * the FIFO depending on the free space, and returns the number of 113 * bytes copied. 114 * 115 * Note that with only one concurrent reader and one concurrent 116 * writer, you don't need extra locking to use these functions. 117 */ 118 unsigned int __kfifo_put(struct kfifo *fifo, 119 unsigned char *buffer, unsigned int len) 120 { 121 unsigned int l; 122 // 读这段程序可结合图B的分析 // min函数的第二个参数实为(fifo->size - (fifo->in - fifo->out)), // 很显然它就是上面提到的BUF_FREE_SPACE,BUF_FREE_SPACE和本 // 函数__kfifo_put 参数len比较求出的最小值就是本次要写入循环缓冲区 // 的字节个数,也即调用min函数后len为要写入循环缓冲区的真正字节个数 // 注意:这里的fifo->size可能是小于fifo->in,但fifo->size, // fifo->in, fifo->out三者都是无符号整形,运算中的逻辑不会出错,这 // 个技巧后面再解释。 123 len = min(len, fifo->size - fifo->in + fifo->out); 124 125 /* first put the data starting from fifo->in to buffer end */ /* 首先把数据写到从写下标开始到缓冲buffer结束 */ // (fifo->in & (fifo->size - 1))和(fifo->in % fifo->size)是等价的, // 这一技巧后面再解释。既然它们是等价的,那么 // fifo->size - (fifo->in & (fifo->size - 1))就是 // WRETE_INDEX_TO_BUF_END_BYTES。函数min目的就很显然了,它求出来的 // 是要写的字节数,而这字节数的范围是:从写下标开始到循环缓冲结束。 126 l = min(len, fifo->size - (fifo->in & (fifo->size - 1))); 127 memcpy(fifo->buffer + (fifo->in & (fifo->size - 1)), buffer, l); 128 129 /* then put the rest (if any) at the beginning of the buffer */ /* 然后如果还有数据没有写入,就把剩下的字节数len - l 从缓冲 * 区buffer的开始处写入剩余数据 */ 130 memcpy(fifo->buffer, buffer + l, len - l); 131 // 注意fifo->in只有加没有减,当它达到它所能表达的最大范围时会遵循 // 无符号整形的规则,这也是使用了无符号整形的技巧,也将在后面解释。 132 fifo->in += len; 133 134 return len; 135 } 136 EXPORT_SYMBOL(__kfifo_put); 137 138 /* 139 * __kfifo_get - gets some data from the FIFO, no locking version 140 * @fifo: the fifo to be used. 141 * @buffer: where the data must be copied. 142 * @len: the size of the destination buffer. 143 * 144 * This function copies at most 'len' bytes from the FIFO into the 145 * 'buffer' and returns the number of copied bytes. 146 * 147 * Note that with only one concurrent reader and one concurrent 148 * writer, you don't need extra locking to use these functions. 149 */ 150 unsigned int __kfifo_get(struct kfifo *fifo, 151 unsigned char *buffer, unsigned int len) 152 { 153 unsigned int l; 154 // 读这段程序可结合图B的分析 // 调用min函数后len为要读取的真正字节个数 155 len = min(len, fifo->in - fifo->out); 156 157 /* first get the data from fifo->out until the end of the buffer */ /* 首先从读下标开始读取数据直到缓冲结束 */ 158 l = min(len, fifo->size - (fifo->out & (fifo->size - 1))); 159 memcpy(buffer, fifo->buffer + (fifo->out & (fifo->size - 1)), l); 160 161 /* then get the rest (if any) from the beginning of the buffer */ /* 如果没有读完所需的字节数据,就从缓冲的开始读取剩下的字节 */ 162 memcpy(buffer + l, fifo->buffer, len - l); 163 // fifo->out也是只有加没有减,跟fifo->in类似 164 fifo->out += len; 165 166 return len; 167 } 168 EXPORT_SYMBOL(__kfifo_get); |