Linux内核的percpu变量如何精确取值?

我选择signed int类型的percpu变量作为Linux内核中的半连接数量的统计值,我没有选择atomic类型的全局变量,我更是没有采用spinlock去保护一个一般的unsigned int类型的全局变量。

之所以选择signed int类型的percpu变量是因为要考虑到连接的处理在不同CPU之间的迁移。

到此为止,percpu变量的一切都很完美,轻量且无锁的操作是它作为统计计数器的最大优势。作为统计计数器,我们在读数的时候是允许一定的误差的,所以我们一般采用无锁的方式去读数:

for_each_possible_cpu(i) {
    res += per_cpu_ptr(ptr, i);
}

我们知道,以上语句的执行是需要时间的,无论遍历所有CPU有多快,但也是需要时间的,在这段时间内,percpu变量就可能发生遍历累加逻辑在执行期间无法捕捉的变化。

幸亏这些统计值是给人来读的,而人读这些统计值的目的是通过数值去导出一些规律,通常对数据分辨率的要求不会达到毫秒以下。

然而,如果内核需要这些值怎么办?

比如内核依照这些变量的值来执行是否释放一个数据对象的逻辑:

for_each_possible_cpu(i) {
    res += per_cpu_ptr(ptr, i);
}
if (res == 0) 
    free_something(...);

以上的代码显然是危险⚠️的,那么怎么办?

很简单,一把读写锁即可。但是和通常的读写锁的用法正好相反:

  • 更新percpu变量时拿read锁。
  • 读取percpu变量时拿write锁。

更新逻辑如下:

signed int *per_cpu_counter = per_cpu_ptr(..., this_cpu);
...
read_lock(&percpu_wrlock);
*per_cpu_counter ++;
read_unlock(&percpu_wrlock);

读取逻辑如下:

write_lock(&percpu_wrlock);

for_each_possible_cpu(i) {
    res += per_cpu_ptr(ptr, i);
}
if (res == 0) 
    free_something(...);

write_unlock(&percpu_wrlock);

虽然说,read/write lock期间会禁用抢占,并且会插入屏障,但具体到特定的体系结构以及具体的Linux内核平台,这些看似会 影响性能 的操作大多数都是可以忽略的,比方说,大部分的服务器内核都是关闭内核抢占选项来编译的。


如果从总体上看而不是抠细节的话,遍历所有CPU并取出percpu变量累加的过程是非常快的,至少这是一个

O

(

1

)

O(1)

O(1)操作,更何况,绝大多数机器的CPU基本也就是3位数量级以下,所以这个

O

(

1

)

O(1)

O(1)的常数值本身也是非常小的。

经理不待见trick,经理也不待见遍历,哪怕for一个20也不行。

2007年夏天,经理说第一次慢,经理不管DNS,所以一个工人就把北京一个机房的服务器IP写死在代码里了。后来这个服务器搬迁了,这个工人也离职了,事情到了我这里,我查到了这个硬编码,但是我很认同这种做法,虽然我更倾向于用配置文件而不是代码的宏定义…

我在配置文件里写死了20个常用的IP地址,前10个是服务器的IP,后10个是我首选的10个DNS,然后就上线了,效果真不错!

但是经理要看代码,经理看见了一个for,for了20个IP,经理说这个循环是耗时的,经理非要让我改,我百口难辩,于是,我改成了下面的样子:

if (是IP1)
    ...
else if (是IP2)
    ...
else if (是IP3)
    ...
else if (是IP4)
    ...
else if (是IP5)
    ...
else if (是IP6)
    ...
    ...
else if (是IP20)
    ...
else 
    ...

OK,消除了循环,增加了代码量,大家唱着歌,下班了。


浙江温州皮鞋湿,下雨进水不会胖。

原文链接: https://blog.csdn.net/dog250/article/details/105087167

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    Linux内核的percpu变量如何精确取值?

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/406063

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年4月26日 上午9:36
下一篇 2023年4月26日 上午9:36

相关推荐