你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

linux的 “行缓冲”机制

[复制链接]
gaosmile 发布时间:2021-3-1 15:21
1. 前言
“我的人品有这么差吗!半个小时Linux都没调度我的线程!”。
前些日子同事抱怨,“linux是多线程系统,每个线程都有一个时间片,为什么我的程序似乎一直没被调度”,随即给我演示执行过程。大致归纳成下面的代码逻辑。
程序启动后仅仅输出一行“run”,然后就没有然后了,喝着咖啡、嗑着瓜子、带薪摸鱼,屏幕上干干净净。理想状态下每10秒执行任务完毕后输出“do”。
分析代码逻辑可知 “推断” 代码是否被运行的依据是屏幕上输出 “do” ,”而这真的科学吗?答案是否定的,linux有着雨露均沾的调度系统,很难做到半小时没被调度。问题就出在linux的 “行缓冲”机制 。
  1. & h$ a8 p* ]8 B  @0 _7 N; n
  2. void main()
    , q3 F6 K! I& u) I- E
  3. {2 b4 N  E3 j" ?. p
  4.     printf("run\n");" x' m) R" }+ V, {5 q+ \
  5.     while(1) {
    . x- M: |& p/ [4 \- x
  6.         sleep(10);7 Z0 a% `* J+ p) }
  7.         do_thing();
    5 b' ?- Z$ M, t3 o
  8.         printf("do");
    2 v& ^9 B! \7 u$ D" @* x
  9.     }
    7 j$ k( i% o8 K0 r/ L+ `
  10. }
复制代码

7 g7 v* r; n% v+ p
! G! A4 m* o2 |" b& \
2. 行缓冲

$ E0 b$ M( A" m
上文的printf输出目标设备由STDOUT指定,STDOUT可能指向115200波特率的串口设备,也可能指向本地图形设备,相对于CPU而言他们的速度要慢上几个数量级。都是为了提高机器或者程序的性能、提高CPU利用率。协调高速设备和低速设备之间速度的不匹配,操作系统默认在标准I/O上采用行缓冲机制,printf的内容首先存储在内存,当缓冲填满或检测到换行符’’时则输出到目标设备。
Linux上这个行缓冲默认是1024Byte,每10s输出do占用2Byte,为了等待缓冲填满需要等待81min。
知道原理后解决方法就简单了。
方法1:fflush强制刷新标准输出stdout

  1. 7 Z) P6 g5 X! p3 G* v4 Y' R
  2. #include ) R! q' M! }2 K8 l2 m
  3. void main()
    3 ~* A' |1 ~$ Q3 W- b
  4. {' F0 P0 Z0 I# X  q3 y( T
  5.     printf("run\n");
    5 m, E4 J7 P# d( x2 A
  6.     while(1) {/ v; u8 J; ]5 I! ]
  7.         sleep(10);, D7 z0 \; n9 ^  }1 s% {
  8.         do_thing();
      G; w& z. m  }" W2 K  y7 P
  9.         fflush(stdout);
    4 c2 ~. F& |. Z; i7 B/ P7 w' |+ c
  10.         printf("do");9 Q' |( V9 O" \! L- C
  11.     }
    - P: E8 U( T' W" z
  12. }
    0 x' j3 M& y1 ~5 I* x! r& {' a
复制代码

% Y7 u! K) k5 M, Z6 J
方法2:输出“换行符”
- y. Y2 o2 @+ `3 \- S- i( B

  1. - i8 _: j. C3 e  B/ }- ]7 P$ d
  2. #include 0 z& V9 c% @6 }+ `1 {
  3. void main()7 G4 n  Y' i8 V- _4 v
  4. {+ h8 J5 K3 f; V) o! ]8 y7 ]
  5.     printf("run\n");
    ( o8 t1 p+ c% k7 E! s
  6.     while(1) {7 p2 l; p% N+ z8 u8 R9 W4 |
  7.         sleep(10);# q9 F" s4 d* f, N7 D, c$ s$ n' K
  8.         do_thing();
    % C) u' _0 n. H9 l7 S. e% p- n
  9.         printf("do\n");
    . w; B/ p; a& A6 z9 V) k- e
  10.     }, n; N! e, }# x( B' a& a; A  J
  11. }
复制代码

3 D; F: h: `4 b- r3 Y
赞 收藏 评论0 发布时间:2021-3-1 15:21

举报

0个回答

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版