Coccinelle 使用

January 20th, 2015 by JasonLe's Tech 2,003 views

Coccinelle是一个程序的匹配和转换引擎,它提供了语言SMPL(语义补丁语言)用于指定C代码所需的匹配和转换。Coccinelle 最初是用来帮助Linux的演变,支持更改库应用程序编程接口,比如重命名一个函数,增加一个依赖于上下文的函数参数或者重新组织一个数据结构。除此之外,Coccinelle页被人用来查找或者修复系统代码的bug。

项目地址:https://github.com/coccinelle/coccinelle

安装在这里不再赘述,这里要注意的是需要安装python的devel包,否则这个程序无法运行!

$git clone https://github.com/coccinelle/coccinelle
$git tag > git checkout -b build coccinelle-1.0.0-rc21
$apt-get install python2.6-dev libpycaml-ocaml-dev libmenhir-ocaml-dev menhir ocaml-native-compilers \
ocamlduce camlp4-extra ocaml-findlib pkg-config texlive-fonts-extra
$./configure --with-python --with-menhir
$make all
$apt-get remove coccinelle (prevent conflict)
$make install

安装完毕之后,我们可以定义脚本

@search@
identifier fn,call;
statement s1,s2;
expression E1,E2;
int fd;
position p;
constant C;
@@

<+...
* fd=open@p(...);
//  ...when != fn(<+...fd...+>);
  ...when !=fd=C
* if (fd<0||...){...}
...+>   

@script:python@
p << search.p;
@@

print "%s equal expression" % (p[0].line)

之后我们可以运行这个脚本,可以快速从代码中匹配。

$spatch -sp_file demos/simple.cocci demos/simple.c -o /tmp/new_simple.c

目前这个项目的问题是文档不是很完善,期待之后这个项目的发展。这个工具吸引人的地方在于可以智能的匹配譬如i++ <=> i=i+1这种形式。

目前我们可以更多的参考/usr/local/share/coccinelle/standard.iso

 

 

Safety Engineering 关键概念学习

January 19th, 2015 by JasonLe's Tech 1,456 views

1.Safety is about understanding potential causality in systems with limited determinism.

  • Control
  • Reduce Hazard

在中文中Safety与Security 概念很类似,都是安全的含义,但是我们要分清楚,区别在于是否得到system Administrator guarantee .

Security 是在没有 guarantee保证的情况下,hacker walks into system without guarantee.

Safety 则是让系统在任何情况下under my control.

2.Fault/Error/Failure

  • Fault is a defect within the system – Software Bugs/Hardware fault/Memory Fault
  • Error is a deviation from the required operation of system or subsystem
    • A fault may lead to an error, i.e., error is a mechanism by which the fault becomes apparent
  • A system failure occurs when the system fails to perform its required function

所以总的来说,Failure对于system可能会造成灾难性后果(catastrophe)。

Functional safety is a resonable response to the increased safety needs but the first option should stay to design simple and clean systems from
the start and Say No where resonable safety is not possible.

3.Fault Tolerance and Robustness

System happened fault ,system won’t walk into fails to perform its required function This is tolerance !

When system faces hazard,failure lead system walk into unsafety state while reliability make system safety (It ‘s really hard!)

Reliability Definitions The ability of an item to perform a required function, under given environmental and operational conditions and for a stated period of
time

4.Mechanisms and Policies

  • Mechanisms specifies how it is to be done(与硬件软件结合相关,不能轻易改变)
  • Policies is what is to be done(具体算法)

The separation of mechanism and policy is important to provide flexibility to a system. If the interface between mechanism and policy is well defined, the change of policy may affect only a few parameters. On the other hand, if interface between these two is vague or not well defined, it might involve much deeper change to the system.

http://www.personal.kent.edu/~rmuhamma/OpSystems/Myos/mechanicPolicy.htm

正如kernel中的scheduler一样,这个就是Mechanisms/Policies分离的例子,Mechanisms负责切换进程实体prev,next tasks,包括context_switch,而Policies 负责根据某个策略去是选取特定的task,包括RR,CFS等等…具体对应的函数就是pick_next_task()

 

参考:

http://lxr.free-electrons.com/source/kernel/sched/core.c#L2693

cgroup 介绍(1)

January 14th, 2015 by JasonLe's Tech 2,008 views

cgroups (abbreviated from control groups) is a Linux kernel feature that limits, accounts for and isolates the resource usage (CPU, memory, disk I/O, network, etc.) of a collection of processes.

cgroup 在内核的发展是从从2007年 2.6.24内核引入的机制。经过这些年的发展,已经发展成为docker /LXC 中间力量

cgroup定义,很多中文资料已经说明非常详细了,我这里就过多赘述。

值得注意的是,cgroup最初是依靠sysfs作为与用户的控制接口,因为会存在很多hierarchy。

vfs在cgroup这里受到一些滥用,因此cgroup也积累的很多的问题,在vfs中可能会出现重名死锁。
在3.14的版本后,也就是2013之后,kernel对cgroup进行了巨大的修改。很多的数据结构都有了巨大的变化。其中提出来一种 Unified hierarchy 。

缺点[1][2]:

1)虽然这种树型结构可以带来一定的灵活性,但是在实际应用中可能存在一些问题,比如每个子系统在一个hierarchy只能有一个实例,显然freezer也只能有一个实例,freezer不得不移动去控制其他进程。
2)所有子系统绑定在hierarchy中,一旦hierarchy与具体pid绑定,控制granularity不好把握。
3)因为是树型结构,所以树的深度是无限的,这就使得在一个有限的资源中,子hierarchy可能会分配出有限资源外的资源。也使得管理更加复杂。
4)对多hierarchy支持限制了cgroup的使用,因为我们可以知道我们可以有12个hierarchy绑定12个子系统,也可以只有一个hierarhy绑定12个子统统。

在kernel 3.16中开发了Unified hierarchy。它的目的是通过使用其他的结构,同时解决了上述缺点,保持足够的灵活性,对于大多数用例

这个特性目前没有在本文中讨论。

简单提一点就是:这种新的unified hierarchy不允许remount/rename

——————-

由于从3.14后cgroup大改,放弃使用sysfs,创建一个kernfshttp://en.wikipedia.org/wiki/Kernfs_%28Linux%29

这种方式说白了就是抽出了sysfs的核心,创建了一种新的文件系统,可以进行复用。但是这个kernfs目前只是由cgroup在使用

https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=2bd59d48ebfb3df41ee56938946ca0dd30887312

这个里面对于3.14之后的更改说的比较清晰。因为使用kernfs,vfs被移除,也就是说super_block dentry, inode 和 bdi 被移除,使用cgroup_mount()直接挂载根由vfs管理的注册结构体转移到 kernfs_ops and kernfs_syscall_ops。

具体的子系统,我这里简单的提一下:

  • blkio — 这个子系统为块设备设定输入/输出限制,比如物理设备(磁盘,固态硬盘,USB 等
    等)。
  • cpu — 这个子系统使用调度程序提供对 CPU 的 cgroup 任务访问。说白了就是时间片大小!
  • cpuacct — 这个子系统自动生成 cgroup 中任务所使用的 CPU 报告。
  • cpuset — 这个子系统为 cgroup 中的任务分配独立 CPU(在多核系统)和内存节点。
  • devices — 这个子系统可允许或者拒绝 cgroup 中的任务访问设备。
  • freezer — 这个子系统挂起或者恢复 cgroup 中的任务。
  • memory — 这个子系统设定 cgroup 中任务使用的内存限制,并自动生成由那些任务使用的
    内存资源报告。
  • net_cls — 这个子系统使用等级识别符(classid)标记网络数据包,可允许 Linux 流量控制程
    序(tc)识别从具体 cgroup 中生成的数据包。
  • ns — 名称空间子系统。

比如我们要创建一个cpu核数和memory大小受限的cgroup:

1)创建一个目录mkdir

2)挂载新的文件系统,如果我们在/sys/fs/cgroup挂载,我们要先挂载一个tmpfs,因为sysfs下不允许创建文件夹,其他允许创建文件夹的文件系统,不需要挂载tmpfs

3)$mount -t cgroup -o cpuset,memory cgroup_cpu_mem  /mnt/cgroup_cpu_mem

4))我们挂载到root_cgroup的文件系统成功

5)

[lzz@localhost cgroup_cpu_mem]$ ls
cgroup.clone_children   cpuset.memory_pressure_enabled   memory.kmem.slabinfo                memory.pressure_level
cgroup.event_control    cpuset.memory_spread_page        memory.kmem.tcp.failcnt             memory.soft_limit_in_bytes
cgroup.procs            cpuset.memory_spread_slab        memory.kmem.tcp.limit_in_bytes      memory.stat
cgroup.sane_behavior    cpuset.mems                      memory.kmem.tcp.max_usage_in_bytes  memory.swappiness
cgroup_test             cpuset.sched_load_balance        memory.kmem.tcp.usage_in_bytes      memory.usage_in_bytes
cpuset.cpu_exclusive    cpuset.sched_relax_domain_level  memory.kmem.usage_in_bytes          memory.use_hierarchy
cpuset.cpus             memory.failcnt                   memory.limit_in_bytes               notify_on_release
cpuset.mem_exclusive    memory.force_empty               memory.max_usage_in_bytes           release_agent
cpuset.mem_hardwall     memory.kmem.failcnt              memory.move_charge_at_immigrate     tasks
cpuset.memory_migrate   memory.kmem.limit_in_bytes       memory.numa_stat
cpuset.memory_pressure  memory.kmem.max_usage_in_bytes   memory.oom_control

我们发现在这个root cgroup里面,包括两个系统的相关设置,分别以cpuset/memory开头,上面就是建立一个hierarchy.是一个cpusset与memory的资源集合。

6)在这个hierarchy下面,建立文件夹,就是建立新的cgroup,进入cgroup_test

7)然后这个cgroup_test中的设置都为0

8)具体每个字段含义,可以查看document https://www.kernel.org/doc/Documentation/cgroups/

9)我们简单的限定一下:

$echo 16M  > memory.memory.limit_in_bytes
$echo 1  > cpuset.cpus
$echo 0  > cpus.mems

10)这个cgroup就可以往里面添加进程了,我们可以先添加一个shell终端 echo $$ > tasks ,然后通过这个终端启动的都会添加到该cgroup!

 

 

 

[1] http://lwn.net/Articles/606699/
[2] https://www.kernel.org/doc/Documentation/cgroups/unified-hierarchy.txt

 

Python 快速学习教程

January 7th, 2015 by JasonLe's Tech 1,664 views

» Read more: Python 快速学习教程

内存管理3个层次的关系:物理内存管理(2)

January 4th, 2015 by JasonLe's Tech 1,634 views

综述 http://www.lizhaozhong.info/archives/690

之前我们在编写模块时候,对内核地址空间有一个粗略的了解,最近结合内存管理代码的学习,使得我对内核中内存管理有了更清晰的认识!

首先我们看一下http://www.lizhaozhong.info/archives/1003

这个图对kernel中kmalloc、vmalloc有比较详细的说明。

下面我们阐述一下Linux 物理内存管理

在内核中,内核认为一旦有内核函数申请内存,那么就必须立刻满足该申请内存的请求,并且这个请求一定是正确合理的。相反,对于用户态申请内存的请求,内核总是尽量延后分配物理内存,用户进程总是先获得一个虚拟内存区的使用权,最终通过缺页异常获得一块真正的物理内存。

我们之前通过代码看到,linux将内核分为三个区域DMA,NORMAL,HIGHMEM

我们要明白的是只是针对内核有这三个区域,用户空间没有!

这三个区域与体系结构相关,比如有的DMA所占用的物理内存区域是0-16M,有的是0-4GB。这个我们要结合具体的体系结构来看。

从物理内存布局来说DMA 0~16M     NORMAL  16M~896M    HIGHMEM 大于896MB

 

我们拿IA32举例:

kernel可以直接将低于896MB大小的物理内存(即ZONE_DMA,ZONE_NORMAL)映射到内核地址空间,但超出896MB大小的page frame 并不映射在内核线性地址空间的第4个GB。

1.高端内存不能全部映射到内核空间,也就是说这些物理内存没有对应的线性地址。内核此时可以使用alloc_pages()和alloc_page()来分配高端内存,因为这些函数返回页框描述符的线性地址。

2.内核地址空间的后128MB专门用于映射高端内存,否则,没有线性地址的高端内存不能被内核所访问。这些高端内存的内核映射显然是暂时映射的,否则也只能映射128MB的高端内存。当内核需要访问高端内存时就临时在这个区域进行地址映射,使用完毕之后再用来进行其他高端内存的映射。

The lower 896 MB, from 0xC0000000 to 0xF7FFFFFF, is directly mapped to the kernel physical address space, and the remaining 128 MB, from 0xF8000000 to 0xFFFFFFFF, is used on demand by the kernel to be mapped to high memory. When inuser mode, translations are only effective for the first region, thus protecting the kernel from user programs, but when in kernel mode, translations are effective for both regions, thus giving the kernel an easy way to refer to the buffers of processes—it just uses the process’ own mappings.[1]

由于要进行高端内存的内核映射,因此直接能够映射的物理内存大小只有896MB,该值保存在high_memory中。内核地址空间的线性地址区间如下图所示:

phy_addr

 

 

从这个图,我们可以清晰看出来从high_memory到4GB这段内存区域,系统可以使用vmalloc,也可以临时映射到用户空间的某一段内存。

总的来说高端内存映射有三种方式:

1)因为通过 vmalloc() ,在”内核动态映射空间”申请内存的时候,就可能从高端内存获得页面 (VMALLOC_START~VMALLOC_END)

2)持久映射:这个空间和其它空间使用同样的页目录表,通过内核页目录表方式达到内存映射

3)固定映射:

这块空间具有如下特点:
(1)每个 CPU 占用一块空间
(2)在每个 CPU 占用的那块空间中,又分为多个小空间,每个小空间大小是 1 个 page,每个小空间用于一个目的,这些目的定义在map_types.h 中的 km_type 中。

当要进行一次临时映射的时候,需要指定映射的目的,根据映射目的,可以找到对应的小空间,然后把这个空间的地址作为映射地址。这意味着一次临时映射会导致以前的映射被覆盖。通过 kmap_atomic() 可实现临时映射。

 

http://blog.csdn.net/trochiluses/article/details/9297311