免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 18902 | 回复: 18

内核源码kfifo分析(原创) [复制链接]

论坛徽章:
0
发表于 2009-03-23 01:35 |显示全部楼层
从2.6.10开始,Linux内核提供了一个通用的环形缓存(我喜欢称为环形队列);它的头文件是<linux/kfifo.h>,kfifo.c是实现代码。
在设备驱动中环形缓存出现相当多. 网络适配器, 特别地, 常常使用环形缓存来与处理器交换数据(报文)[LDD3]。

见下面的图“LDD3中描述的队列”。

我们来看下kfifo的数据结构:

struct kfifo {
&nbsp;&nbsp;&nbsp;&nbsp;unsigned char *buffer;&nbsp;&nbsp;&nbsp;&nbsp;/* the buffer holding the data */
&nbsp;&nbsp;&nbsp;&nbsp;unsigned int size;&nbsp;&nbsp;&nbsp;&nbsp;/* the size of the allocated buffer */
&nbsp;&nbsp;&nbsp;&nbsp;unsigned int in;&nbsp;&nbsp;&nbsp;&nbsp;/* data is added at offset (in % size) */
&nbsp;&nbsp;&nbsp;&nbsp;unsigned int out;&nbsp;&nbsp;&nbsp;&nbsp;/* data is extracted from off. (out % size) */
&nbsp;&nbsp;&nbsp;&nbsp;spinlock_t *lock;&nbsp;&nbsp;&nbsp;&nbsp;/* protects concurrent modifications */
};


如E文注释所解,buffer指向队列空间,对于队列的操作,一般会涉及到读写,如果是多线程的话,就有可能涉及到生产者/消费者,也称读者/写者问题;
size表示空间大小,必须为2^k,如果不是2^k大小,kfifo将会帮助用户扩展到一个合适的大小;
in表示写者指向的索引,在kfifo体统的put函数中,被处理为一个虚拟索引(我暂这么称呼)。之所以称之为虚拟索引,是因为该索引并不一定真正指向有效的地址空间,而是要通过一定运算才能得到真实的索引。下面的put/get代码分析将会看到内核是kfifo是怎么运算的。
out表示读者指向的索引,out的更新与in一样,都是使用了虚拟索引的概念,out总是小于等于in。

我们直接来看代码(保留了原来的注释,//后面的内容为笔者的解释)

/**
&nbsp;* kfifo_init - allocates a new FIFO using a preallocated buffer
&nbsp;* @buffer: the preallocated buffer to be used.
&nbsp;* @size: the size of the internal buffer, this have to be a power of 2.
&nbsp;* @gfp_mask: get_free_pages mask, passed to kmalloc()
&nbsp;* @lock: the lock to be used to protect the fifo buffer
&nbsp;*
&nbsp;* Do NOT pass the kfifo to kfifo_free() after use! Simply free the
&nbsp;* &struct kfifo with kfree().
&nbsp;*/

struct kfifo *kfifo_init(unsigned char *buffer, unsigned int size,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gfp_t gfp_mask, spinlock_t *lock)
{
&nbsp;&nbsp;&nbsp;&nbsp;struct kfifo *fifo;

&nbsp;&nbsp;&nbsp;&nbsp;/* size must be a power of 2 */
&nbsp;&nbsp;&nbsp;&nbsp;BUG_ON(size & (size - 1)); //大小必须为2的k次方(k>0)的目的在于put/get中从虚拟索引计算真实索引,size & (size - 1)是常用判断技巧


&nbsp;&nbsp;&nbsp;&nbsp;fifo = kmalloc(sizeof(struct kfifo), gfp_mask); //分配kfifo数据结构

&nbsp;&nbsp;&nbsp;&nbsp;if (!fifo)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return ERR_PTR(-ENOMEM);

&nbsp;&nbsp;&nbsp;&nbsp;fifo->buffer = buffer;
&nbsp;&nbsp;&nbsp;&nbsp;fifo->size = size;
&nbsp;&nbsp;&nbsp;&nbsp;fifo->in = fifo->out = 0; //当fifo->in == fifo->out 时,表示空队列

&nbsp;&nbsp;&nbsp;&nbsp;fifo->lock = lock;

&nbsp;&nbsp;&nbsp;&nbsp;return fifo;
}


/**
&nbsp;* kfifo_alloc - allocates a new FIFO and its internal buffer
&nbsp;* @size: the size of the internal buffer to be allocated.
&nbsp;* @gfp_mask: get_free_pages mask, passed to kmalloc()
&nbsp;* @lock: the lock to be used to protect the fifo buffer
&nbsp;*
&nbsp;* The size will be rounded-up to a power of 2.
&nbsp;*/

//通过调用kfifo_alloc分配队列空间,该函数会调用kfifo_init初始化kfifo结构体,并调整size的大小以适应运算

struct kfifo *kfifo_alloc(unsigned int size, gfp_t gfp_mask, spinlock_t *lock)
{
&nbsp;&nbsp;&nbsp;&nbsp;unsigned char *buffer;
&nbsp;&nbsp;&nbsp;&nbsp;struct kfifo *ret;

&nbsp;&nbsp;&nbsp;&nbsp;/*
&nbsp;&nbsp;&nbsp;&nbsp; * round up to the next power of 2, since our 'let the indices
&nbsp;&nbsp;&nbsp;&nbsp; * wrap' tachnique works only in this case.
&nbsp;&nbsp;&nbsp;&nbsp; */

&nbsp;&nbsp;&nbsp;&nbsp;if (size & (size - 1)) { //如果size不是2的k次方,代码将size调整最近的2^k次方附近

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BUG_ON(size > 0x80000000);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;size = roundup_pow_of_two(size);
&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;buffer = kmalloc(size, gfp_mask);
&nbsp;&nbsp;&nbsp;&nbsp;if (!buffer)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return ERR_PTR(-ENOMEM);

&nbsp;&nbsp;&nbsp;&nbsp;ret = kfifo_init(buffer, size, gfp_mask, lock);

&nbsp;&nbsp;&nbsp;&nbsp;if (IS_ERR(ret))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kfree(buffer);

&nbsp;&nbsp;&nbsp;&nbsp;return ret;
}

/**
&nbsp;* __kfifo_put - puts some data into the FIFO, no locking version
&nbsp;* @fifo: the fifo to be used.
&nbsp;* @buffer: the data to be added.
&nbsp;* @len: the length of the data to be added.
&nbsp;*
&nbsp;* This function copies at most @len bytes from the @buffer into
&nbsp;* the FIFO depending on the free space, and returns the number of
&nbsp;* bytes copied.
&nbsp;*
&nbsp;* Note that with only one concurrent reader and one concurrent
&nbsp;* writer, you don't need extra locking to use these functions.
&nbsp;*/

unsigned int __kfifo_put(struct kfifo *fifo,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned char *buffer, unsigned int len)
{
&nbsp;&nbsp;&nbsp;&nbsp;unsigned int l;

&nbsp;&nbsp;&nbsp;&nbsp;//fifo->size - fifo->in + fifo->out,这段代码计算空闲的空间

&nbsp;&nbsp;&nbsp;&nbsp;//in是写索引,out是读索引,而且put与get操作都是分别增加in与out的值来重新计算虚拟索引

&nbsp;&nbsp;&nbsp;&nbsp;//注意,out 始终不会大于 in,(in - out)是有效数据空间大小,size是总空间的大小

&nbsp;&nbsp;&nbsp;&nbsp;//那么空闲的空间大小就是 size - (int - out)

&nbsp;&nbsp;&nbsp;&nbsp;//如果请求的len大于空闲空间,就使len = size - (int - out)

&nbsp;&nbsp;&nbsp;&nbsp;len = min(len, fifo->size - fifo->in + fifo->out);

&nbsp;&nbsp;&nbsp;&nbsp;/*
&nbsp;&nbsp;&nbsp;&nbsp; * Ensure that we sample the fifo->out index -before- we
&nbsp;&nbsp;&nbsp;&nbsp; * start putting bytes into the kfifo.
&nbsp;&nbsp;&nbsp;&nbsp; */


&nbsp;&nbsp;&nbsp;&nbsp;smp_mb();

&nbsp;&nbsp;&nbsp;&nbsp;/* first put the data starting from fifo->in to buffer end */
&nbsp;&nbsp;&nbsp;&nbsp;//(fifo->in & (fifo->size - 1))这段代码计算真实的写索引偏移,笔者假设为real_in

&nbsp;&nbsp;&nbsp;&nbsp;//这是因为in在每次调用put之后都会增加一个len的长度

&nbsp;&nbsp;&nbsp;&nbsp;//由于fifo->size必定是2的k次方,而(fifo->size - 1)就是类似0x00FFFFF的值

&nbsp;&nbsp;&nbsp;&nbsp;//(fifo->in & (fifo->size - 1))的操作从数学角度将就是对长度fifo->size的取模运算

&nbsp;&nbsp;&nbsp;&nbsp;//这里能用AND运算代替取模运算得益于前面申请的空间大小为2^k次方

&nbsp;&nbsp;&nbsp;&nbsp;//l = min(空闲空间大小,从real_in开始到缓冲区结尾的空间)

&nbsp;&nbsp;&nbsp;&nbsp;l = min(len, fifo->size - (fifo->in & (fifo->size - 1)));

&nbsp;&nbsp;&nbsp;&nbsp;//先从buffer中拷贝l字节到缓冲区剩余空间,l<=len,也<=从real_in开始到缓冲区结尾的空间

&nbsp;&nbsp;&nbsp;&nbsp;//所以这个copy可能没拷贝完,但是不会造成缓冲区越界

&nbsp;&nbsp;&nbsp;&nbsp;memcpy(fifo->buffer + (fifo->in & (fifo->size - 1)), buffer, l);

&nbsp;&nbsp;&nbsp;&nbsp;/* then put the rest (if any) at the beginning of the buffer */
&nbsp;&nbsp;&nbsp;&nbsp;//当len > l时,拷贝buffer中剩余的内容,其实地址当然为buffer + l,而剩余的大小为len - l

&nbsp;&nbsp;&nbsp;&nbsp;//当len == l时,下面的memcpy啥都不干,绝对精妙的算法

&nbsp;&nbsp;&nbsp;&nbsp;memcpy(fifo->buffer, buffer + l, len - l);

&nbsp;&nbsp;&nbsp;&nbsp;/*
&nbsp;&nbsp;&nbsp;&nbsp; * Ensure that we add the bytes to the kfifo -before-
&nbsp;&nbsp;&nbsp;&nbsp; * we update the fifo->in index.
&nbsp;&nbsp;&nbsp;&nbsp; */


&nbsp;&nbsp;&nbsp;&nbsp;smp_wmb();

&nbsp;&nbsp;&nbsp;&nbsp;//更新in(写者)的逻辑索引

&nbsp;&nbsp;&nbsp;&nbsp;fifo->in += len;

&nbsp;&nbsp;&nbsp;&nbsp;return len;
}

/**
&nbsp;* __kfifo_get - gets some data from the FIFO, no locking version
&nbsp;* @fifo: the fifo to be used.
&nbsp;* @buffer: where the data must be copied.
&nbsp;* @len: the size of the destination buffer.
&nbsp;*
&nbsp;* This function copies at most @len bytes from the FIFO into the
&nbsp;* @buffer and returns the number of copied bytes.
&nbsp;*
&nbsp;* Note that with only one concurrent reader and one concurrent
&nbsp;* writer, you don't need extra locking to use these functions.
&nbsp;*/

unsigned int __kfifo_get(struct kfifo *fifo,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned char *buffer, unsigned int len)
{
&nbsp;&nbsp;&nbsp;&nbsp;unsigned int l;
&nbsp;&nbsp;&nbsp;&nbsp;//读取的大小不能超过有效空间长度

&nbsp;&nbsp;&nbsp;&nbsp;//经过min运算后len <= 请求的空间len, len <= size

&nbsp;&nbsp;&nbsp;&nbsp;len = min(len, fifo->in - fifo->out);

&nbsp;&nbsp;&nbsp;&nbsp;/*
&nbsp;&nbsp;&nbsp;&nbsp; * Ensure that we sample the fifo->in index -before- we
&nbsp;&nbsp;&nbsp;&nbsp; * start removing bytes from the kfifo.
&nbsp;&nbsp;&nbsp;&nbsp; */


&nbsp;&nbsp;&nbsp;&nbsp;smp_rmb();

&nbsp;&nbsp;&nbsp;&nbsp;/* first get the data from fifo->out until the end of the buffer */
&nbsp;&nbsp;&nbsp;&nbsp;//同理,fifo->out & (fifo->size - 1)等于out(读者)的虚拟索引计算出来真实索引real_out

&nbsp;&nbsp;&nbsp;&nbsp;//fifo->size - real_out就等于该索引到缓冲区尾部的空间大小

&nbsp;&nbsp;&nbsp;&nbsp;//经过min运算后,l<=len,l<=real_out至缓冲区尾部的空间大小

&nbsp;&nbsp;&nbsp;&nbsp;l = min(len, fifo->size - (fifo->out & (fifo->size - 1)));

&nbsp;&nbsp;&nbsp;&nbsp;//从real_out开始拷贝l字节内容到buffer中

&nbsp;&nbsp;&nbsp;&nbsp;memcpy(buffer, fifo->buffer + (fifo->out & (fifo->size - 1)), l);

&nbsp;&nbsp;&nbsp;&nbsp;/* then get the rest (if any) from the beginning of the buffer */
&nbsp;&nbsp;&nbsp;&nbsp;//如果l<len,那么从fifo->buffer的首部开始继续拷贝剩下的内容

&nbsp;&nbsp;&nbsp;&nbsp;//如果l == len,memcpy啥都不干

&nbsp;&nbsp;&nbsp;&nbsp;memcpy(buffer + l, fifo->buffer, len - l);

&nbsp;&nbsp;&nbsp;&nbsp;/*
&nbsp;&nbsp;&nbsp;&nbsp; * Ensure that we remove the bytes from the kfifo -before-
&nbsp;&nbsp;&nbsp;&nbsp; * we update the fifo->out index.
&nbsp;&nbsp;&nbsp;&nbsp; */


&nbsp;&nbsp;&nbsp;&nbsp;smp_mb();

&nbsp;&nbsp;&nbsp;&nbsp;//更新out(读者)的虚拟索引

&nbsp;&nbsp;&nbsp;&nbsp;fifo->out += len;

&nbsp;&nbsp;&nbsp;&nbsp;return len;
}


      从上面几个重要的函数可以看出一些特性,就是put函数能放入的数据长度永远不会大于缓冲区的长度,而fifo->in - fifo->out永远小于等于size。
get函数得到的数据永远小于等于size(这个是必然的)。
在读者/写者问题中,发生互斥问题时,使用环形队列是很好的解决方案。
fifo不太好的地方在于,想写完整的话,必须保证空间足够大,否则不能保证一次写完,特别是在中断调用过程中,如果阻塞了,然后让读者读取内容后腾出空间唤醒继续写,将会出现问题,唯一我能想到的方法就是申请大空间,以避免这种“没写完”的情况发生。不知道还有没有其它方法,写的不对的地方,大家讨论讨论,我是菜鸟,写得也仓促,刚写内核代码不久,请多指教。

[ 本帖最后由 springtty 于 2009-3-24 00:04 编辑 ]
ldd3-5-1.png

_kfifo_.pdf

145.2 KB, 下载次数: 849

评分

参与人数 2可用积分 +57 收起 理由
scutan + 30 原创内容
prolj + 27 原创内容

查看全部评分

论坛徽章:
3
金牛座
日期:2014-06-14 22:04:062015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:49:45
发表于 2009-03-23 12:30 |显示全部楼层
不错,整个pdf就好了

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
发表于 2009-03-23 13:13 |显示全部楼层
分析的比较详细。

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
发表于 2009-03-23 13:20 |显示全部楼层
考虑到一个极限的情况啊。因为这里的in和out是一直增加的,那么当存在in溢出,out还没溢出的时候,是不是有一定的问题了?
    //注意,out 始终不会大于 in,(in - out)是有效数据空间大小,size是总空间的大小

    //那么空闲的空间大小就是 size - (int - out)

    //如果请求的len大于空闲空间,就使len = size - (int - out)

    len = min(len, fifo->size - fifo->in + fifo->out);

[ 本帖最后由 Godbach 于 2009-3-23 13:27 编辑 ]

论坛徽章:
0
发表于 2009-03-23 23:51 |显示全部楼层
原帖由 Godbach 于 2009-3-23 13:20 发表
考虑到一个极限的情况啊。因为这里的in和out是一直增加的,那么当存在in溢出,out还没溢出的时候,是不是有一定的问题了?

是的,就是考虑到这种情况。
谢谢各位老大的鼓励:)

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
发表于 2009-03-24 09:56 |显示全部楼层
原帖由 springtty 于 2009-3-23 23:51 发表

是的,就是考虑到这种情况。
谢谢各位老大的鼓励:)


出现in溢出的时候:
    //如果请求的len大于空闲空间,就使len = size - (int - out)

    len = min(len, fifo->size - fifo->in + fifo->out);

这个结果还正确吗?

论坛徽章:
0
发表于 2009-03-25 12:56 |显示全部楼层
原帖由 Godbach 于 2009-3-24 09:56 发表


出现in溢出的时候:

这个结果还正确吗?

这里的in溢出而out没有溢出是不是指 in(写入)而out(读取)的指针环绕的情况。
这里应该避免这种情况,要不然就不能达到互斥访问缓冲区的目的了。

[ 本帖最后由 springtty 于 2009-3-25 13:01 编辑 ]

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
发表于 2009-03-25 14:06 |显示全部楼层
原帖由 springtty 于 2009-3-25 12:56 发表

这里的in溢出而out没有溢出是不是指 in(写入)而out(读取)的指针环绕的情况。
这里应该避免这种情况,要不然就不能达到互斥访问缓冲区的目的了。


这里的in和out不都是unsigned int类型的嘛。而且你说out 不会大于in的。

那么当出现in超过该类型的最大值时,是不是溢出了,它的值是不是回绕到比较小的无符号整数了。

论坛徽章:
0
发表于 2009-03-25 22:52 |显示全部楼层
原帖由 Godbach 于 2009-3-25 14:06 发表


这里的in和out不都是unsigned int类型的嘛。而且你说out 不会大于in的。

那么当出现in超过该类型的最大值时,是不是溢出了,它的值是不是回绕到比较小的无符号整数了。

我理解错了,以为是buffer的溢出。
你说的情况确实存在,我只考虑数学层面上的东西了。
不过如果真的发生这种情况,程序还是正确的:
        unsigned int out        = 0xfffffff0;
        unsigned int in        = 0x00000006;
       
        printf("%u\n", in - out);
gcc打印出来的值等于22。

0x00000006
-0xfffffff0
================

0x00000016 = 22

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
发表于 2009-03-25 23:10 |显示全部楼层
原帖由 springtty 于 2009-3-25 22:52 发表

我理解错了,以为是buffer的溢出。
你说的情况确实存在,我只考虑数学层面上的东西了。
不过如果真的发生这种情况,程序还是正确的:
        unsigned int out        = 0xfffffff0;
        unsigned int in        = 0x00000006;
...


buffer的话应该不会溢出了,程序里面已经控制好了。
在接着写的时候,实际可写的长度通过如下代码判断,就算in是溢出的值,应该也没有问题。
len = min(len, fifo->size - fifo->in + fifo->out);

[ 本帖最后由 Godbach 于 2009-3-25 23:27 编辑 ]
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP