单进程中利用alarm实现动态定时器

    要求如题所示,在单个进程中实现动态定时器。因为每个进程只能有一个闹钟时钟,所以在调用alarm时,若以前已经为该进程设置时钟,而且它还没有超时,则将该闹钟的余值作为本次alarm的返回值。以前登记的闹钟时钟被新值取代。
   对于这个题目,我的设计是:定义一个限量的结构体数组(TASK如下所示),用于承载不同的计时任务,根据任务的状态决定alarm到时后的操作,从而实现动态定时。
   在任务结构体中
   taskid表示任务ID,在实际操作中使其等于所在位置的数组号;
   xsec表示相对时间,为了便于操作,任务数组里的时间被规划为同一起点的时间。每当有任务到时、新任务加入或有任务被删除时,数组时间被更新;
   job表示所要执行的任务;
   flag是状态标识,RUNNING为运行态,即处于该状态的任务在计时到时后被执行;WAITTING为等待,因为此状态的相对时间大于RUNNING态的任务,所以在alarm到时前不需作操作,alarm到时后,相对时间更新(所有WAITTING态的任务相对时间减去RUNNING态相对时间),RUNNING态任务变为COMPLETED态,然后把WAITTING态中最小时间的任务设为新的RUNNING态。

typedef struct mytask {
    int taskid; //任务ID
    int xsec; //相对时间
    jobFunc job;//到期执行任务
    int flag;   
}TASK;
代码如下,由于时间仓促,只完成基本功能,以后再作优化。
头文件timer.h

#ifndef __TIMER__H
#define __TIMER__H

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <strings.h>
#include <string.h>


#define TASK_MAX 100
#define TASK_BUF_SIZE 1024

typedef void(*jobFunc)(void);

enum {
    COMPLETED,
    WAITTING,
    RUNNING,
        
};

typedef struct mytask {
    int taskid;
    int xsec; //相对时间

    jobFunc job;//到期执行任务

    int flag;    
}TASK;

void new_run(void);
int add_job();
int del_job();
void regeneration_time(int base);
int find_and_store(jobFunc job, int expire);
int search(int taskid,int flag);
void do_job(int s);
void print(void);
void print_menu(void);

#endif


mytimer.c

#include "timer.h"


TASK task[TASK_MAX];    //任务数组

int taskcnt = 0;        //当前任务数量



void job_1(void)
{
    printf("***job_1 over***\n");
}

void new_run(void)
{
    int ret,min,i;
    ret = search(-1,WAITTING);
    min = ret;
    if(taskcnt >= 1)
    {
        for(i=0;i<TASK_MAX;i++)
            if(WAITTING == task[i].flag)
                if(task[min].xsec > task[i].xsec)
                    min = i;    
        task[min].flag = RUNNING;
        alarm(task[min].xsec);
    }    
    //还缺少相等情况    

}

void do_job(int s)
{
    int i,ret,min;
    for(i=0;i<TASK_MAX;i++)
    {
        if(RUNNING == task[i].flag)
        {
            task[i].job();
            task[i].flag = COMPLETED;
            ret = i;
        }
    }
    taskcnt--;
    regeneration_time(task[ret].xsec);    //更新

    new_run();
}



int search(int taskid,int flag)
{
    int i;
    
    if(flag >= 0)
    {
        for(i=0;i<TASK_MAX;i++)
            if(task[i].flag == flag)
                return i;        
    }
    if(taskid >= 0)
    {
        for(i=0;i<TASK_MAX;i++)
            if(task[i].taskid == taskid)
                return i;        
    }
}

void regeneration_time(int base)
{
    int i;
    for(i=0;i<TASK_MAX;i++)
    {
        if(task[i].flag == WAITTING)
            task[i].xsec = task[i].xsec - base;
    }
}

int find_and_store(jobFunc job, int expire)
{
    int ret,ret2;

    ret = search(-1,COMPLETED);
    
    task[ret].taskid = ret;
    task[ret].xsec = expire;
    task[ret].job = job;
    task[ret].flag = WAITTING;
    
    ret2 = search(-1,RUNNING);
    if(expire < task[ret2].xsec)
    {
        //缺少对同为running状态的改变

        task[ret2].flag = WAITTING;
        task[ret].flag = RUNNING;
        alarm(expire);    
    }
    else if(expire == task[ret2].xsec)
    {
        task[ret].flag = RUNNING;
        alarm(expire);
    }
    else
        alarm(task[ret2].xsec);
    return 0;    
}

int add_job(void)
{
    int ret,lsec,base,jobnum;
    int taskid,expire;
    jobFunc job=job_1;
    
    
    printf("in put time:\n");
    scanf("%d",&expire);
    getchar();
    
    if(taskcnt==0)
    {
        task[0].taskid = 0;
        task[0].xsec = expire;
        task[0].job = job;
        task[0].flag = RUNNING;
        alarm(expire);    
    }
    else
    {
        ret = search(-1,RUNNING);    //排在第一位任务的位置

        lsec = alarm(0);    //剩余alarm时间

        base = task[ret].xsec - lsec;    //已过的时间

        task[ret].xsec = lsec;
        regeneration_time(base);
        find_and_store(job,expire);
    }
    taskcnt++;
    return 0;        
}

void print(void)
{
    int i;
    for(i=0;i<TASK_MAX;i++)
        if((task[i].flag == WAITTING)||(task[i].flag == RUNNING))
            printf("taskid:%d\n",task[i].taskid);
}

int del_job(void)
{
    int id,lsec,base,ret;
    char inc[10];
    printf("input the taskid:\n");
    fgets(inc,10,stdin);
    ret = strlen(inc);
    inc[ret-1] = '\0';
    id = atoi(inc);
    if(task[id].flag == RUNNING)
    {    
        task[id].flag = COMPLETED;
        lsec = alarm(0);
        base = task[id].xsec - lsec;
        regeneration_time(base);
        new_run();
    }
    else
        task[id].flag = COMPLETED;
    taskcnt--;
    return 0;
}

void print_menu(void)
{
    printf("1.add\t2.del\t3.show\n");
}

int main(void)
{
    char inc[10];
    
    signal(SIGALRM, do_job);
    bzero(task,sizeof(TASK)*TASK_MAX);
    
    while(1)
    {
        print_menu();
        fgets(inc,10,stdin);
        
        switch(inc[0])
        {
            case '1':add_job();break;
            case '2':del_job();break;
            case '3':print();break;
            default :break;
        }    
    }    
    return 0;
}


文件: timer.tar.gz
大小: 4KB
下载: 下载

作者: shenhailuanma   发布时间: 2010-11-20