mingjiagu

  C++博客 :: 首页 :: 联系 :: 聚合  :: 管理
  5 Posts :: 0 Stories :: 1 Comments :: 0 Trackbacks

常用链接

留言簿(12)

我参与的团队

搜索

  •  

最新评论

阅读排行榜

评论排行榜

2011年12月1日 #

test243:~ # ln -d /usr/local/named/etc/named.conf /etc/named.conf
ln: creating hard link ' /etc/............. /etc/named.conf' :Invalid cross-device link
原因:
硬链接限制:1.不能跨文件系统。2,不能连接目录。只能在同一个分区建立数据关联
此处因为2个文件在不同的目录所有不能建立硬链接。


以下是网络收集的一些资料
硬链接和软连接的比较
1)在同一文件系统下,可以创建软链接或硬链接(同文件系统不同目录下也可以);
2)硬链接的文件显示大小跟原文件一样;软链接的文件很小,只有几十个字节;
3)硬链接的文件的inode跟原文件一样;软连接的文件有自己的inode,跟原文件不一样;
4)创建软链接或硬链接文件不会明显占用文件系统磁盘空间;

我们测试一下跨文件系统(/home --> /var ),是否可以建立软链接和硬链接:
软链接成功:
[root@s14 var]# ln -s /home/zjw/Wins2003.tar.gz /var/wins2003.symboliclink
硬链接失败:
[root@s14 var]# ln -b /home/zjw/Wins2003.tar.gz /var/wins2003.hardlink
ln: creating hard link `/var/wins2003.hardlink' to `/home/zjw/Wins2003.tar.gz': Invalid cross-device link

上述实验说明:
1)软链接可以跨文件系统建立; 硬链接则不可以;

硬链接(hard link)
UNIX文件系统提供了一种将不同文件链接至同一个文件的机制,我们称这种机制为链接。它可以使得单个程序对同一文件使用不同的名字。这样的好处是文件系 统只存在一个文件的副本,系统简单地通过在目录中建立一个新的登记项来实现这种连接。该登记项具有一个新的文件名和要连接文件的 inode号,文件的目录登记项就是所谓的文件硬链接硬链接,目录登记项: 文件名-->文件的inode;文件名可以有多个,但文件inode只是一个)。不论一个文件有多少硬链接,在磁盘上只有一个描述它的inode,只要该文件的链接数不为0,该文件就保持存在。硬链接不能跨越文件系统,也不能对目录建立硬链接!
硬 连接是直接建立在节点表上的(inode),建立硬连接指向一个文件的时候,会更新节点表上面的计数值。举个例子,一个文件被连接了两次(硬连接),这 个文件的计数值 是3,而无论通过3个文件名中的任何一个访问,效果都是完全一样的,但是如果删除其中任意一个,都只是把计数值减1,不会删除实际的内容的,(任何存在的 文件本身就算是一个硬连接)只有计数值变 成0也就是没有任何硬连接指向的时候才会真实的删除内容。

软链接(symbolic link)
我们把符号链接称为软链接,它是指向另一个文件的特殊文件,这种文件的数据部分仅包含它所要链接文件的路径名。软链接是为了克服硬链接的不足而引入的,软链接不直接使用inode号作为文件指针,而是使用文件路径名作为指针软链接:文件名 + 数据部分-->目标文件的路径名)。软件有自己的inode,并在磁盘上有一小片空间存放路径名。因此,软链接能够跨文件系统,也可以和目录链接!其二,软链接可以对一个不存在的文件名进行链接,但直到这个名字对应的文件被创建后,才能打开其 链接。
posted @ 2011-12-01 11:27 mousegu 阅读(15901) | 评论 (0)编辑 收藏

2011年11月15日 #

 在Linux中,可以用gcov进行代码覆盖率测试。设想一种测试场景:被测对象是一个动态链接库,另外有几个试程序,现在想知道:

(1)这些测试程序是否足够多了,即是否能覆盖所有的动态链接库中的代码;

(2)动态链接库中是否有冗余的代码,即无论什么测试都不可能走到的代码;

(3)动态链接库中的hot spot, 即那些代码是被执行最多的,以便优化

  gcov 就可以很好的满足上述3点需求。

 

步骤如下:

(1)编译测试对象

在编译被测对象时加入“-fprofile-arcs -ftest-coverage ”, 例如下面是动态链接库的源码:cal.c

#include <stdio.h>
int cal(int i)
{
        if(i<0)
                printf("\n %d", i);
        if(i<5)
                printf("\n%d", i);
        if(i>20)
                printf("\n%d", i);
        if(i>100)
                printf("\n%d", i);

        return 1;

}


编译命令如下:

gcc -fprofile-arcs -ftest-coverage  -c cal.c
gcc -fprofile-arcs -ftest-coverage  -shared -o libcal.so cal.o
编译成功后,除了产生*.so , *.o, 还将在cal.c 所在的目录中产生cal.gcno文件

(2)编译测试程序

main.c:

#include <stdio.h>

int main()
{

        int i = 0;

        for(i=0;i<45;i++)
        {
                cal(i);
        }
        return 1;
}
 

编译命令如下(假设libcal.so放在/root下):

 gcc -o main main.c -L/root -lcal

 (3)运行测试程序

./main

运行完毕后,在cal.c 所在的目录中产生cal.gcda文件

 (4)运行gcov

进入cal.c所在的目录,运行“gcov cal.c”, 会产生cal.c.gov, 内容如下:
   -:    0:Source:cal.c
        -:    0:Graph:cal.gcno
        -:    0:Data:cal.gcda
        -:    0:Runs:1
        -:    0:Programs:1
        -:    1:#include <stdio.h>
        -:    2:int cal(int i)
       45:    3:{
       45:    4:        if(i<0)
    #####:    5:                printf("\n %d", i);
       45:    6:        if(i<5)
        5:    7:                printf("\n%d", i);
       45:    8:        if(i>20)
       24:    9:                printf("\n%d", i);
       45:   10:        if(i>100)
    #####:   11:                printf("\n%d", i);
        -:   12:
       45:   13:        return 1;
        -:   14:
        -:   15:}

其中, “#####”表示该行没执行,数字表示执行的次数

 

 (4)运行lcov

lcov是一个与gcov配合使用, 可以将gcov的结果整理成HTML。可能需要安装“apt-get install lcov”

执行“lcov --directory    --capture --output-file cov.txt”

然后“genhtml  -o  results cov.txt”

最终结果会以html的形式放在result目录下。

 

需要说明的是:

(1)gcov的结果可以累加。如果上面的程序main运行多次, cal.c.gov的结果是不同的,每行执行的次数会增加。

(2)*.gcno会产生在源文件编译时所在的目录。例如cal.c所在的目录是/root/cal_lib, 动态链接库编译成功后,将该目录删除了,运行程序main时,仍然会产生/root/cal_lib并在其中生成cal.gcda.

(3)在运行gcov时, cal.c, cal.gcno和cal.gcda必须在同一目录中。

posted @ 2011-11-15 11:32 mousegu 阅读(569) | 评论 (0)编辑 收藏

2011年11月14日 #

简介
在这章里,我们将会探讨gcov实用程序,并且了解一下如何使用gcov来帮助测试与支持软件配置与优化。我们将会了解如何使用gcov来构建软件,并且理解他所提供的各种数据类型。最后,我们将探讨当执行保险测试时要避免的事情。
gcov是什么?
我们从gcov可以为我们做什么开始。gcov是一个保险测试工具。当构建一个程序时,gcov会监视一个程序的执行,并且会标识出执行了哪一行源码,哪一行没有执行。更进一步,gcov可以标识出某一行源执行的次数,这对于执行配置很有用(程序在哪里花费了大多数的时间)。因为gcov可以分辨出哪一行没有执行,这对于保险测试工具是很有用的。
我们将会讨论3.2.2版本的GNU编译器工具链的gcov的用法。
准备镜像
让我们来看一下如何为gcov的使用准备镜像。我们将会在接下来的部分提供更为详细的gcov的选项,所以这里只是作为一个介绍。我们将将会使用下面的所列的bubblesort的源码:
1: #include
2:
3: void bubbleSort( int list[], int size )
4: {
5: int i, j, temp, swap = 1;
6:
7: while (swap) {
8:
9: swap = 0;
10:
11: for ( i = (size-1) ; i >= 0 ; i— ) {
12:
13: for ( j = 1 ; j list[j] ) {
16:
17: temp = list[j-1];
18: list[j-1] = list[j];
19: list[j] = temp;
20: swap = 1;
21:
22: }
23:
24: }
25:
26: }
27:
28: }
29:
30: }
31:
32: int main()
33: {
34: int theList[10]={10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
35: int i;
36:
37: /* Invoke the bubble sort algorithm */
38: bubbleSort( theList, 10 );
39:
40: /* Print out the final list */
41: for (i = 0 ; i 使用gcov程序
现在我们准备好了我们的程序镜像了,让我们继续我们其余的部分。运行我们的程序就会生成我们在前面所讨论的数据集文件。然后我们使用我们希望进行检测的源码运行gcov程序。如下面所示:
$ ./bubblesort
...
$ gcov bubblesort.c
100.00% of 17 source lines executed in file bubblesort.c
Creating bubblesort.c.gcov.
这告诉我们在我们的例子程序中所有的源码行至少都执行了一次。我们可以通过查看所生成的bubblesort.c.gcov文件来了解每一源码行所实际运行的次数。如下面所示:
-: 0:Source:bubblesort.c
-: 0:Graph:bubblesort.gcno
-: 0:Data:bubblesort.gcda
-: 0:Runs:1
-: 0:Programs:1
-: 1:#include
-: 2:void bubbleSort(int list[],int size)
1: 3:{
1: 4: int i,j,temp,swap=1;
4: 5: while(swap)
-: 6: {
2: 7: swap=0;
22: 8: for(i=(size-1);i>=0;i--)
-: 9: {
110: 10: for(j=1;jlist[j])
-: 13: {
45: 14: temp=list[j-1];
45: 15: list[j-1]=list[j];
45: 16: list[j]=temp;
45: 17: swap=1;
-: 18: }
-: 19: }
-: 20: }
-: 21: }
1: 22:}
-: 23:int main()
1: 24:{
1: 25: int theList[10]={10,9,8,7,6,5,4,3,2,1};
-: 26: int i;
-: 27: /*Invoke the buble sort algorithm*/
1: 28: bubbleSort(theList,10);
-: 29:
-: 30: /*print out the final list*/
11: 31: for(i=0;i查看分支概率
我们也可以使用-b选项来查看程序的分支数据。这个选项会输出程序中每一个分支的频度与相应的摘要。例如,我们使用-b选项来执行gcov命令:
$ gcov -b bubblesort.c
100.00% of 17 source lines executed in file bubblesort.c
100.00% of 12 branches executed in file bubblesort.c
100.00% of 12 branches taken at least once in file bubblesort.c
100.00% of 2 calls executed in file bubblesort.c
Creating bubblesort.c.gcov.
所生成的bubblesort.c.gcov文件如下所示。
-: 0:Source:bubblesort.c
-: 0:Graph:bubblesort.gcno
-: 0:Data:bubblesort.gcda
-: 0:Runs:1
-: 0:Programs:1
-: 1:#include
-: 2:void bubbleSort(int list[],int size)
function bubbleSort called 1 returned 100% blocks executed 100%
1: 3:{
1: 4: int i,j,temp,swap=1;
4: 5: while(swap)
branch 0 taken 67%
branch 1 taken 33% (fallthrough)
-: 6: {
2: 7: swap=0;
22: 8: for(i=(size-1);i>=0;i--)
branch 0 taken 91%
branch 1 taken 9% (fallthrough)
-: 9: {
110: 10: for(j=1;jlist[j])
branch 0 taken 50% (fallthrough)
branch 1 taken 50%
-: 13: {
45: 14: temp=list[j-1];
45: 15: list[j-1]=list[j];
45: 16: list[j]=temp;
45: 17: swap=1;
-: 18: }
-: 19: }
-: 20: }
-: 21: }
1: 22:}
-: 23:int main()
function main called 1 returned 100% blocks executed 100%
1: 24:{
1: 25: int theList[10]={10,9,8,7,6,5,4,3,2,1};
-: 26: int i;
-: 27: /*Invoke the buble sort algorithm*/
1: 28: bubbleSort(theList,10);
call 0 returned 100%
-: 29:
-: 30: /*print out the final list*/
11: 31: for(i=0;i
2:
3: int main()
4: 1 {
5: 1 int a=1, b=2;
6:
7: 1 if (a == 1) {
8: 1 printf("a = 1\n");
9: } else {
10: ###### printf("a != 1\n");
11: }
12:
13: 1 if (b == 1) {
14: ###### printf("b = 1\n");
15: } else {
16: 1 printf("b != 1\n");
17: }
18:
19: 1 return 0;
20: }
当这个程序运行时,gcov实用程序也会向标准输出输出相应的信息。他会显示可能执行的源码行的行数以及实际运行的百分比。
$ gcov incomptest.c
77.78% of 9 source lines executed in file incomptest.c
Creating incomptest.c.gcov.
$
如果我们的例子程序有多个函数,我们可以通过使用-f选项来查看每一个函数的执行情况。如下面的我们以bubbleSort程序所进行的演示:
$ gcov -f bubblesort.c
100.00% of 11 source lines executed in function bubbleSort
100.00% of 6 source lines executed in function main
100.00% of 17 source lines executed in file bubblesort.c
Creating bubblesort.c.gcov.
$
gcov可用的选项
gcov程序调用的格式为:
gcov [options] sourcefile
其可用的选项如下:
选项 目的
-v,-version 打印版本信息
-h,-help 打印帮助信息
-b,-branch-probabilities向输出文件输出分支频度
-c,-branch-counts 打印分支计数而不是分支频度
-n,-no-output 不创建gcov输出文件
-l,-long-file-names 创建长文件名
-f,-function-summaries 打印每一个函数的概要
-o,-object-directory .bb,.bbg,.da文件存放的目录
从上面这个表中,我们可以看到一个单个字符选项,以及一个长选项。当从命令行中使用gcov命令时短选项是比较有用的,但是当gcov是Makefile的一个部分时,应使用长选项,因为这更易于理解。
当了解gcov程序的版本信息时,可以使用-v选项。因为gcov是与一个指定的编译器工具链联系在一起的(实际上是由gcc工具链而构建的),gcc版本与gcov的版本是相同的。
gcov程序的简介以及选项帮助可以用-h选项来进行显示。

undefined reference to _gcov_init问题
On the link line you have to either
a) add -fprofile-arcs
b) add -lgcov
posted @ 2011-11-14 11:27 mousegu 阅读(1943) | 评论 (1)编辑 收藏

2011年10月10日 #

CLI Command XML

It is known that Clish can execute the command correctly by defining the right xml files .Here is the schema about CLI command xml I studied below:

For XML syntax can be understood by Clish, we must put the following at the top of our XML files.

XML Syntax

A entire xml file should express itself with right syntax. A complete xml file should contain  the following tags below:

Description

The VIEW is a top level XML element and it may contain one or more COMMAND XML elements.  These COMMAND   elements define the configuration mode commands.

Attributes

name   An identifier for the view

 prompt The prompt  will be  displayed on the CLI when this view is entered on the CLI.

Description

This XML element is used to indicate the name of the CLI command.

Attributes

name  The name means that the command name of The CLI command.

help The help text about the command.

view – The CLI view that will be switched to when the command is executed. This is used for the mode-change commands.

Example

When the command named-view executed, Clish will switch to the view named-view and user can go on configuring by using the command defined in the view named-view. Here is the result I used the command named-view: When I execute this command, it will enter the view “named-view” and I can used the command show defined in named-view to go on displaying the info on the screen .

PARAM

Description

This xml element is used as the value the CLI command will expect and CLI command may have more than one parameters.

Attributes

name – The name of the parameter

help – The help text about the parameter

ptype – A CLI command type. This element can enforce us to input the right parameter value, otherwise we can’t execute the command correctly. The parameter is defined in the types.xml.

Example

There are four parameters behind the command clock set. When we input right parameters, it only can execute the command correctly. Once we input incorrect parameters, Clish will remind us to input the right parameters. Here is the executed result below:

When I input the command clock set without any parameter, Clish will remind me to input the time. This command clock set need four parameters behind it, if we miss any one, this command can’t be executed.

Description

This element indicates that it is a new CLI type and used to enforce the value the parameter must have, it is associated with ptype of the element PARAM.

Attributes

name The name of the CLI type

method – “select” from a list, “integer”, not mandatory

pattern  a regex pattern enforcing user to input the right parameters

help – the help text about PTYPE

Example

 

The PTYPE DAY_MONTH will ask user to enter the value of day of month from 0 to 31, other value will be wrong. The PTYPE MONTH_NAME will require us to input the value of month from a list of 12 months. The same meaning with the PTYE TZ_NAME, YYYY_YEAR and TIME_HOURS.                                                                     

 

From the executed result above, when I try to input the value of day of moth with ‘32’, Clish reminds me input the value from 0 to 31.

ACTION

Description

The XML element ACTION is a sub-element of COMMAND. The ACTION XML element is used to specify the action associated with a CLI command. After the command is executed, the ACTION will be executed.

Attributes

None

Example

The command clock timezone above defines the time zone and time zone name. This ACTION calls echo shell to display time zone on the screen. Here is the executed result below:

When I executed the command clock timezone correctly, the ACTION called echo shell to display the time zone information I just configured on the screen.

 

 

posted @ 2011-10-10 09:49 mousegu 阅读(952) | 评论 (0)编辑 收藏

2011年7月21日 #

memcpy和memmove的区别
memcpy()和memmove()都是C语言中的库函数,在头文件string.h中,其原型分别如下:

void*memcpy(void *dst, const void *src, size_t count);
void*memmove(void *dst, const void *src, size_t count);

它们都是从src所指向的内存中复制count个字节到dst所指内存中,并返回dst的值。当源内存区域和目标内存区域无交叉时,两者的结果是一样的,但如果有交叉呢?先看下图:

图的上半部分为源内存区域在目标内存区域右边,下半部分为源内存区域在目标区域左边,源内存区域和目标内存区域都有交叉。

memcpy()是从src的起始部分开始复制,所以虽然第一种情况下没有问题,但如果遇到第二种情况,则会发生错误,如图所示,后两个字节在被复制前已经被覆盖掉了。而memmove()则由于采用了不同的复制机制,所以可以正确处理第二种情况。

VS.NET2003中所附源码如下(有删):

void * __cdecl memcpy (void * dst, const void* src,size_t count)
{
void * ret = dst;

/*
* copy from lower addresses to higher addresses
*/

while (count--) {
*(char *)dst = *(char *)src;
dst = (char *)dst + 1;
src = (char *)src + 1;
}

return(ret);
}

void * __cdecl memmove (void * dst, const void* src,size_t count)
{
void * ret = dst;

if (dst <= src || (char *)dst >= ((char *)src + count)) {
/*
* Non-Overlapping Buffers
* copy from lower addresses to higher addresses
*/

while (count--) {
*(char *)dst = *(char *)src;
dst = (char *)dst + 1;
src = (char *)src + 1;
}
}
else {
/*
* Overlapping Buffers
* copy from higher addresses to lower addresses
*/

dst = (char *)dst + count - 1;
src = (char *)src + count - 1;

while (count--) {
*(char *)dst = *(char *)src;
dst = (char *)dst - 1;
src = (char *)src - 1;
}
}

return(ret);
}

posted @ 2011-07-21 21:55 mousegu 阅读(392) | 评论 (0)编辑 收藏