system函数和进程会计

84 篇文章 0 订阅

 

system函数

在程序中执行一个命令字符串十分的方便。例如嘉定时间和日期放到一个文件中,6.10中说明的函数实现这一点。调用time得到当前日历时间,接着调用localtime将日历时间转换为年月日 时分秒,然后调用strftime对上面的结果进行格式化处理,最后将结果写到文件中。

#include <stdlib.h>

int system(const char* cmd);

cmdstring 是一个空指针,则晋档命令处理程序可用的时候,system在实现中调用了fork、exec和waitpid,因此有三种返回值。

如果fork失败或者waitpid返回除了EINTR之外的出错,则system返回-1,而且errno中设置了错误类型值。

如果exec失败,则其返回值如图shell执行可exit一样。

否则所有三个函数(fork、exec和waitpid)都执行成功,并且system的返回值是shell的终止状态,其格式已经在waitpid中进行了说明。

我们在代码中加入的函数是execl(“/bin/sh”,”sh”,”-c”,cmdstring,(char*)0)

exit和_exit的区别 exit会清除IO 而_exit不会

如果调用system的进程在调用它之前已经生成它自己的子进程,那么他将引起问题。因为上面的while语句一直在循环执行,直到有system产生的子进程终止才停止,如果不是用pid标识的任意进程在pid子进程之前终止,那么他的进程id和终止状态都会被while语句锁丢弃,由于wait不能等待一个置顶的进程以及一些其他的原因,我们定义了waitpid函数没如果不提供waitpid函数,popen和pclose也会出现同样的问题。

exit的作用就是结束,清理,就是说先检查缓冲区,把没有写入的数据写入到文件,而_exit是立刻关闭文件,文件缓冲区的内容也就消失了,这个时候就不可能再输出到显示设备了。

使用system而不是直接使用fork和exec的优点是:system进行了所需要的各种出错处理,以及信号处理,在unix早起版本中没有waitpid于是就只能使用wait

如果一个进程正在以特殊的权限运行,他邮箱生成另一个进程执行另一个程序,他应该直接使用fork和exec,而且在fork之后、exec之前更改会普通用户。

8.14 进程会计

大多数unix系统提供了一个选项以进行进程会计处理。启用这个选项后,当进程结束时候内核就会写一个会计记录。典型的会计记录包含总量较小的二进制数据,一般包括命令名,使用的cpu时间总量,用户id和用户组id、启动时间等。

一个至今没有说明的函数用于启用和禁止进程会计,唯一使用这一个函数的是accton命令。超级用户执行一个带路径名字的accton命令启动会计处理。会计记录写到指定的文件中,这个文件通常是/var/account/acct,在linux中这个文件是/var/account/pacct 在 solaris中则是/var/adm/pacct

include

typedef u_short comp_t; // 3-bit base 8 exponent; 13-bit fraction
type acct{
char ac_flag; // flag, see below
char ac_stat; // termination status(signal & core flag only)
// (Solaris only)
uid_t ac_uid; // real user ID
gid_t ac_gid; // real group ID
dev_t ac_tty; // controlling terminal
time_t ac_btime; // starting calendar time
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
comp_t ac_io; // bytes transferred (by read and write)
// “blocks” on BSD systems
comp_t ac_rw; // blocks read or written (not present on BSD systems)
char ac_comm[8]; // command name: [8] for Solaris, [10] for Mac OS X,
// [16] for FreeBSD and [17] for Linux
};

会计记录中的ac_flag说明
AFORK 进程是由fork产生的但是从来没有调用exec
ASU 进程使用超级用户特权
ACOMPAT 进程使用兼容模式
ACORE 进程转存储core
AXSIG 进程由信号杀死
AEXPND 扩展的会计条目

会计记录对应与进程而不是程序。在fork之后,内核为子进程初始化一个记录,而不是一个新程序执行时候做这个项目的工作。虽然exec并不创建新的会计记录,单改变了相应的命令名字,并且AFORK标志就会被清除。如果一个进程exec了A B C,只会写一条会计记录,改记录的命名对应与c,但是cpu时间是abc之和。

demo 使用 调用 accton打开进程会计

accton /home/zhanglei/pacct

关闭进程会计

accton off

执行程序查看进程会计中的内容

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/acct.h>

typedef int ElementType;
struct TreeNode;
typedef struct TreeNode *SearchTree;
typedef struct TreeNode *Position;

struct TreeNode{
    ElementType Element;
    SearchTree left;
    SearchTree right;
};

struct _TreeContainer{

}TreeContainer;
#if defined(BSD)    // different structure in FreeBSD
#define acct    acctv2
    #define ac_flag ac_trailer.ac_flag
    #define FMT "%-*.*s e = %.0f, chars = %.0f, %c %c %c %c\n"
#elif defined(HAS_AC_STAT)
#define FMT "%-*.*s e = %6ld, chars = %7ld, stat = %3u: %c %c %c %c\n"
#else
#define FMT "%-*.*s e = %6ld, chars = %7ld, %c %c %c %c\n"
#endif
SearchTree MakeEmpty(SearchTree T);

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

    val = comptime & 0x1fff;    // 13-bit fraction
    exp = (comptime >> 13) & 7; // 3-bit exponent (0-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: %s filename\n", argv[0]);
    exit(1);
    }
    if((fp=fopen(argv[1], "r")) == NULL){
    printf("can't open %s\n", argv[1]);
    exit(2);
    }
    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\n");
    exit(0);
}

//做一个空的树
SearchTree MakeEmpty(SearchTree T)
{
    if(T != NULL)
    {
    MakeEmpty(T->left);
    MakeEmpty(T->right);
    }
    return NULL;
}

每当进程结束的时候就会写一个会计记录写入文件,我们可以用acct 结构体去读这个文件去查看相对应的内容

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值