Linux IPC 计时器与信号:发送信号,睡眠函数,真实计时器,虚拟计时器,实用计时器

Linux IPC 信号

    • 用程序发送信号
      • kill 信号发送函数
    • 睡眠函数
      • 模拟睡眠3秒
    • 时钟处理函数
      • 函数getitimer()
      • 函数setitimer()
      • 函数time()
      • 函数gmtime()
        • 采用实用计时器统计1秒中机器浮点乘法运算的次数
        • 采用真实计时器统计1秒中机器浮点乘法运算的次数

用程序发送信号

kill 信号发送函数

函数原型:

#include 
#include 
int kill(pid_t pid, int sig);

参数 pid 为将要接受信号的进程的 pid,可以通过 getpid()函数获得来给自身发送信号,还可以发送信号给指定的进程,此时 pid 有如下描述:

pid > 0   将信号发给 ID 为 pid 的进程
pid == 0  将信号发送给与发送进程属于同一个进程组的所有进程
pid < 0   将信号发送给进程组 ID 等于 pid 绝对值的所有进程
pid == -1 将信号发送给该进程有权限发送的系统里的所有进程

参数 sig 为要发送的信号

如果成功,返回 0,否则为-1

# include 
#include 
#include 
#include 
int main(int argc, char* argv[])
{
	int pid = atoi(argv[1]);
	kill(pid,SIGQUIT);
	return 0;
}

睡眠函数

Linux 下有两个睡眠函数,原型为:

#include 
unsigned int sleep(unsigned int seconds);
void usleep(unsigned long usec);

函数 sleep 让进程睡眠 seconds 秒,函数 usleep 让进程睡眠 usec 微秒。
sleep 睡眠函数内部是用信号机制进行处理的,用到的函数有:

#include 
unsigned int alarm(unsigned int seconds);
//告知自身进程,要进程在 seconds 秒后自动产生一个 SIGALRM 的信号
int pause(void); //将自身进程挂起,直到有信号发生时才从 pause 返回

模拟睡眠3秒

#include 
#include 
#include 
void SignHandler(int iSignNo)    //信号处理函数
{
	printf("signal:%d\n",iSignNo);
}
int main()
{
	signal(SIGALRM,SignHandler);
	alarm(3); //等待 3 秒之后自动产生 SIGALRM 信号
	printf("Before pause().\n");
	pause(); //将进程挂起,直到有信号发生才退出挂起状态
	printf("After pause().\n");
	return 0;
}

注意:因为 sleep 在内部是用 alarm 实现的,所以在程序中最好不要 sleep 与 alarm 混用,以免造成混乱。

时钟处理函数

Linux 为每个进程维护 3 个计时器,分别是真实计时器、虚拟计时器和实用计时器。

真实计时器计算的是程序运行的实际时间。

虚拟计时器计算的是程序运行在用户态时所消耗的时间(可认为是实际时间减掉系统调用和程序睡眠所消耗的时间)。

实用计时器计算的是程序处于用户态和处于内核态所消耗的时间之和。

例如:有一程序运行,在用户态运行了 5 秒,在内核态运行了 6 秒,还睡眠了 7 秒,则真实计算器
计算的结果是 18 秒,虚拟计时器计算的是 5 秒,实用计时器计算的是 11 秒。

用指定的初始间隔和重复间隔时间为进程设定好一个计时器后,该计时器就会定时地向进程发送时
钟信号。3 个计时器发送的时钟信号分别为:SIGALRM,SIGVTALRM 和 SIGPROF。

函数getitimer()

#include 
int getitimer(int which, struct itimerval *value);   //获取计时器的设置

参数 which 指定哪个计时器,可选项为 ITIMER_REAL(真实计时器)、ITIMER_VIRTUAL(虚拟
计时器、ITIMER_PROF(实用计时器)。

参数 value 为一结构体的传出参数,用于传出该计时器的初始间隔时间和重复间隔时间。

函数返回值:如果成功,返回 0,否则-1。

函数setitimer()

#include
int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue); //设置计时器

参数 which 指定哪个计时器,可选项为 ITIMER_REAL(真实计时器)、ITIMER_VIRTUAL(虚拟
计时器、ITIMER_PROF(实用计时器)。

参数 value 为一结构体的传入参数,指定该计时器的初始间隔时间和重复间隔时间。

参数 ovalue 为一结构体传出参数,用于传出以前的计时器时间设置。

函数返回值:如果成功,返回 0,否则-1。

struct itimerval {
	struct timeval it_interval; /* next value */ //重复间隔
	struct timeval it_value;    /* current value */ //初始间隔
};
struct timeval {
	long tv_sec;    /* seconds */ //时间的秒数部分
	long tv_usec;   /* microseconds */ //时间的微秒部分
};

函数time()

typedef long time_t;
#include 
time_t time(time_t *tloc); 

time() returns the time as the number of seconds since the Epoch, 1970-01-01 00:00:00 +0000 (UTC)
If tloc is non-NULL, the return value is also stored in the memory pointed to by tloc.

函数gmtime()

#include 
struct tm *gmtime(const time_t *timep);

The ctime(), gmtime() and localtime() functions all take an argument of data type time_t, which represents calendar time. When interpreted as an absolute time value, it represents the number of seconds elapsed since the Epoch, 1970-01-01 00:00:00 +0000 (UTC).
On success, gmtime() and localtime() return a pointer to a struct tm.

struct tm {
	int tm_sec;    /* Seconds (0-60) */
	int tm_min;    /* Minutes (0-59) */
	int tm_hour;   /* Hours (0-23) */
	int tm_mday;   /* Day of the month (1-31) */
	int tm_mon;    /* Month (0-11) */
	int tm_year;   /* Year - 1900 */
	int tm_wday;   /* Day of the week (0-6, Sunday = 0) */
	int tm_yday;   /* Day in the year (0-365, 1 Jan = 0) */
	int tm_isdst;  /* Daylight saving time */
};

用真实计时器的进行时钟处理(获得当前系统时间,并一秒更新一次)

#include 
#include 
#include 
#include 
#include 
#include 

void sigHandler(int iSigNum)
{
	time_t tt;
	time(&tt);
	struct tm *pTm = gmtime(&tt);
	printf("%04d-%02d-%02d %02d:%02d:%02d\n", (1900+pTm->tm_year), (1+pTm->tm_mon),
pTm->tm_mday, (8+pTm->tm_hour), pTm->tm_min, pTm->tm_sec);
}

void InitTime(int tv_sec, int tv_usec)
{
	signal(SIGALRM, sigHandler);  //捕获SIGALRM信号,进行sigHandler处理
	alarm(0);
	struct itimerval tm;
	tm.it_value.tv_sec = tv_sec;         //初始时间间隔
	tm.it_value.tv_usec = tv_usec;       
	tm.it_interval.tv_sec = tv_sec;      //重复时间间隔
	tm.it_interval.tv_usec = tv_usec;
	if(setitimer(ITIMER_REAL, &tm, NULL) == -1)
	{
		perror("setitimer error");
		exit(-1);
	}
}

int main()
{
	InitTime(2, 0);
	while(1);
	return 0;
}
采用实用计时器统计1秒中机器浮点乘法运算的次数

setitimer_sigprof.c

#include 
long times=0;
void sigFunc(int signum)
{
    time_t now;
    time(&now);     //获取当前距离1970年的秒数
    printf("%s %ld\n",ctime(&now),times);  //打印当前的时间和浮点运算的次数
    times=0;
}
int main(int argc, char* argv[])
{
    signal(SIGPROF,sigFunc);
    struct itimerval t;
    bzero(&t,sizeof(t));
    t.it_value.tv_sec=1;
    t.it_interval.tv_sec=1;
    int ret;
    //用户自己调用一次sigFunc(),括号中的数字传递任意一个int类型的数即可
    sigFunc(0); //kill(0,SIGPROF)
    ret=setitimer(ITIMER_PROF,&t,NULL);
    ERROR_CHECK(ret,-1,"setitimer");
    double d,f;
    while(1)
    {
        f=123423132.21;
        d=892.126*f;
        times++;
    }
    return 0;
}
采用真实计时器统计1秒中机器浮点乘法运算的次数

setitimer_sigalarm.c

#include 
long times=0;
void sigFunc(int signum)
{
    time_t now;
    time(&now);    //获取当前距离1970年的秒数
    printf("%s %ld\n",ctime(&now),times);
    times=0;
}
int main(int argc, char* argv[])
{
    signal(SIGALRM,sigFunc);
    struct itimerval t;
    bzero(&t,sizeof(t));
    t.it_value.tv_sec=1;
    t.it_interval.tv_sec=1;
    int ret;
    sigFunc(0);
    ret=setitimer(ITIMER_REAL,&t,NULL);
    ERROR_CHECK(ret,-1,"setitimer");
    double d,f;
    while(1)
    {
        f=123423132.21;
        d=892.126*f;
        times++;
    }
    return 0;
}

你可能感兴趣的:(LINUX系统)