当前位置: 首页 > news >正文

验证Linux多进程时间片切换的程序

​​
在这里插入图片描述

一、软件需求

在同时运行多个CPU密集型进程时,需采集以下统计信息:

  • 当前运行在逻辑CPU上的进程ID
  • 每个进程的运行进度百分比

实验程序设计要求:

1. 命令行参数

参数说明示例值
n并发进程数量3
total总运行时长(毫秒)50
resol统计间隔(毫秒)1

2. 进程行为规范

  • 每个进程消耗total毫秒CPU时间后结束
  • resol毫秒记录:
    1. 进程ID(0~n-1)
    2. 累计运行时间(ms)
    3. 进度百分比((i+1)*100/nrecordnrecord=total/resol

二、代码实现

#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <err.h>


#define NLOOP_FOR_ESTIMETION 1000000000UL
#define NSEC_PER_SEC    1000000000UL
#define NSEC_PER_MSEC   1000000UL

/* 获取纳秒差 */
static inline long diff_nsec(struct timespec before, struct timespec after)
{
    return ((after.tv_sec * NSEC_PER_SEC + after.tv_nsec) 
    - (before.tv_sec * NSEC_PER_SEC + before.tv_nsec));
}

/* 每微秒消耗的空循环的次数 */
static unsigned long loops_per_msec(void)
{
    struct  timespec before, after;
    clock_gettime(CLOCK_MONOTONIC, &before);
    unsigned long i;
    for(i = 0; i < NLOOP_FOR_ESTIMETION; i++)
    ;
    clock_gettime(CLOCK_MONOTONIC, &after);
    return ((NLOOP_FOR_ESTIMETION * NSEC_PER_MSEC) / diff_nsec(before, after));
}

static inline void load(unsigned long nloops)
{
    unsigned long i;
    for(i = 0; i < nloops; i++ )
        ;
}

static void chidld_fn(int nproc, struct timespec *buf, int nrecord, 
        unsigned long nloop_per_resol, struct timespec start)
{
    int i;
    struct timespec ts;
    for(i = 0; i < nrecord; i++)
    {
        load(nloop_per_resol);
        clock_gettime(CLOCK_MONOTONIC, &ts);
        buf[i] = ts;
    }
    printf("nproc\tms\t step\n");
    printf("---------------------\n");
    for(i = 0; i < nrecord; i++)
    {
        printf("%d\t%ld\t%d\n", nproc, 
            diff_nsec(start, buf[i]) / NSEC_PER_MSEC,
            ((i + 1) * 100) / nrecord );
    }
    printf("---------------------\n");
    exit(EXIT_SUCCESS);
}

int main(int argc, char *argv[])
{
    int ret = EXIT_FAILURE;
    if( 4 > argc)
    {
        fprintf(stderr, "usage: %s <nproc> <total[ms]> <resolution[ms]>\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    int nproc = atoi(argv[1]); //同时运行的进程的数量
    int total = atoi(argv[2]); //程序运行的总时长,ms为单位 
    int resol = atoi(argv[3]); //采集统计信息的间隔

    if(1 > nproc) //对进程数量参数过滤非法值
    {
        fprintf(stderr, "<nproc> (%d) should be >= 1\n", nproc);
        exit(EXIT_FAILURE);
    }

    if(1 > total) //对程序时长参数过滤非法值
    {
        fprintf(stderr, "<total> (%d) should be >= 1\n", total);
        exit(EXIT_FAILURE);
    }

    if(1 > resol) //对采集统计信息参数过滤非法值
    {
        fprintf(stderr, "<resol> (%d) should be >= 1\n", resol);
        exit(EXIT_FAILURE);
    }

    if(total % resol)
    {
        fprintf(stderr, "<total> (%d) should be mutliple of <resol> (%d) \n",total, resol);
        exit(EXIT_FAILURE);
    }

    int nrecord = total / resol;
    struct timespec* logbug = malloc(nrecord * sizeof(struct timespec)); //堆中开辟内存

    if(!logbug)
    {
        err(EXIT_FAILURE, "malloc(nrecord) failed");
    }
    puts("estimeting workload which just take one millsecond");
    unsigned long nloops_per_resol = loops_per_msec() * resol;
    puts("end estimeting");
    fflush(stdout); // fflush log

    pid_t* pids = malloc(nrecord * sizeof(pid_t));
    if(!pids)
    {
        warn("malloc (pids) failed");
        goto free_logbuf;
    }

    int i, ncreated;
    struct timespec start;
    clock_gettime(CLOCK_MONOTONIC, &start);

    for(i = 0, ncreated = 0; i < nproc; i++, ncreated++)
    {
        pids[i] = fork();
        if( 0 > pids[i])
        {
            goto wait_children;
        }
        else if( 0 == pids[i])
        {//子进程执行空间
            chidld_fn(i, logbug, nrecord, nloops_per_resol, start);
        }
    }

    ret = EXIT_SUCCESS;

wait_children:
    if(EXIT_FAILURE == ret) //杀死所有已创建的子进程.
    {
        for(i = 0; i < ncreated; i++)
        {
            if(0 > kill(pids[i], SIGINT))
            {
                warn("kill(%d) failed", pids[i]);
            }
        }
    }

    for(i = 0; i < ncreated; i++) //等待子进程结束
    {
        if(0 > wait(NULL))
        {
            warn("wait() failed");
        }
    }

free_pids:
    free(pids);

free_logbuf:
    free(logbug);

    exit(ret);
}

三、编译配置(Makefile)

TARGET := app
SRC := sched.c
CPPFLAGS := -pthread

all: $(TARGET)
    @echo "make successful"

$(TARGET): $(SRC)
    @echo $(SRC)
    gcc $(CPPFLAGS) $^ -I. -o $@

clean:
    rm $(TARGET)

四、实验结果

nproc   ms      step
---------------------
2       0       2
2       1       4
2       2       6
...
2       172     100
---------------------
nproc   ms      step
---------------------
0       10      2
0       11      4
...
0       176     100
---------------------
nproc   ms      step
---------------------
1       6       2
1       7       4
...
1       203     100

相关文章:

  • PyTorch 张量的new_tensor方法介绍
  • 算法基础——树
  • RAG基建之PDF解析的“流水线”魔法之旅
  • 网络安全-网络安全基础
  • freecad gear模块 生成齿轮导出fcstd step
  • 20组电影美学RED摄像摄影机视频胶片模拟色彩分级调色LUT预设包 Pixflow – CL – RED Camera LUTs
  • 项目实战--权限列表
  • Mybatis日志模块分析--适配器模式+代理模式
  • 身份验证:区块链如何让用户掌控一切
  • Scrapy对比Selenium:哪个最适合您的网络爬虫项目
  • 深度学习Note.5(机器学习2)
  • Unity中UDP异步通信常用API使用
  • Python小练习系列 Vol.7:全排列生成(回溯算法模板题)
  • Spring笔记03-依赖注入
  • Javaweb后端登录认证 登录校验 过滤器 filter令牌校验,执行流程,拦截路径
  • 业之峰与宏图智能战略携手,开启家装数字化新篇章
  • excel 时间戳 转日期
  • shop搜索需求及测试点
  • 01-Docker 安装
  • 知识图谱之知识抽取:从数据海洋中 “捞金”
  • 湖北鄂城:相继4所小学有学生腹泻呕吐,供餐企业负责人已被采取强制措施
  • 两部门调度部署“五一”假期安全防范工作,要求抓好旅游安全
  • 特朗普加征关税冲击波:美国零售、汽车、航空、科技企业纷纷预警业绩波动
  • 魔都眼|静安光影派对五一启幕:苏河湾看徐悲鸿艺术画作
  • “五一”假期逛上海车展请提前购票,展会现场不售当日票
  • 王毅会见泰国外长玛里:坚决有力打击电诈等跨境犯罪