kk Blog —— 通用基础


date [-d @int|str] [+%s|"+%F %T"]
netstat -ltunp
sar -n DEV 1

vim+cscope

Ctags:
按下"Ctrl+]“, 光标会自动跳转到其定义处
按下"ctrl+t”, 返回上一个查找的地方


1
2
yum install cscope
sudo apt-get install cscope

生成Cscope数据

1
cscope –Rbq

Cscope相关命令

所有的cscope命令都是通过向主cscope命令”:cscope”传递参数选项。她最短的缩写是”:cs”。”:scscope”命令也做同样的事情并且同时会横向分隔窗口(简称:”scs”)。

可用的缩写有:

add :增加一个新的cscope数据库/链接库

使用方法:

1
:cs add {file|dir} [pre-path] [flags]

其中:
[pre-path] 就是以-p选项传递给cscope的文件路径,是以相对路径表示的文件前加上的path,这样你不要切换到你数据库文件所在的目录也可以使用它了。
[flags] 你想传递给cscope的额外旗标

实例:

1
2
3
:cscope add /root/code/vimtest/ftpd
:cscope add /project/vim/cscope.out /usr/local/vim
:cscope add cscope.out /usr/local/vim –C

find :查询cscope。所有的cscope查询选项都可用除了数字5(“修改这个匹配模式”)。

使用方法:

1
:cs find {querytype} {name}

其中: {querytype} 即相对应于实际的cscope行接口数字,同时也相对应于nvi命令:

1
2
3
4
5
6
7
8
0或者s   —— 查找这个C符号
1或者g   —— 查找这个定义
2或者d   —— 查找被这个函数调用的函数(们)
3或者c   —— 查找调用这个函数的函数(们)
4或者t   —— 查找这个字符串
6或者e   —— 查找这个egrep匹配模式
7或者f   —— 查找这个文件
8或者i   —— 查找#include这个文件的文件(们)

实例:(#号后为注释)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
:cscope find c ftpd_send_resp    # 查找所有调用这个函数的函数(们)
:cscope find 3 ftpd_send_resp # 和上面结果一样

:cscope find 0 FTPD_CHECK_LOGIN   # 查找FTPD_CHECK_LOGIN这个符号
执行结果如下:
Cscope tag: FTPD_CHECK_LOGIN                   
   #   line  filename / context / line
   1     19  ftpd.h <<GLOBAL>>
	         #define FTPD_CHECK_LOGIN() \
   2    648  ftpd.c <<ftpd_do_pwd>>
	         FTPD_CHECK_LOGIN();
   3    661  ftpd.c <<ftpd_do_cwd>>
	         FTPD_CHECK_LOGIN();
Enter nr of choice (<CR> to abort):

然后输入最前面的序列号即可。

help :显示一个简短的摘要。

使用方法:

1
:cs help

kill :杀掉一个cscope链接(或者杀掉所有的cscope链接)

使用方法:

1
:cs kill {num|partial_name}

为了杀掉一个cscope链接,那么链接数字或者一个部分名称必须被指定。部分名称可以简单的是cscope数据库文件路径的一部分。要特别小心使用部分路径杀死一个cscope链接。假如指定的链接数字为-1,那么所有的cscope链接都会被杀掉。

reset:重新初始化所有的cscope链接。

使用方法:

1
:cs reset

show:显示cscope的链接

使用方法:

1
:cs show

假如你在使用cscope的同时也使用ctags,|:cstag|可以允许你在跳转之前指定从一个或另一个中查找。例如,你可以选择首先从cscope数据库中查找,然后再查找你的tags文件(由ctags生成)。上述执行的顺序取决于|csto|的值。
|:cstag|当从cscope数据库中查找标识符时等同于“:cs find g”。
|:cstag|当从你的tags文件中查找标识符时等同于“|:tjump|”。

mod_timer会切换cpu

https://lkml.org/lkml/2009/4/16/45

Ingo, Thomas, all,

In an SMP system, tasks are scheduled on different CPUs by the scheduler, interrupts are managed by irqbalancer daemon, but timers are still stuck to the CPUs that they have been initialised. Timers queued by tasks gets re-queued on the CPU where the task gets to run next, but timers from IRQ context like the ones in device drivers are still stuck on the CPU they were initialised. This framework will help move all ‘movable timers’ using a sysctl interface.

kernel/timer.c 中 __mod_timer函数的部分patch:

1
2
3
4
5
6
7
8
9
10
11
+    cpu = smp_processor_id();
+ if (get_sysctl_timer_migration() && idle_cpu(cpu) && !pinned) {
+#if defined(CONFIG_NO_HZ) && (CONFIG_SMP)
+     preferred_cpu = get_nohz_load_balancer();
+#endif
+     if (preferred_cpu >= 0)
+         cpu = preferred_cpu;
+ }
+
+ new_base = per_cpu(tvec_bases, cpu);
+

也就是说:如果当前进程是idle(函数idle_cpu(cpu)判定),那么在mod_timer时会根据cpu的struct rq runqueues;中的 struct sched_domain *sd; 来选一个不是idle的cpu,然后把timer移到他上去。如果都是idle,就还在本cpu。
禁用该功能可以 echo 0 > /proc/sys/kernel/timer_magration,默认的启用是1。

也就是说:系统默认状态下mod_timer有可能会mod_timer到其他cpu上。


但是基本只有softirq时(如 /blog/2015/01/14/debug-softirq-time-count/),这时会的当前进程就是idle,但cpu实际并不空闲。这样的话softirq的timer在mod_timer时,会被加到其他cpu的定时器队列。如果这些timer是不允许切换cpu的(如对per_cpu变量的操作),那么就会产生bug。

中断时间统计

软中断运行在中断上下文,不会被抢占调度,只会被硬中断打断,但硬中断退出时还是继续执行没结束的软中断。

因为软中断不是运行在进程上下文,不具备被调度的前提,也不具备统计运行时间。系统是将softirq的时间加到当前被他打断的进程上(还是不统计softirq时间???有待学习)。

如果当前系统只运行数据包的接收服务,那么系统很可能显示的是100%idle,因为被softirq打断的进程就是idle。

如果softirq足够多,导致启动了ksoftirqd进程来协助处理,那么softirq的时间会被记到ksoftirqd的进程上,显示有“有点正常”了。

这样就会出现:当cpu个数充足时显示100%idle,然后减少到一半cpu就显示X%si。也就是说显示100%idle是不对,应该是近似的(x/2)%si