如何使用SIGSTOP和SIGCONT强制一个过程以CPU使用的指定百分比运行?

发布于 2025-02-10 06:12:16 字数 3432 浏览 1 评论 0原文

我编写了一个简单的C程序,以强制使用Sigstop和Sigcont在CPU使用的特定百分比下运行的过程。但是%cpu topCommand显示它始终超过设置编号。如何强制程序运行%CPU不超过指定值?

图像Bellow显示将限制设置为20%时获得的内容,Process loop使用%CPU = 21.3

​github,运行测试以在项目的根文件夹中启动测试实例:

https:> https://github.com/zltl/ CPU_LIMIT_RUN

代码是计算当前CPU流程时间的程序的主要循环,并发送sigstop或sigcond以达到限制:

// we store time stats of process in a circular queue array, each element store
// a struct time_history.
struct time_history {
    long utime, stime, cutime, cstime;
    long long total_cpu_usage;
};
#define MAX_HISTORY_LEN 30
struct time_history time_history[MAX_HISTORY_LEN];
int cur_history_idx = 0;

#define MAX_PATH_LEN 256

// main loop, calculate current cpu time of process, send SIGSTOP or SIGCOND to
// satisfy the limit.
int loop(struct my_conf *conf) {
    char stat_file[MAX_PATH_LEN];

    long nproc = get_nprocs();

    long long p_total_cpu_usage = 0;
    long p_utime, p_stime, p_cutime, p_cstime;

    long utime, stime, cutime, cstime;
    long long starttime;

    int full = 0;

    int is_stop = 0;

    sprintf(stat_file, "/proc/%d/stat", conf->pid);
    for (;;) {
        long long total_cpu_usage = get_total_cpu_usage();

        FILE *fp = fopen(stat_file, "r");
        if (fp == NULL) {
            fprintf(stdout, "pid %d exited %s\n", conf->pid, strerror(errno));
            return -1;
        }
        fscanf(fp,
               "%*d %*s %*c %*d "  // pid,command,state,ppid
               "%*d %*d %*d %*d %*u %*u %*u %*u %*u "
               "%ld %ld %ld %ld "  // utime,stime,cutime,cstime
               "%*d %*d %*d %*d "
               "%lld",
               &utime, &stime, &cutime, &cstime, &starttime);
        fclose(fp);

        struct time_history *th = &time_history[cur_history_idx];
        th->utime = utime;
        th->stime = stime;
        th->cutime = cutime;
        th->cstime = cstime;
        th->total_cpu_usage = total_cpu_usage;

        cur_history_idx++;
        if (cur_history_idx >= MAX_HISTORY_LEN) {
            cur_history_idx = 0;
            full = 1;
        }
        if (!full) {
            usleep(1000L * conf->interval_ms);
            continue;
        }

        struct time_history *th_prev = &time_history[cur_history_idx];
        p_utime = th_prev->utime;
        p_stime = th_prev->stime;
        p_cutime = th_prev->cutime;
        p_cstime = th_prev->cstime;
        p_total_cpu_usage = th_prev->total_cpu_usage;

        long long proc_time_since = utime - p_utime + stime - p_stime + cutime -
                                    p_cutime + cstime - p_cstime;
        long long total_time_since = total_cpu_usage - p_total_cpu_usage;

//********** calculate, send signals ***************
        double cpu_usage =
            (proc_time_since * (double)100.0) / total_time_since * nproc;

        if (cpu_usage >= conf->percent && !is_stop) {
            kill(conf->pid, SIGSTOP);
            is_stop = 1;
        }
        if (cpu_usage < conf->percent && is_stop) {
            kill(conf->pid, SIGCONT);
            is_stop = 0;
        }
//*************************

        usleep(1000L * conf->interval_ms);
    }
}

I wrote a simple C program to force a process to run under a specific percent of cpu usage using SIGSTOP and SIGCONT. But %CPU of topcommand shows it always exceed the setting number a little bit. How can I force the program run with %CPU not exceed the specified value?

The image bellow shows what I get when setting the limit to 20%, process loop run with %CPU=21.3:

enter image description here

Source codes upload on github, run make test to start a testing instance inside the project's root folder:

https://github.com/zltl/cpu_limit_run

Codes fllow are main loop of the program that calculates current cpu time of process, and send SIGSTOP or SIGCOND to attain the limit:

// we store time stats of process in a circular queue array, each element store
// a struct time_history.
struct time_history {
    long utime, stime, cutime, cstime;
    long long total_cpu_usage;
};
#define MAX_HISTORY_LEN 30
struct time_history time_history[MAX_HISTORY_LEN];
int cur_history_idx = 0;

#define MAX_PATH_LEN 256

// main loop, calculate current cpu time of process, send SIGSTOP or SIGCOND to
// satisfy the limit.
int loop(struct my_conf *conf) {
    char stat_file[MAX_PATH_LEN];

    long nproc = get_nprocs();

    long long p_total_cpu_usage = 0;
    long p_utime, p_stime, p_cutime, p_cstime;

    long utime, stime, cutime, cstime;
    long long starttime;

    int full = 0;

    int is_stop = 0;

    sprintf(stat_file, "/proc/%d/stat", conf->pid);
    for (;;) {
        long long total_cpu_usage = get_total_cpu_usage();

        FILE *fp = fopen(stat_file, "r");
        if (fp == NULL) {
            fprintf(stdout, "pid %d exited %s\n", conf->pid, strerror(errno));
            return -1;
        }
        fscanf(fp,
               "%*d %*s %*c %*d "  // pid,command,state,ppid
               "%*d %*d %*d %*d %*u %*u %*u %*u %*u "
               "%ld %ld %ld %ld "  // utime,stime,cutime,cstime
               "%*d %*d %*d %*d "
               "%lld",
               &utime, &stime, &cutime, &cstime, &starttime);
        fclose(fp);

        struct time_history *th = &time_history[cur_history_idx];
        th->utime = utime;
        th->stime = stime;
        th->cutime = cutime;
        th->cstime = cstime;
        th->total_cpu_usage = total_cpu_usage;

        cur_history_idx++;
        if (cur_history_idx >= MAX_HISTORY_LEN) {
            cur_history_idx = 0;
            full = 1;
        }
        if (!full) {
            usleep(1000L * conf->interval_ms);
            continue;
        }

        struct time_history *th_prev = &time_history[cur_history_idx];
        p_utime = th_prev->utime;
        p_stime = th_prev->stime;
        p_cutime = th_prev->cutime;
        p_cstime = th_prev->cstime;
        p_total_cpu_usage = th_prev->total_cpu_usage;

        long long proc_time_since = utime - p_utime + stime - p_stime + cutime -
                                    p_cutime + cstime - p_cstime;
        long long total_time_since = total_cpu_usage - p_total_cpu_usage;

//********** calculate, send signals ***************
        double cpu_usage =
            (proc_time_since * (double)100.0) / total_time_since * nproc;

        if (cpu_usage >= conf->percent && !is_stop) {
            kill(conf->pid, SIGSTOP);
            is_stop = 1;
        }
        if (cpu_usage < conf->percent && is_stop) {
            kill(conf->pid, SIGCONT);
            is_stop = 0;
        }
//*************************

        usleep(1000L * conf->interval_ms);
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

贱贱哒 2025-02-17 06:12:16

您可以使用Linux NICE命令 - 运行具有修改的计划优先级程序的方法

You can use the linux nice command - a method to run a program with modified scheduling priority

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文