自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Linux平臺下生成C語言數(shù)據(jù)結(jié)構(gòu)關(guān)系圖

系統(tǒng) Linux
graphviz很強(qiáng)大,可以用來畫各種各樣的圖,本文只是簡單總結(jié)一下用于畫C語言結(jié)構(gòu)體關(guān)系的方法,并做一個記錄。小編在看代碼的時候,一直想著有什么工具可以實現(xiàn)這個功能,檢索了一圈,沒找到什么很方便的工具。

作為一名Linux系統(tǒng)下的C語言開發(fā),經(jīng)常需要閱讀源碼,但是有些源碼實在是難以閱讀,各種龐大的結(jié)構(gòu)體交雜,分分鐘把你繞暈,讓你頭昏眼花,遲遲無法梳理清楚。這時候,一個能夠幫你梳理數(shù)據(jù)結(jié)構(gòu)的工具就顯得極其重要,讓你能夠很清晰的看出各個數(shù)據(jù)結(jié)構(gòu)之間的關(guān)系。

本文我們主要介紹CentOS平臺下通過python和graphviz生成數(shù)據(jù)結(jié)構(gòu)關(guān)系圖。

一、前置條件

為使用python和graphviz生成C語言的數(shù)據(jù)結(jié)構(gòu)關(guān)系圖,需提前安裝好python3,這里不做介紹。這里介紹一下繪圖工具graphviz和Linux命令行打開圖片的工具eog等。

1、安裝繪圖工具graphviz

Graphviz(Graph Visualization Software)是一個由AT&T實驗室啟動的開源工具包,能夠支持基于 DOT 腳本,文件擴(kuò)展名通常是 .gv 或 .dot 的描述繪制圖形。DOT 是一種文本圖形描述語言,將生成的圖形轉(zhuǎn)換成多種輸出格式的命令行工具,其輸出格式包括PostScript,PDF,SVG,PNG,含注解的文本等。DOT 本身非常原始,提供了一種非常簡單的描述圖形的方法,同時意味著可以在命令行終端使用,或者被其它編程語言調(diào)用(Graphviz 就可以作為一個庫使用)。這一點非常關(guān)鍵,基于 Graphviz 應(yīng)用開發(fā)者不必掌握布局的復(fù)雜算法,而是可以把精力放在業(yè)務(wù)方面,將最后的圖對象交給繪圖引擎來處理即可。

yum install graphviz -y

2、安裝命令行圖片查看工具

GNOME之眼,圖像查看器(eog)是GNOME桌面的官方圖像查看器,可以用來在服務(wù)器端查看圖片。它可以查看各種格式的單個圖像文件,以及大型圖像集合。eog可以通過插件系統(tǒng)進(jìn)行擴(kuò)展。

yum install eog -y

二、生成工具及使用方法

繪制關(guān)鍵數(shù)據(jù)結(jié)構(gòu)的關(guān)聯(lián)關(guān)系圖,可以協(xié)助我們快速理解組織架構(gòu),加速理解代碼邏輯;Linux平臺下生成C語言數(shù)據(jù)結(jié)構(gòu)關(guān)系圖主要基于python+graphviz,python和graphviz工具是基礎(chǔ),需要輔助以python腳本,才能實現(xiàn)分析數(shù)據(jù)結(jié)構(gòu)并生成用于繪圖的dot語言;之后利用graphviz根據(jù)上一步中的臨時生成文件的dot語言描述繪圖。圖形保存到xxx.svg文件中,.svg可以使用eog或者瀏覽器打開。

1、Python腳本分析工具

用于分析結(jié)構(gòu)體關(guān)聯(lián)關(guān)系的python腳本(analysis_dt.py),如下:

#!/usr/bin/python3
import os,re
prefix = '''digraph spdk {
    graph [
        rankdir = "LR"
        //splines=polyline
        //overlap=false
    ];

    node [
        fontsize = "16"
        shape = "ellipse"\r
    ];

    edge [
    ];
'''

middle_str = ''
edge_list = []
edge_string = ''
cur_indentation_level = 0
space4 = '    '
space8 = space4 + space4
space12 = space4 + space8
space16 = space4 + space12
node_database = {}
node_database['created'] = []
color_arrary = ['red', 'green', 'blue', 'black','blueviolet','brown', 'cadetblue','chocolate','crimson','cyan','darkgrey','deeppink',data_struct
with open(r'/tmp/713/data_struct', 'r') as file_input:
    tmpline = file_input.readline()
    while(tmpline):
        tmpline = re.sub(r'([^a-zA-Z0-9]const )', ' ', tmpline)
        #for match :struct device {
        if re.search(r'struct\s*([0-9a-zA-Z_\-]+)\s*\{', tmpline):
            m = re.search(r'struct\s*([0-9a-zA-Z_\-]+)\s*\{', tmpline)
            cur_indentation_level += 1
            if (cur_indentation_level == 1):
                node_name =  m.group(1)
                node_str = space4 + '\"' + node_name + '\" [\n' + space8 + 'label = \"<head> '+ node_name +'\l|\n' + space12 + '{|{\n'
                node_database['created'].append(node_name)
                try:
                    node_database[node_name]['node_str'] = node_str
                except:
                    node_database[node_name] = {}
                    node_database[node_name]['node_str'] = node_str
        #for match :struct device        *parent;
        elif re.search(r'struct\s*([0-9a-zA-Z_\-]+)\s*(\**)(\s*)([0-9a-zA-Z_\-]+)\s*;', tmpline) and cur_indentation_level > 0:
            m = re.search(r'struct\s*([0-9a-zA-Z_\-]+)\s*(\**)(\s*)([0-9a-zA-Z_\-]+)\s*;', tmpline)
            member_type = m.group(1)
            node_database[node_name]['node_str'] += space16 + '<'+ member_type + '> ' + m.group(2) +  m.group(3) +  m.group(4) + '\l|\n'
            try:
                node_database[member_type]['included_by'].append(node_name)
            except:
                try:
                    node_database[member_type]['included_by'] = []
                    node_database[member_type]['included_by'].append(node_name)
                except:
                    node_database[member_type] = {}
                    node_database[member_type]['included_by'] = []
                    node_database[member_type]['included_by'].append(node_name)
            #print('%s included by %s'%(member_type, node_database[member_type]['included_by']))
            if(member_type in node_database['created']):
                tmp_edge_str = space4 + node_name + ':' + member_type + ' -> ' + member_type + ':' + 'head'
                if not tmp_edge_str in edge_list:
                    edge_list.append(tmp_edge_str)
        #for match : void *driver_data;
        elif re.search(r'\s*[0-9a-zA-Z_\-]+\s*(\**[0-9a-zA-Z_\-]+)\s*;', tmpline) and cur_indentation_level > 0:
            m = re.search(r'\s*[0-9a-zA-Z_\-]+\s*(\**[0-9a-zA-Z_\-]+)\s*;', tmpline)
            node_database[node_name]['node_str'] += space16 + '<'+ m.group(1) + '> ' + m.group(1) +  '\l|\n'
        #for match:const char        *init_name;
        elif re.search(r'(.*)\s+(\**)(\s*)([0-9a-zA-Z_\-]+\s*);', tmpline) and cur_indentation_level > 0:
            m = re.search(r'(.*)\s+(\**)(\s*)([0-9a-zA-Z_\-]+\s*);', tmpline)
            node_database[node_name]['node_str'] += space16 + '<'+ m.group(2) + '> ' + m.group(2) + m.group(3) + m.group(4) +  '\l|\n'
        #for match:int *(*runtime_idle)(struct device *dev);
        elif re.search(r'\s*[0-9a-zA-Z_\-]+\s*\**\s*\(\s*(\**\s*[0-9a-zA-Z_\-]+)\s*\)\s*\([^\)]*\)\s*;', tmpline) and cur_indentation_level > 0:
            m = re.search(r'\s*[0-9a-zA-Z_\-]+\s*\**\s*\(\s*(\**\s*[0-9a-zA-Z_\-]+)\s*\)\s*\([^\)]*\)\s*;', tmpline)
            node_database[node_name]['node_str'] += space16 + '<'+ m.group(1) + '> (' + m.group(1) + ')\l|\n'
        #for match: };
        elif re.search(r'\s*\}\s*;', tmpline):
            if(cur_indentation_level >= 1):
                cur_indentation_level -= 1
                if (cur_indentation_level == 0):
                    node_database[node_name]['node_str'] += space12 + '}}\"\n'
                    node_database[node_name]['node_str'] += space8 + 'shape = \"record\"\n' + space4 + '];\n'
                    if 'included_by' in node_database[node_name]:
                        for parent_node in node_database[node_name]['included_by']:
                            if parent_node in node_database['created']:
                                tmp_edge_str = space4 + parent_node + ':' + node_name + ' -> ' + node_name + ':' + 'head'
                                if not tmp_edge_str in edge_list:
                                    edge_list.append(tmp_edge_str)
        tmpline = file_input.readline()

for tmpnode in node_database['created']:
    middle_str = middle_str + node_database[tmpnode]['node_str']
for i, tmpstr in enumerate(edge_list):
    edge_string += tmpstr + '[color="' + color_arrary[i%len(color_arrary)] + '"]\n'

print(prefix + middle_str + '\n' + edge_string + '}')

2、使用方法

繪制C語言結(jié)構(gòu)體關(guān)系圖方法和流程如下:

(1)把需要繪制關(guān)系圖的關(guān)鍵數(shù)據(jù)結(jié)構(gòu)復(fù)制粘貼到一個文本文件data_struct中;

(2)把python腳本中保存數(shù)據(jù)結(jié)構(gòu)的文件路徑(/tmp/713/data_struct )替換為自己的保存數(shù)據(jù)結(jié)構(gòu)的文件路徑(可自行修改腳本,通過參數(shù)傳入文件路徑);

(3)執(zhí)行命令,自動生成關(guān)系圖,命令如下:

python3 analysis_dt.py > tmpfile
dot -Tsvg tmpfile -o xxx.svg

其中第一條命令使用python分析數(shù)據(jù)結(jié)構(gòu)并生成用于繪圖的dot語言,第二條命令利用graphviz根據(jù)tmpfile中的dot語言描述繪圖。圖形保存到xxx.svg文件中,xxx可以自行命名;生成的xxx.svg文件可以在服務(wù)器的命令行使用eog打開,也可以下載到windows上使用瀏覽器打開,且可以實現(xiàn)縮放。

注意:這里也可以通過dot命令直接生成圖片格式,如下:

dot -Tsvg tmpfile -o xxx.png 即可生成xxx.png圖片。

這里以一個簡單的結(jié)構(gòu)體文本文件data_struct為Demo,查看其內(nèi)結(jié)構(gòu)體之間的關(guān)系。data_struct文本文件內(nèi)容如下:

struct ovsdb {
    char *name;
    struct ovsdb_schema *schema;
    struct ovsdb_storage *storage; /* If nonnull, log for transactions. */
    struct uuid prereq;
    struct ovs_list monitors;   /* Contains "struct ovsdb_monitor"s. */
    struct shash tables;        /* Contains "struct ovsdb_table *"s. */

    /* Triggers. */
    struct ovs_list triggers;   /* Contains "struct ovsdb_trigger"s. */
    bool run_triggers;
    bool run_triggers_now;

    struct ovsdb_table *rbac_role;

    /* History trasanctions for incremental monitor transfer. */
    bool need_txn_history;     /* Need to maintain history of transactions. */
    unsigned int n_txn_history; /* Current number of history transactions. */
    unsigned int n_txn_history_atoms; /* Total number of atoms in history. */
    struct ovs_list txn_history; /* Contains "struct ovsdb_txn_history_node. */

    size_t n_atoms;  /* Total number of ovsdb atoms in the database. */

    /* Relay mode. */
    bool is_relay;  /* True, if database is in relay mode. */
    /* List that holds transactions waiting to be forwarded to the server. */
    struct ovs_list txn_forward_new;
    /* Hash map for transactions that are already sent and waits for reply. */
    struct hmap txn_forward_sent;

    /* Database compaction. */
    struct ovsdb_compaction_state *snap_state;
};

struct ovsdb_storage {
    /* There are three kinds of storage:
     *
     *    - Standalone, backed by a disk file.  'log' is nonnull, 'raft' is
     *      null.
     *
     *    - Clustered, backed by a Raft cluster.  'log' is null, 'raft' is
     *      nonnull.
     *
     *    - Memory only, unbacked.  'log' and 'raft' are null. */
    struct ovsdb_log *log;
    struct raft *raft;

    char *unbacked_name; /* Name of the unbacked storage. */

    /* All kinds of storage. */
    struct ovsdb_error *error;  /* If nonnull, a permanent error. */
    long long next_snapshot_min; /* Earliest time to take next snapshot. */
    long long next_snapshot_max; /* Latest time to take next snapshot. */

    /* Standalone only. */
    unsigned int n_read;
    unsigned int n_written;
};

struct ovsdb_table {
    struct ovsdb_table_schema *schema;
    struct ovsdb_txn_table *txn_table; /* Only if table is in a transaction. */
    struct hmap rows;           /* Contains "struct ovsdb_row"s. */

    /* An array of schema->n_indexes hmaps, each of which contains "struct
     * ovsdb_row"s.  Each of the hmap_nodes in indexes[i] are at index 'i' at
     * the end of struct ovsdb_row, following the 'fields' member. */
    struct hmap *indexes;

    bool log; /* True if logging is enabled for this table. */
};

struct ovsdb_compaction_state {
    pthread_t thread;          /* Thread handle. */

    struct ovsdb *db;          /* Copy of a database data to compact. */

    struct json *data;         /* 'db' as a serialized json. */
    struct json *schema;       /* 'db' schema json. */
    uint64_t applied_index;    /* Last applied index reported by the storage
                                * at the moment of a database copy. */

    /* Completion signaling. */
    struct seq *done;
    uint64_t seqno;

    uint64_t init_time;        /* Time spent by the main thread preparing. */
    uint64_t thread_time;      /* Time spent for compaction by the thread. */
};

執(zhí)行結(jié)果如下:

[root@localhost 713]# vi analysis_dt.py
[root@localhost 713]# python3 analysis_dt.py > tmpfile
[root@localhost 713]# ls
analysis_dt.py  data_struct  tmpfile
[root@localhost 713]# vi tmpfile
[root@localhost 713]# dot -Tsvg tmpfile -o my.svg
[root@localhost 713]# ls
analysis_dt.py  data_struct  my.svg  tmpfile
[root@localhost 713]# eog my.svg

eog打開my.svg文件,結(jié)果如下:

圖片圖片

根據(jù)圖片可以看出,成功展現(xiàn)了結(jié)構(gòu)體之間的關(guān)系。

三、總結(jié)

graphviz很強(qiáng)大,可以用來畫各種各樣的圖,本文只是簡單總結(jié)一下用于畫C語言結(jié)構(gòu)體關(guān)系的方法,并做一個記錄。小編在看代碼的時候,一直想著有什么工具可以實現(xiàn)這個功能,檢索了一圈,沒找到什么很方便的工具。也有人推薦用draw.io,processon等,但是小編覺得這兩個工具畫結(jié)構(gòu)體關(guān)系圖終究是沒有這種通過腳本工具的方法方便。因此總結(jié)成文,希望對有需要的朋友能夠有幫助,也希望有更方便的解決方案的朋友可以反饋給小編,大家一起互幫互助,一起成長。

責(zé)任編輯:武曉燕 來源: Linux二進(jìn)制
相關(guān)推薦

2023-12-13 10:01:15

數(shù)據(jù)結(jié)構(gòu)c++編程

2010-11-15 10:24:24

啟動Oracle數(shù)據(jù)庫

2021-06-08 10:41:00

Go語言算法

2011-01-07 16:35:53

2010-01-27 15:58:35

C++數(shù)據(jù)結(jié)構(gòu)

2021-04-19 09:08:19

無向圖數(shù)據(jù)結(jié)構(gòu)

2009-08-03 17:38:12

排序算法C#數(shù)據(jù)結(jié)構(gòu)

2012-02-02 10:21:05

單鏈表nexthead

2011-04-01 09:06:49

WebDAV協(xié)作平臺

2019-08-27 10:33:12

Python數(shù)據(jù)結(jié)構(gòu)

2011-07-13 09:42:45

密碼crypt

2019-06-18 15:28:24

TomcatLinux優(yōu)化

2016-08-22 21:53:06

LinuxPython腳本

2016-08-23 10:00:28

LinuxPython腳本

2023-04-13 08:14:53

數(shù)據(jù)結(jié)構(gòu)算法存儲

2023-12-22 08:56:01

Java編程語言鏈表

2019-09-18 08:31:47

數(shù)據(jù)結(jié)構(gòu)設(shè)計

2009-08-12 18:35:17

C#數(shù)據(jù)結(jié)構(gòu)

2021-06-08 06:01:00

C++數(shù)據(jù)結(jié)構(gòu)向量和數(shù)組

2011-03-31 15:41:51

Cacti數(shù)據(jù)表結(jié)構(gòu)
點贊
收藏

51CTO技術(shù)棧公眾號