Problem 54 An example for understanding Linux initcall mechanism?
Ans:
1. 源码
#include <stdio.h>
/*定义函数指针*/ typedef int (*initcall_t)(void); /*申明外部变量,在ld的脚本文件中定义*/ extern initcall_t __initcall_start, __initcall_end;
#define __initcall(fn) / static initcall_t __initcall_##fn __init_call = fn
#define __init_call __attribute__ ((unused,__section__ ("function_ptrs")))
#define module_init(x) __initcall(x); /*上述宏定义名为"__initcall_函数名"的函数指针,且将函数指针放在function_ptrs节 这个函数指针,指向fn(fn函数则放在code_segment节中)*/
#define __init __attribute__ ((__section__ ("code_segment"))) /*函数放在code_segment节*/ static int __init my_init1 (void) { printf ("my_init () #1/n"); return 0; }
static int __init my_init2 (void) { printf ("my_init () #2/n"); return 0; } module_init (my_init1);/*定义要被调用的函数指针并放到指定的节中*/ module_init (my_init2);
void do_initcalls (void) { initcall_t *call_p; /*定义函数指针变量*/ call_p = &__initcall_start;/*获取节首址*/ do { fprintf (stderr, "call_p: %p/n", call_p); (*call_p)(); ++call_p;/*32位机器上,函数指针占4bytes,增加一次就是指针便宜4bytes*/ } while (call_p < &__initcall_end); }
int main (void) { fprintf (stderr, "in main()/n"); do_initcalls (); /*调用*/ return 0; } |
2. 定义lds文件
通过命令ld --verbose可以获得默认的连接控制脚本, 即选择 "=======..."之间的文本,保存为linker.lds文件
在linker.lds文件中增加本例需要控制的语句:
将
/*定义__initcall_start符号为当前位置,即.代表当前位置*/
__initcall_start = .;
function_ptrs : { *(function_ptrs) }
__initcall_end = .;
/*上述3行代码代表function_ptrs节位于__initcall_start和__initcall_end之间*/
code_segment : { *(code_segment) }
这段代码copy到linker.lds文件的
__bss_start = .;
语句之前。
这项工作可由如下脚本完成:
#!/bin/sh outputfile=linker.lds
lineno1=`ld --verbose | tee ${outputfile} | sed '/==================================================/q' | wc -l`
sed -i "1,${lineno1}d" ${outputfile} sed -i '/==================================================/d' ${outputfile}
lineno2=`sed -n '/__bss_start/=' ${outputfile}` sed -i "${lineno2} i/__initcall_start = .;/nfunction_ptrs : { *(function_ptrs) }/n__initcall_end = .;/ncode_segment : { *(code_segment) } " ${outputfile} |
3. 编译运行
命令:
gcc -Tlinker.lds -o doinitcall doinitcall.c
其中:
-T选项告诉ld要用的连接控制脚本文件,做为链接程序的依据。格式如下:
-T commandfile 或
--script=commandfile
运行结果如下:
byd123@ubuntu:~/Desktop$ ./doinitcall
in main()
call_p: 0x804a01c
my_init () #1
call_p: 0x804a020
my_init () #2
Problem 55系统管理:Linux系统下临时文件TMP清理?
Ans:
系统使用时间长后会产生临时文件(/tmp下),需要清理,但清理的时候不推荐使用rm –rf。这样有时会引起程序的僵死。推荐使用tmpwatch工具。
tmpwatch工具从指定的目录中递归地搜索,并删除在指定时间段内没有被访问的文件。tmpwatch一般被用来清扫那些用来临时驻留文件的目录(如/tmp),tmpwatch忽略符号链接,它不会切换文件系统,而且只删除空目录和常规文件。
语法: tmpwatch [-afqv] [-test][超期时间][目录…]
补充说明:执行tmpwatch指令可删除不必要的暂存文件,您可以设置文件超期时间,单位以小时计算。
参数:
-a或--all 删除任何类型的文件
-f或--force 强制删除文件或目录,其效果类似rm指令的”-f”参数。
-q或--quiet 不显示指令执行过程
-v或--verbose 详细显示指令执行过程
-test 仅作测试,并不真的删除文件或目录
实例:tmpwatch -afv 3 /tmp