实现一个进程树工具pstree

代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct node {
    int          pid;
    int          ppid;
    struct node *child;
    struct node *next;
    char         str[0];
} NODE;

static NODE *head = NULL;
static NODE *tail = NULL;

static int cmpWord(char *str, char *word){
    while(word[0]){
        if(str[0] != word[0]){
            return str[0] - word[0];
        }
        str++;
        word++;
    }
    if((str[0] <= ' ') || (str[0] > '~')){
        return 0;
    }
    return str[0];
}

static int getIndexByWord(char *str, char *word){
    int index = 0;
    int flag = 0; //0=单词外,1=单词内。
    while(str[0]){
        if((str[0] > ' ') && (str[0] <= '~')){
            if(flag == 0){
                flag = 1;
                if(cmpWord(str, word) == 0){
                    return index;
                }
            }
        }else{
            if(flag == 1){
                flag = 0;
                index++;
            }
        }
        str++;
    }
    return -1;
}

static char *getWordByIndex(char *str, int index){
    int num = 0;
    int flag = 0; //0=单词外,1=单词内。
    while(str[0]){
        if((str[0] > ' ') && (str[0] <= '~')){
            if(flag == 0){
                flag = 1;
                if(num == index){
                    return str;
                }
            }
        }else{
            if(flag == 1){
                flag = 0;
                num++;
            }
        }
        str++;
    }
    return NULL;
}

static void putNode(NODE *node){
    node->next = NULL;
    if(head == NULL){
        head = node;
    }else{
        tail->next = node;
    }
    tail = node;
}

static NODE *getNodeByPPID(int ppid){
    if(head == NULL){
        return NULL;
    }
    NODE *ret = head;
    if(head->ppid == ppid){
        head = head->next;
        return ret;
    }
    
    NODE *last = ret;
    ret = ret->next;
    
    while(ret){
        if(ret->ppid == ppid){
            last->next = ret->next;
            return ret;
        }else{
            last = ret;
            ret = ret->next;
        }
    }
    return NULL;
}

static NODE *makeTree(int pid){
    NODE *headNode = NULL;
    NODE *last;
    NODE *node;
    while((node = getNodeByPPID(pid))){
        node->child = makeTree(node->pid);
        node->next  = NULL;
        if(headNode){
            last->next = node;
        }else{
            headNode = node;
        }
        last = node;
    }
    return headNode;
}

static void dumpTree(NODE *node, char *headStr){
    char *buffer = alloca(strlen(headStr)+8);
    NODE *freeNode;
    while(node){
        if(node->next){
            printf("%s|-<%d> %s", headStr, node->pid, node->str);
        }else{
            printf("%s+-<%d> %s", headStr, node->pid, node->str);
        }
        if(node->child){
            if(node->next){
                sprintf(buffer, "%s|  ", headStr);
            }else{
                sprintf(buffer, "%s   ", headStr);
            }
            dumpTree(node->child, buffer);
        }else{
            if(node->next == NULL){
                printf("%s\n", headStr);
            }
        }
        freeNode = node;
        node = node->next;
        free(freeNode);
    }
}

////////////////////////////////////////////////////////////////////////////////

int main(int argc, char *argv[]){
    if(argc < 2){
        printf("Usage: ps -ef | %s -v\n", argv[0]);
        return -1;
    }else{
        if(strcmp(argv[1], "-v")){
            printf("Usage: ps -ef | %s -v\n", argv[0]);
            return -1;
        }
    }
    
    char lineBuffer[4096];
    if(fgets(lineBuffer, 4096, stdin) == NULL){
        return -2;
    }
    
    int indexOfPID  = getIndexByWord(lineBuffer, "PID");
    int indexOfPPID = getIndexByWord(lineBuffer, "PPID");
    int indexOfCMD  = getIndexByWord(lineBuffer, "CMD");
    if((indexOfPID < 0) || (indexOfPPID < 0) || (indexOfCMD < 0)){
        return -3;
    }
    
    int length;
    char *str;
    NODE *node;
    while(fgets(lineBuffer, 4096, stdin)){
        str = getWordByIndex(lineBuffer, indexOfCMD);
        length = strlen(str);
        node = malloc(sizeof(NODE) + length + 8);
        if(node){
            node->pid   = atoi(getWordByIndex(lineBuffer, indexOfPID));
            node->ppid  = atoi(getWordByIndex(lineBuffer, indexOfPPID));
            node->child = NULL;
            node->next  = NULL;
            memcpy(node->str, str, length+1);
            putNode(node);
        }
    }
    
    node = makeTree(0);
    printf(" <0>\n");
    dumpTree(node, "  ");
    return 0;
}

用法:
ps -ef | ./pstree -v
运行效果:

 <0>
  |-<1> /sbin/init splash
  |  |-<282> /lib/systemd/systemd-journald
  |  |-<297> /lib/systemd/systemd-udevd
  |  |-<684> /usr/sbin/haveged --Foreground --verbose=1 -w 1024
  |  |-<685> /lib/systemd/systemd-timesyncd
  |  |-<686> /usr/sbin/rsyslogd -n -iNONE
  |  |-<687> /usr/sbin/smartd -n
  |  |-<689> /usr/sbin/alsactl -E HOME=/run/alsa -s -n 19 -c rdaemon
  |  |-<690> /usr/sbin/cron -f
  |  |-<691> /usr/sbin/deepin-elf-verify
  |  |-<692> /usr/bin/deepin-user-experience-daemon
  |  |-<694> /opt/todesk/bin/todeskd -f /opt/todesk/config/todeskd.conf
  |  |-<696> /usr/sbin/uos-resource-manager
  |  |-<698> /usr/lib/udisks2/udisksd
  |  |-<700> /usr/lib/accountsservice/accounts-daemon
  |  |-<701> /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only
  |  |-<702> /sbin/wpa_supplicant -u -s -O /run/wpa_supplicant
  |  |-<703> /usr/sbin/NetworkManager --no-daemon
  |  |-<704> /usr/sbin/ModemManager --filter-policy=strict
  |  |-<707> /lib/systemd/systemd-logind
  |  |-<762> /usr/lib/policykit-1/polkitd --no-debug
  |  |-<787> /usr/bin/deepin-devicemanager-server
  |  |-<1104> /usr/sbin/lightdm
  |  |  |-<10979> /usr/lib/xorg/Xorg -background none :0 -seat seat0 -auth /var/run/lightdm/root/:0 -nolisten tcp vt1 -novtswitch
  |  |  +-<11073> lightdm --session-child 12 19 20
  |  |     +-<11257> /usr/bin/startdde
  |  |        |-<11466> /bin/sh /usr/bin/kwin_no_scale
  |  |        |  +-<11476> kwin_x11 -platform dde-kwin-xcb:appFilePath=/usr/bin/kwin_no_scale
  |  |        |  
  |  |        |-<11467> /usr/lib/deepin-daemon/dde-session-daemon
  |  |        |-<11473> /usr/bin/dde-desktop
  |  |        |-<11525> /usr/bin/dde-dock -r
  |  |        |-<11728> /usr/lib/polkit-1-dde/dde-polkit-agent
  |  |        |-<11879> /usr/bin/dde-clipboard
  |  |        |-<11883> /usr/lib/deepin-daemon/dde-calendar-service
  |  |        |-<11884> /usr/bin/DeepinVoiceWakeuper
  |  |        |-<11889> /usr/lib/deepin-deepinid-daemon/deepin-deepinid-daemon
  |  |        |-<11893> /usr/lib/geoclue-2.0/demos/agent
  |  |        |-<11904> /usr/bin/deepin-defender-daemonservice
  |  |        |-<11905> dde-printer-helper
  |  |        |-<11908> /usr/lib/at-spi2-core/at-spi-bus-launcher --launch-immediately
  |  |        |  +-<11929> /usr/bin/dbus-daemon --config-file=/usr/share/defaults/at-spi2/accessibility.conf --nofork --print-address 3
  |  |        |  
  |  |        |-<11911> DeepinAIAssistant
  |  |        +-<12197> deepin-terminal
  |  |           +-<12205> /bin/bash
  |  |           
  |  |-<1326> /usr/lib/deepin-daemon/dde-system-daemon
  |  |  +-<1398> rfkill event
  |  |  
  |  |-<1342> /usr/lib/deepin-deepinid-daemon/deepin-sync-helper
  |  |-<1362> /usr/lib/deepin-daemon/backlight_helper
  |  |-<1412> /bin/sh /usr/bin/deepin-anything-tool-ionice --dbus
  |  |  +-<1413> deepin-anything-tool --dbus
  |  |  
  |  |-<1414> /usr/bin/dbus-udcp
  |  |-<1432> /usr/bin/deepin-anything-monitor
  |  |-<1433> /usr/lib/upower/upowerd
  |  |-<1593> /usr/lib/deepin-authenticate/deepin-authentication
  |  |-<1612> /usr/sbin/nmbd --foreground --no-process-group
  |  |-<1614> /usr/lib/deepin-daemon/uos-license-agent
  |  |-<1615> /usr/bin/udcpg
  |  |-<1784> /lib/systemd/systemd --user
  |  |  |-<1785> (sd-pam)
  |  |  |-<1840> /usr/bin/dbus-daemon --session --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only
  |  |  |-<1943> /usr/lib/gvfs/gvfsd
  |  |  |-<1948> /usr/lib/gvfs/gvfsd-fuse /run/user/1000/gvfs -f -o big_writes
  |  |  |-<2059> /usr/lib/dconf/dconf-service
  |  |  |-<2196> /usr/lib/gvfs/gvfs-udisks2-volume-monitor
  |  |  |-<2200> /usr/lib/gvfs/gvfs-mtp-volume-monitor
  |  |  |-<2276> /usr/lib/gvfs/gvfs-gphoto2-volume-monitor
  |  |  |-<2312> /usr/lib/gvfs/gvfs-goa-volume-monitor
  |  |  |-<2337> /usr/lib/gvfs/gvfs-afc-volume-monitor
  |  |  |-<11391> /usr/lib/deepin-daemon/dde-osd
  |  |  |-<11508> /usr/bin/deepin-wm-dbus
  |  |  |-<11545> /usr/bin/kglobalaccel5
  |  |  |-<11677> /usr/lib/x86_64-linux-gnu/bamf/bamfdaemon
  |  |  |-<11768> /usr/bin/pulseaudio --daemonize=no
  |  |  |-<11769> /usr/lib/deepin-turbo/booster-dtkwidget --systemd
  |  |  |  +-<11774> booster [dtkwidget]
  |  |  |  
  |  |  |-<11954> /usr/bin/deepin-defender-datainterface
  |  |  |-<12173> /usr/lib/bluetooth/obexd
  |  |  +-<12232> /usr/bin/uos-activator
  |  |  
  |  |-<2352> /usr/sbin/smbd --foreground --no-process-group
  |  |  |-<2463> /usr/sbin/smbd --foreground --no-process-group
  |  |  |-<2464> /usr/sbin/smbd --foreground --no-process-group
  |  |  +-<2476> /usr/sbin/smbd --foreground --no-process-group
  |  |  
  |  |-<2370> /usr/libexec/lastore-daemon/lastore-daemon
  |  |-<2393> /usr/sbin/ipwatchd -c /etc/ipwatchd.conf
  |  |-<2597> /bin/sh /usr/lib/bluetooth/bluetoothd.sh
  |  |  +-<2598> /usr/lib/bluetooth/bluetoothd
  |  |  
  |  |-<2609> /usr/bin/dde-file-manager-daemon
  |  |-<2721> /usr/bin/deepin-MonitorNetFlow
  |  |-<2805> /usr/bin/sh -c cd /usr/bin;/usr/bin/deepin-defender-antiav
  |  |  +-<2813> /usr/bin/deepin-defender-antiav
  |  |  
  |  |-<3903> /usr/sbin/cupsd -l
  |  |-<4760> /usr/sbin/sshd -D
  |  |  +-<9826> sshd: test [priv]
  |  |     +-<9829> sshd: test@pts/1
  |  |        +-<9830> -bash
  |  |           |-<13489> ps -ef
  |  |           +-<13490> ./a.out -v
  |  |           
  |  |-<10498> /usr/lib/deepin-daemon/greeter-display-daemon
  |  |-<11254> /usr/bin/gnome-keyring-daemon --daemonize --login
  |  |-<11368> /usr/bin/fcitx-implugin-service
  |  |-<11370> /usr/bin/fcitx -d
  |  |  +-<11600> sh -c /opt/apps/org.deepin.chineseime/files/bin/chinime-qim
  |  |     +-<11601> /opt/apps/org.deepin.chineseime/files/bin/chinime-qim
  |  |     
  |  |-<11382> /usr/bin/dbus-daemon --syslog --fork --print-pid 5 --print-address 7 --config-file /usr/share/fcitx/dbus/daemon.conf
  |  |-<11386> /usr/bin/fcitx-dbus-watcher unix:abstract=/tmp/dbus-0XBHAVE18o,guid=250d6f9b792522fe2640cda161c97cdd 11382
  |  |-<11931> /usr/lib/at-spi2-core/at-spi2-registryd --use-gnome-session
  |  +-<11979> /usr/bin/dde-clipboardloader
  |  
  +-<2> [kthreadd]
     |-<3> [rcu_gp]
     |-<4> [rcu_par_gp]
     |-<6> [kworker/0:0H-kblockd]
     |-<8> [mm_percpu_wq]
     |-<9> [ksoftirqd/0]
     |-<10> [rcu_sched]
     |-<11> [rcu_bh]
     |-<12> [migration/0]
     |-<14> [cpuhp/0]
     |-<15> [cpuhp/1]
     |-<16> [migration/1]
     |-<17> [ksoftirqd/1]
     |-<19> [kworker/1:0H-events_highpri]
     |-<20> [kdevtmpfs]
     |-<21> [netns]
     |-<22> [kauditd]
     |-<23> [khungtaskd]
     |-<24> [oom_reaper]
     |-<25> [writeback]
     |-<26> [kcompactd0]
     |-<27> [ksmd]
     |-<28> [khugepaged]
     |-<29> [crypto]
     |-<30> [kintegrityd]
     |-<31> [kblockd]
     |-<32> [ata_sff]
     |-<33> [edac-poller]
     |-<34> [devfreq_wq]
     |-<35> [watchdogd]
     |-<37> [kswapd0]
     |-<55> [kthrotld]
     |-<56> [nvme-wq]
     |-<57> [nvme-reset-wq]
     |-<58> [nvme-delete-wq]
     |-<59> [scsi_eh_0]
     |-<60> [scsi_tmf_0]
     |-<61> [scsi_eh_1]
     |-<62> [scsi_tmf_1]
     |-<63> [scsi_eh_2]
     |-<64> [scsi_tmf_2]
     |-<65> [scsi_eh_3]
     |-<66> [scsi_tmf_3]
     |-<71> [ipv6_addrconf]
     |-<81> [kstrp]
     |-<83> [kworker/0:1H-events_highpri]
     |-<153> [kworker/u5:0-i915_flip]
     |-<185> [kworker/1:1H-events_highpri]
     |-<239> [jbd2/sda5-8]
     |-<240> [ext4-rsv-conver]
     |-<293> [lightcherry]
     |-<294> [lightorange]
     |-<344> [irq/126-mei_me]
     |-<408> [kworker/0:3-cgroup_pidlist_destroy]
     |-<611> [jbd2/sda1-8]
     |-<612> [ext4-rsv-conver]
     |-<621> [jbd2/sda3-8]
     |-<622> [ext4-rsv-conver]
     |-<624> [jbd2/sda7-8]
     |-<625> [ext4-rsv-conver]
     |-<1330> [cfg80211]
     |-<2621> [kworker/u5:1]
     |-<10295> [kworker/u4:0-events_unbound]
     |-<12066> [kworker/1:2-mm_percpu_wq]
     |-<13318> [kworker/1:0-cgroup_destroy]
     |-<13390> [kworker/u4:1-events_unbound]
     +-<13431> [kworker/0:1-cgroup_destroy]
     
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,657评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,889评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,057评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,509评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,562评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,443评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,251评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,129评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,561评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,779评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,902评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,621评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,220评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,838评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,971评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,025评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,843评论 2 354

推荐阅读更多精彩内容