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