栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

使用accton进行进程会计处理

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

使用accton进行进程会计处理

1 进程会计介绍

启用进程会计选项后,当进程结束后内核会写一个会计记录。会计记录一般包括命令名,使用的CPU时间总量,用户ID,组ID和启动时间等。

root用户可以执行accton命令来启用会计处理。会计记录邪道指定的文件中,linux中该文件是/var/account/pacct。

acct结构定义在中:

typedef u_short comp_t;
struct acct
{
    char ac_flag;    //flag
    char ac_stat;    //termination staus,Solaris only
    uid_t ac_uid;    //real user ID
    gid_t ac_gid;    //real group ID
    comp_t ac_utime;    //user CPU time
    comp_t ac_stime;    //system CPU time
    comp_t ac_etime;    //elapsed time
    comp_t ac_mem;    //average memory usage
    char ac_comm[8];    //command name
    ...
}

ac_flag成员记录了进程执行期间的某些事件。linux支持的ac_flag如下:

ac_flag 说明
AFORK(F) 进程由fork产生,但未调用exec
ASU(S) 进程使用超级用户特权
ACORE(D) 进程转储core
AXSIC(X) 进程由一个信号杀死

会计记录由内核保存在进程表中。在进程新创建时初始化,在进程结束时写入会计记录。由此得出结论:
(1)对于没终止的进程,我们无法获取进程记录
(2)会计文件中记录的顺序对应进程终止的顺序,不是进程启动的顺序
(3)会计记录对应的是进程而不是程序。如果一个进程顺序执行了3个程序(A exec B, B exec C),则只会写C进程的会计记录

2 使用accton进行进程会计处理

如下test1程序fork了4个进程,每个进程处理不同的事情,生成会计记录:

#include    
#include    
#include    
#include    

int main(void)
{
    pid_t    pid;

    if ((pid = fork()) < 0)
        printf("fork error");
    else if (pid != 0) {        
        sleep(2);
        exit(2);                
    }

    if ((pid = fork()) < 0)
        printf("fork error");
    else if (pid != 0) {        
        sleep(4);
        abort();                
    }

    if ((pid = fork()) < 0)
        printf("fork error");
    else if (pid != 0) {        
        execl("/bin/dd", "dd", "if=/etc/passwd", "of=/dev/null", NULL);
        exit(7);                
    }

    if ((pid = fork()) < 0)
        printf("fork error");
    else if (pid != 0) {        
        sleep(8);
        exit(0);                
    }

    sleep(6);                   
    kill(getpid(), SIGKILL);    
    exit(6);                    
}

如下test2程序从会计记录中选择一些字段打印:

#include    
#include    
#include    
#include    
#include    

#if defined(BSD)    
#define acct acctv2
#define ac_flag ac_trailer.ac_flag
#define FMT "%-*.*s  e = %.0f, chars = %.0f, %c %c %c %cn"
#elif defined(HAS_AC_STAT)
#define FMT "%-*.*s  e = %6ld, chars = %7ld, stat = %3u: %c %c %c %cn"
#else
#define FMT "%-*.*s  e = %6ld, chars = %7ld, %c %c %c %cn"
#endif

#if defined(LINUX)
#define acct acct_v3    
#endif

#if !defined(HAS_ACORE)
#define ACORE 0
#endif
#if !defined(HAS_AXSIG)
#define AXSIG 0
#endif

#if !defined(BSD)
static unsigned long
compt2ulong(comp_t comptime)    
{
    unsigned long    val;
    int                exp;


    val = comptime & 0x1fff;    
    exp = (comptime >> 13) & 7;    
    while (exp-- > 0)
        val *= 8;
    return(val);
}
#endif

int main(int argc, char *argv[])
{
    struct acct        acdata;
    FILE            *fp;


    if (argc != 2) {
        printf("usage: pracct filename n");
                exit(127);
        }
    if ((fp = fopen(argv[1], "r")) == NULL) {
        printf("can't open %s n", argv[1]);
                exit(127);
        }
    while (fread(&acdata, sizeof(acdata), 1, fp) == 1) {
        printf(FMT, (int)sizeof(acdata.ac_comm),
            (int)sizeof(acdata.ac_comm), acdata.ac_comm,
#if defined(BSD)
            acdata.ac_etime, acdata.ac_io,
#else
            compt2ulong(acdata.ac_etime), compt2ulong(acdata.ac_io),
#endif
#if defined(HAS_AC_STAT)
            (unsigned char) acdata.ac_stat,
#endif
            acdata.ac_flag & ACORE ? 'D' : ' ',
            acdata.ac_flag & AXSIG ? 'X' : ' ',
            acdata.ac_flag & AFORK ? 'F' : ' ',
            acdata.ac_flag & ASU   ? 'S' : ' ');
    }
    if (ferror(fp))
        printf("read error");
    exit(0);
}

编译脚本如下:

#!/bin/bash

gcc -o test1 test1.c
gcc -o test2 test2.c -DLINUX

按照如下步骤进行测试:
(1)进入超级用户,新建会计记录文件,安装acct并启用会计记录

touch /var/log/pacct
apt install acct
accton -h
accton /var/log/pacct

(2)终止超级用户,进入普通用户,运行test1程序,这会追加6个记录到会计文件中(超级用户shell,父进程,4个子进程)
在第二个子进程中,execl并不是创建一个新进程,所以对于第二个子子进程来说只有一个会计记录

./test1
ls -lh /var/log/pacct

(3)进入超级用户,停用会计记录

accton off

(4)终止超级用户,进入普通用户,运行test2程序,从会计文件中选出字段并打印

./test2 /var/log/pacct

会计文件记录如下:

accton            e =      0, chars =       0,       S
bash              e =   4303, chars =       0,       S
su                e =   4737, chars =       0,       S
dd                e =      0, chars =       0,                   //子进程2
test1             e =    200, chars =       0,                   //父进程
test1             e =    407, chars =       0,   D X F           //子进程1
test1             e =    600, chars =       0,     X F           //子进程4
test1             e =    800, chars =       0,       F           //子进程3

e表示墙上时钟时间值,例如父进程sleep(2)对应墙上时钟200个时钟滴答。
accton是由超级用户(ASU)关闭的。S。
除了第2个子进程(fork且exec),其他子进程都设置了F标志(AFORK)。F。
子进程1调用abort,abort产生信号(AXSIG)SIGABRT,产生core转储(ACORE)。D X F。
子进程4调用kill,kill产生信号SIGKILL,但不产生core转储。X F。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/886793.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号