问题集锦(54-55)

来源:互联网 发布:js获取input的属性值 编辑:程序博客网 时间:2024/05/16 23:59

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) }

这段代码copylinker.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

原创粉丝点击