加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Linux > 正文

Linux-setitimer实现定时器(day10)

发布时间:2020-12-14 00:44:39 所属栏目:Linux 来源:网络整理
导读:目录 一、信号阻塞与信号未决 二、pause(2)的使用 三、信号传送过程处理 四、可重入函数 五、编写代码实现信号处理函数的继承 六、setitimer实现定时器 ? 六、setitimer实现定时器 ? 1、系统计时器 系统运行一个进程的时候,进程所消耗的时间包括三个部分

目录

一、信号阻塞与信号未决

二、pause(2)的使用

三、信号传送过程处理

四、可重入函数

五、编写代码实现信号处理函数的继承

六、setitimer实现定时器


?

六、setitimer实现定时器

?

1、系统计时器

  系统运行一个进程的时候,进程所消耗的时间包括三个部分:

 用户时间:进程消耗在用户态的时间

 内核时间:进程消耗在内核态的时间

 睡眠时间:进程消耗在等待I/O,睡眠等不被调度的时间

  内核为每个进程维护三个计时器,这三个计时器除了统计进程的时间外,还可以按照各自的及时规则,以定时器的方式工作。向进程周期性的发送不同的信号。

 真实计时器:统计进程的执行时间(用户时间+内核时间+睡眠时间),按真实定时器工作时,发送SIGALRM信号

? ? 虚拟计时器:统计进程的用户时间,按虚拟定时器工作时,发送SIGVTALRM信号

? ? 实用计时器:统计进程的用户时间和内核时间,按实用定时器工作时,发送SIGPROF信号

?

  通过setitimer(2)设置、启动、关闭定时器

setitimer(2)

#include<sys/time.h>

int setitimer(int which,const struct itimerval *new_value,struct itimerval *old_value);

功能:

  设置一个间隔时间的定时器

参数:

  which:

    ITIMER_REAL:以系统真实的时间来计算,它送出SIGALRM信号。
    ITIMER_VIRTUAL:以该进程在用户态下花费的时间来计算,它送出SIGVTALRM信号。
    ITIMER_PROF:以该进程在用户态下和内核态下所费的时间来计算,它送出SIGPROF信号。
  

    struct itimerval {
???     struct timeval it_interval; /* next value */
???     struct timeval it_value;??? /* current value */
    };

    struct timeval {
???     time_t????? tv_sec;???????? /* seconds */
???     suseconds_t tv_usec;??????? /* microseconds */
    };//itimeval又是由两个timeval结构体组成,timeval包含tv_sec和tv_usec两部分,其中tv_se为秒,tv_usec为微秒(即1/1000000秒),其中的new_value参数用来对计时器进行设置,it_interval为计时间隔,it_value为延时时长,下面例子中表示的是在setitimer方法调用成功后,延时1微秒便触发一次SIGALRM信号,以后每隔200毫秒触发一次SIGALRM信号。

settimer工作机制是,先对it_value倒计时,当it_value为零时触发信号,然后重置为it_interval,继续对it_value倒计时,一直这样循环下去。

基于此机制,setitimer既可以用来延时执行,也可定时执行。

假如it_value为0是不会触发信号的,所以要能触发信号,it_value得大于0;如果it_interval为零,只会延时,不会定时(也就是说只会触发一次信号)。

old_value参数,通常用不上,设置为NULL,它是用来存储上一次setitimer调用时设置的new_value值。如果为非NULL,则old_value的值被存储到里面。

---------------------
此段引用:https://blog.csdn.net/lixianlin/article/details/25604779

返回值:

  成功:0

  错误:-1,errno被设置

?

#include <stdio.h>
#include <signal.h>
#include <sys/time.h>
 
void signalHandler(int signo)
{
    switch (signo){
        case SIGALRM:
            printf("Caught the SIGALRM signal!n");
            break;
   }
}
 
int main(int argc,char *argv[])
{
    signal(SIGALRM,signalHandler);
 
    struct itimerval new_value,old_value;
    new_value.it_value.tv_sec = 0;
    new_value.it_value.tv_usec = 1;
    new_value.it_interval.tv_sec = 0;
    new_value.it_interval.tv_usec = 200000;
    setitimer(ITIMER_REAL,&new_value,&old_value);
    
    for(;;);
     
    return 0;
}

七、前台作业与后台作业

  

Linux bash shell单一终端界面下,我们经常需要管理或同时完成多个作业,如一边执行编译,一边实现数据备份,以及执行SQL查询等其他的任务。所有的上述的这些工作我们可以在一个bash内实现,也就是说在同一个终端窗口完成。下面主要描述了Linux下前后台作业切换与管理以及作业在脱机的情形下如何管理。

1、前后台作业的定义
前后台作业实际上对应的也就是前后台进程,因此也就有对应的pid。在这里我们统称为作业。
无论是前台作业还是后台作业,两者都来自当前的shell,是当前shell的子程序。
下面是两者的定义。
前台作业:可以由用户参与交互及控制的作业我们称之为前台作业。
后台作业:在内存可以自运行的作业,用户无法参与交互以及使用[ctrl]+c来终止,只能通过bg或fg来调用该作业。

2、几个常用的作业命令
a、command &? 直接让作业进入后台运行
b、[ctrl]+z? 将当前作业切换到后台
c、jobs? ? ? 查看后台作业状态
d、fg %n? ? ? 让后台运行的作业n切换到前台来
d、bg %n? ? ? 让指定的作业n在后台运行
e、kill %n? ? 移除指定的作业n
"n" 为jobs命令查看到的job编号,不是进程id。
每一个job会有一个对应的job编号,编号在当前的终端从1开始分配。
job 编号的使用样式为[n],后面可能会跟有 "+" 号或者 "-" 号,或者什么也不跟。
"+" 号表示最近的一个job,"-" 号表示倒数第二个被执行的Job。注,"+" 号与 "-" 号会随着作业的完成或添加而动态发生变化。
通过jobs方式来管理作业,当前终端的作业在其他终端不可见。

3、演示后台作业命令

a、直接将作业放入到后台(附加 & 符号)
[email?protected]:/tmp> tar -czvf temp.tar.gz tempSYBO2SZ.dbf &
[1] 12500
[email?protected]:/tmp> tempSYBO2SZ.dbf

[email?protected]:/tmp>? ? ? ? ? ? ? #此时可进行其它操作,作业一旦完成,会弹出如下的提示??
[1]+? Done? ? ? ? ? ? ? ? ? ? tar -czvf temp.tar.gz tempSYBO2SZ.dbf

[email?protected]:/tmp> ls -hltr temp*
-rwxr-xr-x 1 robin oinstall 490M 2013-05-02 17:48 tempSYBO2SZ.dbf
-rw-r--r-- 1 robin oinstall 174M 2013-05-02 17:50 temp.tar.gz

b、已经开始执行,但需要放入后台(使用[ctrl]+z)
[email?protected]:/tmp> tar -czvf temp2.tar.gz tempSYBO2SZ.dbf?
tempSYBO2SZ.dbf

[1]+? Stopped? ? ? ? ? ? ? ? tar -czvf temp2.tar.gz tempSYBO2SZ.dbf
[email?protected]:/tmp> jobs
[1]+? Stopped? ? ? ? ? ? ? ? tar -czvf temp2.tar.gz tempSYBO2SZ.dbf

#下面同时发布两个作业,并且在中途按下[ctrl]+z以便将当前作业提交到后台
[email?protected]:/tmp> find /u02 -type f -size +100000k??
[email?protected]:/tmp> find / -type f -size +100000k

#再次查看当前的jobs时,jobs管理器里出现了3个处于stopp状态的job
[email?protected]:/tmp> jobs
[1]? Stopped? ? ? ? ? ? ? ? tar -czvf temp2.tar.gz tempSYBO2SZ.dbf
[2]-? Stopped? ? ? ? ? ? ? ? find / -type f -size +100000k
[3]+? Stopped? ? ? ? ? ? ? ? find /u02 -type f -size +100000k

[email?protected]:/tmp> jobs -l? ? #使用-l参数查看当前shell下所有的作业以及对应的job number,进程pid
[1]? 32682 Stopped? ? ? ? ? ? ? ? tar -czvf temp2.tar.gz tempSYBO2SZ.dbf
[2]- 32687 Stopped? ? ? ? ? ? ? ? find /u02 -type f -size +100000k
[3]+ 32707 Stopped? ? ? ? ? ? ? ? find / -type f -size +100000k

#下面通过pid可以查看到对应的进程信息
[email?protected]:/tmp> ps -ef | grep 32707 | grep -v grep
robin? ? 32707 32095? 0 09:48 pts/1? ? 00:00:00 find / -type f -size +100000?
[email?protected]:/tmp> tty? ? ? #当前终端的信息为pts/1
/dev/pts/1

#打开另外一个终端
[email?protected]:~> tty
/dev/pts/3
[email?protected]:~> jobs? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #此时可以看到jobs命令无任何返回
[email?protected]:~> ps -ef | grep 32707 | grep -v grep? #仅仅根据进程id可以找到对应的作业
robin? ? 32707 32095? 0 09:48 pts/1? ? 00:00:00 find / -type f -size +100000

#由上可知,对于当前shell下的jobs,仅当前shell(终端)可见

c、将后台作业切换到前台(fg命令)
[email?protected]:/tmp> fg? ? ? ? ? ? #省略Job number的情形,则将缺省的job切换到前台
find / -type f -size +100000k
/u02/database/old/CNMMBOBK/undo/undotbsCNMMBOBK.dbf
......
[ctrl]+z
[email?protected]:/tmp> fg %1
tar -czvf temp2.tar.gz tempSYBO2SZ.dbf
[email?protected]:/tmp> jobs
[2]-? Stopped? ? ? ? ? ? ? ? find /u02 -type f -size +100000k
[3]+? Stopped? ? ? ? ? ? ? ? find / -type f -size +100000k

d、运行后台中暂停的作业(bg命令)
#前面有2个job处于stopped状态,现在我们让其在后台运行,直接输入bg命令则缺省的job继续运行,否则输入job编号,运行指定的job
[email?protected]:/tmp> bg 2? ? ? ? ? ? ? ? ? ? #输入bg 2之后,可以看到原来的命令后被追加了&
[2]- find /u02 -type f -size +100000k &?
rob[email?protected]:/tmp> jobs
[2]-? Running? ? ? ? ? ? ? ? find /u02 -type f -size +100000k &
[3]+? Stopped? ? ? ? ? ? ? ? find / -type f -size +100000k

e、移除指定的作业n(kill)
[email?protected]:/tmp> jobs
[3]+? Stopped? ? ? ? ? ? ? ? find / -type f -size +100000k
[email?protected]:/tmp> kill -9 %3? ? ? #强制终止job 3,注意,此处的%不可省略
[email?protected]:/tmp> jobs
[3]+? Killed? ? ? ? ? ? ? ? ? find / -type f -size +100000k
[email?protected]:/tmp> jobs
#kill -9 表明强制终止指定的Job,-15则表明是正常终止指定的job。 kill -l 则列出kill能够使用的所有信号
#对于上述命令的详细帮助,使用 man command来获取帮助信息

f、带参shell脚本的后台处理
#下面是一个测试用的shell脚本
[email?protected]:~/dba_scripts/custom/bin> more echo_time.sh?
#!/bin/bash
SID=$1
sqlplus -S scott/[email?protected]$1 <<EOF
select to_char(sysdate,‘yyyy-mm-dd hh24:mi:ss‘) today from dual;
begin
dbms_lock.sleep(300);
end;
/
select to_char(sysdate,‘yyyy-mm-dd hh24:mi:ss‘) today from dual;
exit;
EOF
exit

#直接执行带参的shell脚本

# Author : Robinson
# Blog? : http://blog.csdn.net/robinson_0612

[email?protected]:~/dba_scripts/custom/bin> ./echo_time.sh CNMMBO

TODAY
-------------------
2013-05-03 11:07:48

[1]+? Stopped? ? ? ? ? ? ? ? ./echo_time.sh CNMMBO? #按下[ctrl]+z将其切换到后台
[email?protected]:~/dba_scripts/custom/bin> jobs
[1]+? Stopped? ? ? ? ? ? ? ? ./echo_time.sh CNMMBO
[email?protected]:~/dba_scripts/custom/bin> kill -9 %1? ? ? #强制终止该job?

[1]+? Stopped? ? ? ? ? ? ? ? ./echo_time.sh CNMMBO
[email?protected]:~/dba_scripts/custom/bin> jobs? ? ? ? ? ? #此时该job已经被标记为killed?
[1]+? Killed? ? ? ? ? ? ? ? ? ./echo_time.sh CNMMBO
[email?protected]:~/dba_scripts/custom/bin> ./echo_time.sh CNMMBO &? #将shell脚本参数之后跟 &符号即将job放入到后台
[1] 2233
[email?protected]:~/dba_scripts/custom/bin>? ? ? ? #此时依旧可以看到有输出,但可以继续后续操作
TODAY
-------------------
2013-05-03 11:08:25
??
[email?protected]:~/dba_scripts/custom/bin> jobs
[1]+? Running? ? ? ? ? ? ? ? ./echo_time.sh CNMMBO &
[email?protected]:~/dba_scripts/custom/bin> ./echo_time.sh CNMMBO >temp.log 2>&1 &? #最佳的办法是直接将其输出到日志文件
[2] 2256
[email?protected]:~/dba_scripts/custom/bin> jobs
[1]-? Running? ? ? ? ? ? ? ? ./echo_time.sh CNMMBO &
[2]+? Running? ? ? ? ? ? ? ? ./echo_time.sh CNMMBO >temp.log 2>&1 &

#下面来查看日志,日志中的两次查询正好相差5分钟
[email?protected]:~/dba_scripts/custom/bin> more temp.log

TODAY
-------------------
2013-05-03 11:09:24

PL/SQL procedure successfully completed.

TODAY-------------------2013-05-03 11:14:24

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读