Linux 定时器应用
实验目的
阅读 Linux 相关源代码,学习 Linux 系统中的时钟和定时器原理,即,ITIMER_REAL
实时计数,ITIMER_VIRTUAL 统计进程在用户模式执行的时间,ITIMER_PROF 统计进程
在用户模式和核心模式下的执行时间。
理解这些定时器的实现机制。
掌握操作定时器的命令,掌握定时器的使用。
实验内容
ITIMER_REAL 实时计数;ITIMER_VIRTUAL 统计进程在用户模式(进程本身执行)
执行的时间;ITIMER_PROF 统计进程在用户模式(进程本身执行)和核心模式(系统代表
进程执行)下的执行时间,与 ITIMER_VIRTUAL 比较,这个计时器记录的时间多了该进程
核心模式执行过程中消耗的时间。
针对一个计算 fibonacci 数的进程,设定三个定时器,获取该进程在用户模式的运行时
间,在核心模式的运行时间,以及总的运行时间。
实验提示
一、一个应用定时器的简单例子
我们首先来看一个关于 ITIMER_REAL 定时器的例子。在这个例子里面我们将会设置
一个 ITIMER_REAL 类型的定时器,它每过一秒都会发出一个信号,等到定时到达的时候
(即定时器时间值减到 0),程序将统计已经经过的时间。下面是具体的代码:
/*我们在使用 signal 和时钟相关的结构体之前,需要包含这两个头文件*/
#include <signal.h>
#include <sys/time.h>
 
/*声明信号处理函数,信号相关内容将在第八章同步机制中讲述,读者在这里只要明白这个函数是
在进程收到信号的时候调用就可以了*/
static void sig_handler(int signo);
 
long lastsec,countsec;    /*这两个变量分别用来保存上一秒的时间和总共花去的时间*/
 
int main(void)
{
                struct itimerval v;              /*定时器结构体,结构体内容请参阅第三节中的介绍*/
                long nowsec,nowusec;      /*当前时间的秒数和微秒数*/                 /*注册 SIGUSR1 和 SIGALARM 信号的处理函数为 sig_handler*/
                if(signal(SIGUSR1,sig_handler)==SIG_ERR)
                {
                                printf("Unable to create handler for SIGUSR1\n");
                                exit(0);
                }
                if(signal(SIGALRM,sig_handler)==SIG_ERR)
                {
                                printf("Unable to create handler for SIGALRM\n");
                                exit(0);
                }
                /*初始化定时器初值和当前值*/
                v.it_interval.tv_sec=9;
                v.it_interval.tv_usec=999999;
                v.it_value.tv_sec=9;
                v.it_value.tv_usec=999999;
                 
/*调用 setitimer 设置定时器,并将其挂到定时器链表上,这个函数的三个参数的含义分
别是设置 ITIMER_REAL 类型的定时器,要设置的值存放在变量 v 中,该定时器设置前
的值在设置后保存的地址,如果是这个参数为 NULL,那么就放弃保存设置前的值*/
                setitimer(ITIMER_REAL,&v,NULL);
       
                lastsec=v.it_value.tv_sec;
                countsec=0;
 
/*该循环首先调用 getitimer 读取定时器当前值,再与原来的秒数比较,当发现已经过了
一秒后产生一个 SIGUSR1 信号,程序就会进入上面注册过的信号处理函数*/
                while(1)
                {
                                getitimer(ITIMER_REAL,&v);
                                nowsec=v.it_value.tv_sec;
                                nowusec=v.it_value.tv_usec;
                                if(nowsec==lastsec-1)
{
                                    /*每过一秒,产生一个 SIGUSR1 信号*/
                                                raise(SIGUSR1);     
                                                lastsec=nowsec;
                                                countsec++;            /*记录总的秒数*/
                                }
                }       
}
 
/*信号处理函数*/
static void sig_handler(int signo)
{
                switch(signo)
                {
                                /*接收到的信号是 SIGUSR1,打印 One second passed*/
                                case SIGUSR1:                                                 printf("One second passed\n");
                                                break;
                                /*定时器定时到达*/
                                case SIGALRM:
                                {
                                                printf("Timer has been zero,elapsed %d seconds\n",countsec);
                                                lastsec=countsec;
                                                countsec=0;
                                                break;
                                }
                }
}
 
上面的程序比较简单,主要是给大家看一下定时器的设置和读取的方法。下面我们将上
面的程序稍作修改,利用本章第一节介绍过的与进程相关的三种定时器来统计一个进程的用
户模式时间、核心模式时间、CPU 时间和总的进程执行时间。
二、统计关于进程的时间
我们在第一节介绍过和 Linux 进程相关的定时器有三种。ITIMER_REAL 实时计数;
ITIMER_VIRTUAL 统计进程在用户模式(进程本身执行)执行的时间;ITIMER_PROF 统
计进程在用户模式(进程本身执行)和核心模式(系统代表进程执行)下的执行时间,与
ITIMER_VIRTUAL 比较,这个计时器记录的时间多了该进程核心模式执行过程中消耗的时
间。通过在一个进程中设定这三个定时器,我们就可以了解到一个进程在用户模式、核心模
式以及总的运行时间。下面的这个程序除了定义了三个定时器和信号处理过程以外,其它的
地方和上面的程序完全相同。
 
#include <signal.h>
#include <sys/time.h>
 
static void sig_handler(int signo);
long countsec,lastsec,nowsec;
 
int main(void)
{
                struct itimerval v;
 
      /*注册信号处理函数*/
                if(signal(SIGUSR1,sig_handler)==SIG_ERR)
                {
                                printf("Unable to create handler for SIGUSR1\n");
                                exit(0);
                }
                if(signal(SIGALRM,sig_handler)==SIG_ERR)
                {
                printf("Unable to create handler for SIGALRM\n");
                                exit(0);
                }  
                v.it_interval.tv_sec=10;
                v.it_interval.tv_usec=0;
                v.it_value.tv_sec=10;
                v.it_value.tv_usec=0;
 
/*调用 setitimer 设置定时器,并将其挂到定时器链表上,这个函数的三个参数的含义分
别是设置何种类型的定时器;要设置的值存放在变量 v 中;该定时器设置前的值在设置
后保存的地址,如果是这个参数为 NULL,那么就放弃保存设置前的值*/
                setitimer(ITIMER_REAL,&v,NULL);
                setitimer(ITIMER_VIRTUAL,&v,NULL);
                setitimer(ITIMER_PROF,&v,NULL);
                countsec=0;
                lastsec=v.it_value.tv_sec;
                while(1)
                {
                                getitimer(ITIMER_REAL,&v);
                                nowsec=v.it_value.tv_sec;
                                if(nowsec==lastsec-1)
                                {
                                                if(nowsec<9)
                                                {
                                                                /*同上面一样,我们每隔一秒发送一个 SIGUSR1 信号*/
                                                                raise(SIGUSR1);
                                                                countsec++;
                                                }
                                                lastsec=nowsec;
                                }
}       
}
 
static void sig_handler(int signo)
{
                struct itimerval u,v;
                long t1,t2;
 
                switch(signo)
                {
                                case SIGUSR1:
                                        /*显示三个定时器的当前值*/
                                                getitimer(ITIMER_REAL,&v);
                                                printf("real time=%.ld secs %ld
usecs\n",9-v.it_value.tv_sec,999999-v.it_value.tv_usec);
                                                getitimer(ITIMER_PROF,&u);
                                                printf("cpu time=%ld secs %ld
usecs\n",9-u.it_value.tv_sec,999999-u.it_value.tv_usec);
                                                getitimer(ITIMER_VIRTUAL,&v);
                                                printf("user time=%ld secs %ld
usecs\n",9-v.it_value.tv_sec,999999-v.it_value.tv_usec);                                                 /*当前 prof timer 已经走过的微秒数*/
                                                t1=(9-u.it_value.tv_sec)*1000000+(1000000-u.it_value.tv_usec);
                                                /*当前 virtual timer 已经走过的微秒数*/
                                                t2=(9-v.it_value.tv_sec)*1000000+(1000000-v.it_value.tv_usec);
                                                /*计算并显示 kernel time*/
                                                printf("kernel time=%ld secs %ld
usecs\n\n",(t1-t2)/1000000,(t1-t2)%1000000);
                                                break;
                case SIGALRM:
                                printf("Real Timer has been zero,elapsed %d seconds\n",countsec);
                                exit(0);
                                break;
                }
}
 
从上面的程序可以看出来,ITIMER_REAL 定时器运行的时间就是总运行时间,
ITIMER_PROF 定时器的运行时间就是 CPU 花在该进程上的所有时间。ITIMER_VIRTUAL
定时器运行的时间是进程在用户模式的运行时间。ITIMER_PROF 定时器的运行时间减去
ITIMER_VIRTUAL 定时器的运行时间就是进程在核心模式的运行时间。
三、更进一步的进程时间统计
上面的程序只在很短的时间内统计了进程在各种状态的执行时间。但是进程并没有真正
的负载作业,和现实中的进程差距比较大。下面我们要继续修改上面的程序,让这个进程做
点“事情”,然后我们再来看看在和实际情况比较相近的状态下定时器统计到的进程在各个
状态下的时间。在这个程序里面我们将创建两个子进程,加上父进程总共三个进程,这三个
进程分别调用 fibonacci()计算 fibonacci 数。在计算之前我们初始化定时器,完成之后,我们
将读取定时器,然后来统计进程相关的各种时间。
 
#include <sys/time.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
 
long unsigned int fibonacci(unsigned int n);    /*计算 fibonacci 数的函数*/
static void par_sig(int signo);    /*父进程的信号处理函数*/
static void c1_sig(int signo);      /*子进程 1 的信号处理函数*/
static void c2_sig(int signo);      /*子进程 2 的信号处理函数*/
 
/*用于分别记录父,子 1,子 2 进程 real time 过的总秒数*/
static long p_realt_secs=0,c1_realt_secs=0,c2_realt_secs=0;     
/*用于分别记录父,子 1,子 2 进程 virtual time 过的总秒数*/
static long p_virtt_secs=0, c1_virtt_secs=0,c2_virtt_secs=0;
/*用于分别记录父,子 1,子 2 进程 proft time 过的总秒数*/
static long p_proft_secs=0,c1_proft_secs=0,c2_proft_secs=0;     
/*用于分别取出父,子 1,子 2 进程的 real timer 的值*/
static struct itimerval p_realt,c1_realt,c2_realt;     
/*用于分别取出父,子 1,子 2 进程的 virtual timer 的值*/ static struct itimerval p_virtt,c1_virtt,c2_virtt;     
/*用于分别取出父,子 1,子 2 进程的 proft timer 的值*/
static struct itimerval p_proft,c1_proft,c2_proft;     
 
int main()
{
                long unsigned fib=0;
                int pid1,pid2;
                unsigned int fibarg=39;
                int status;
                struct itimerval v;
                long moresec,moremsec,t1,t2;
 
                pid1=fork();
                if(pid1==0)
                {
                                /*设置子进程 1 的信号处理函数和定时器初值*/
                                signal(SIGALRM,c1_sig);
                                signal(SIGVTALRM,c1_sig);
                                signal(SIGPROF,c1_sig);
                                v.it_interval.tv_sec=10;
                                v.it_interval.tv_usec=0;
                                v.it_value.tv_sec=10;
                                v.it_value.tv_usec=0;
                                setitimer(ITIMER_REAL,&v,NULL);
                                setitimer(ITIMER_VIRTUAL,&v,NULL);
                                setitimer(ITIMER_PROF,&v,NULL);
                                fib=fibonacci(fibarg);    /*计算 fibonacci 数*/
                                /*取出子进程 1 的定时器值*/
                                getitimer(ITIMER_PROF,&c1_proft);     
                                getitimer(ITIMER_REAL,&c1_realt);
                                getitimer(ITIMER_VIRTUAL,&c1_virtt);
/*通过定时器的当前值和各信号发出的次数计算子进程 1 总共用的 real time,cpu
time,user time 和 kernel time。moresec 和 moremsec 指根据定时器的当前值计算
出的自上次信号发出时过去的 real time,cpu time,user time 和 kernel time。计算
kernel time 时,moresec 和 moremsec 为 kernel time 的实际秒数+毫秒数*/
                                moresec=9-c1_realt.it_value.tv_sec;
moremsec= (1000000-c1_realt.it_value.tv_usec)/1000;
                                printf("Child 1 fib=%ld , real time=%ld sec,%ld
msec\n",fib,c1_realt_secs+moresec,moremsec);
                                moresec=9-c1_proft.it_value.tv_sec;
                                moremsec=(1000000-c1_proft.it_value.tv_usec)/1000;
                                printf("Child 1 fib=%ld , cpu time=%ld sec,%ld
msec\n",fib,c1_proft_secs+moresec,moremsec);
                                moresec=9-c1_virtt.it_value.tv_sec;
moremsec=(1000000-c1_virtt.it_value.tv_usec)/1000;
                                printf("Child 1 fib=%ld , user time=%ld sec,%ld
msec\n",fib,c1_virtt_secs+moresec,moremsec);                                         
t1=(9-c1_proft.it_value.tv_sec)*1000+(1000000-c1_proft.it_value.tv_usec)/1000+c1_proft_secs*10000;
t2=(9-c1_virtt.it_value.tv_sec)*1000+(1000000-c1_virtt.it_value.tv_usec)/1000+c1_v
i rtt_secs*10000;
                                moresec=(t1-t2)/1000;moremsec=(t1-t2)%1000;
                                printf("Child 1 fib=%ld , kernel time=%ld sec,%ld msec\n",fib,moresec,moremsec);
                                fflush(stdout);
                                exit(0);             
                }
                else
                {
                                pid2=fork();
                                if(pid2==0)
                                {
                                                /*设置子进程 2 的信号处理函数和定时器初值*/
                                                signal(SIGALRM,c2_sig);
                                                signal(SIGVTALRM,c2_sig);
                                                signal(SIGPROF,c2_sig);
                                                v.it_interval.tv_sec=10;
                                                v.it_interval.tv_usec=0;
                                                v.it_value.tv_sec=10;
                                                v.it_value.tv_usec=0;
                                                setitimer(ITIMER_REAL,&v,NULL);
                                                setitimer(ITIMER_VIRTUAL,&v,NULL);
                                                setitimer(ITIMER_PROF,&v,NULL);
                                                fib=fibonacci(fibarg);
                                                /*取出子进程 2 的定时器值*/
                                                getitimer(ITIMER_PROF,&c2_proft);
                                                getitimer(ITIMER_REAL,&c2_realt);
                                                getitimer(ITIMER_VIRTUAL,&c2_virtt);
/*通过定时器的当前值和各信号发出的次数计算子进程 2 总共用的 real
time,cpu time,user time 和 kernel time。moresec 和 moremsec 指根据定时
器的当前值计算出的自上次信号发出时过去的 real time,cpu time,user
time 和 kernel time。计算 kernel time 时,moresec 和 moremsec 为 kernel
time 的实际秒数+毫秒数*/
                                                moresec=9-c2_realt.it_value.tv_sec;
                                                moremsec=(1000000-c2_realt.it_value.tv_usec)/1000;
                                        printf("Child 2 fib=%ld , real time=%ld sec,%ld   
msec\n",fib,c2_realt_secs+moresec,moremsec);
                                                moresec=9-c2_proft.it_value.tv_sec;
                                moremsec=(1000000-c2_proft.it_value.tv_usec)/1000;
                                              printf("Child 2 fib=%ld , cpu time=%ld sec,%ld   
msec\n",fib,c2_proft_secs+moresec,moremsec);
                                                moresec=9-c2_virtt.it_value.tv_sec;
moremsec=(1000000-c2_virtt.it_value.tv_usec)/1000;
                                                printf("Child 2 fib=%ld , user time=%ld sec,%ld
                                msec\n",fib,c2_virtt_secs+moresec,moremsec);
                 
t1=(9-c2_proft.it_value.tv_sec)*1000+(1000000-c2_proft.it_value.tv_usec)/
1000+c2_proft_secs*10000;                  
t2=(9-c2_virtt.it_value.tv_sec)*1000+(1000000-c2_virtt.it_value.tv_usec)/1
000+c2_virtt_secs*10000;
                                                moresec=(t1-t2)/1000;
moremsec=(t1-t2)%1000;
                                                printf("Child 2 fib=%ld , kernel time=%ld sec,%ld
msec\n",fib,moresec,moremsec);
                                                fflush(stdout);
                                                exit(0);
                                }   
                                else
                                {
                                                /*设置父进程的信号处理函数和定时器初值*/
                                                signal(SIGALRM,par_sig);
                                                signal(SIGVTALRM,par_sig);
                                                signal(SIGPROF,par_sig);
                                                v.it_interval.tv_sec=10;
                                                v.it_interval.tv_usec=0;
                                                v.it_value.tv_sec=10;
                                                v.it_value.tv_usec=0;
                                                setitimer(ITIMER_REAL,&v,NULL);
                                                setitimer(ITIMER_VIRTUAL,&v,NULL);
                                                setitimer(ITIMER_PROF,&v,NULL);
                                                fib=fibonacci(fibarg);
                                                /*取出父进程的定时器值*/
                                                getitimer(ITIMER_PROF,&p_proft);
                                                getitimer(ITIMER_REAL,&p_realt);
                                                getitimer(ITIMER_VIRTUAL,&p_virtt);
/*通过定时器的当前值和各信号发出的次数计算子进程 1 总共用的
real time,cpu time,user time 和 kernel time。moresec 和 moremsec 指根据
定时器的当前值计算出的自上次信号发出时过去的 real time,cpu
time,user time 和 kernel time。计算 kernel time 时,moresec 和 moremsec
为 kernel time 的实际秒数+毫秒数*/
                                                moresec=9-p_realt.it_value.tv_sec;
moremsec=(1000000-p_realt.it_value.tv_usec)/1000;
                                                printf("Parent fib=%ld , real time=%ld sec,%ld
msec\n",fib,p_realt_secs+moresec,moremsec);
                                                moresec=9-p_proft.it_value.tv_sec;
moremsec=(1000000-p_proft.it_value.tv_usec)/1000;
                                                printf("Parent fib=%ld , cpu time=%ld sec,%ld
msec\n",fib,p_proft_secs+moresec,moremsec);
                                                moresec=9-p_virtt.it_value.tv_sec;
moremsec=(1000000-p_virtt.it_value.tv_usec)/1000;
                                                printf("Parent fib=%ld , user time=%ld sec,%ld
msec\n",fib,p_virtt_secs+moresec,moremsec);
                   
t1=(9-p_proft.it_value.tv_sec)*1000+(1000000-p_proft.it_value.tv_usec)/1
000+p_proft_secs*10000;
                 7t2=(9-p_virtt.it_value.tv_sec)*1000+(1000000-p_virtt.it_value.tv_usec)/10
00+p_virtt_secs*10000;
                                                moresec=(t1-t2)/1000;
moremsec=(t1-t2)%1000;
                                                printf("Parent fib=%ld , kernel time=%ld sec,%ld
msec\n",fib,moresec,moremsec);
                                                fflush(stdout);
                                                waitpid(0,&status,0);
                                                waitpid(0,&status,0);
                                                exit(0);
                                }
                                printf("this line should never be printed\n");
                }
}
 
long unsigned fibonacci(unsigned int n)
{
                if(n==0)
                                return 0;
                else if(n==1||n==2)
                                return 1;
                else
                                return (fibonacci(n-1)+fibonacci(n-2));
}
 
/*父进程信号处理函数;每个 timer 过 10 秒减为 0,激活处理函数一次,相应的计数器加 10*/
static void par_sig(int signo)
{
 
                switch(signo)
                {
                                case SIGALRM:
                                                p_realt_secs+=10;
                                                break;
                                case SIGVTALRM:
                                                p_virtt_secs+=10;
                                                break;
                                case SIGPROF:
                                                p_proft_secs+=10;
                                                break;
                }
}
 
/*子进程 1 的信号处理函数,功能与父进程的信号处理函数相同*/
static void c1_sig(int signo)
{
 
                switch(signo)
                {                                 case SIGALRM:
                                                c1_realt_secs+=10;
                                                break;
                                case SIGVTALRM:
                                                c1_virtt_secs+=10;
                                                break;
                                case SIGPROF:
                                                c1_proft_secs+=10;
                                                break;
                }
}
 
/*子进程 2 的信号处理函数,功能与父进程的信号处理函数相同*/
static void c2_sig(int signo)
{
 
                switch(signo)
                {
                                case SIGALRM:
                                                c2_realt_secs+=10;
                                                break;
                                case SIGVTALRM:
                                                c2_virtt_secs+=10;
                                                break;
                                case SIGPROF:
                                                c2_proft_secs+=10;
                                                break;
                }
}
 
在上面的程序中,我们为三个进程使用了三个不同的信号处理函数,这是因为每个进程
需要处理的数据不同。如果在 Linux 中运行这个程序,那么我们就可以看到下面的结果:
Child 1 fib=63245986 , real time=20 sec,250 msec
Child 1 fib=63245986 , cpu time=6 sec,840 msec
Child 1 fib=63245986 , user time=6 sec,800 msec
Child 1 fib=63245986 , kernel time=0 sec,40 msec
Child 2 fib=63245986 , real time=20 sec,380 msec
Child 2 fib=63245986 , cpu time=6 sec,850 msec
Child 2 fib=63245986 , user time=6 sec,840 msec
Child 2 fib=63245986 , kernel time=0 sec,10 msec
Parent fib=63245986 , real time=20 sec,290 msec
Parent fib=63245986 , cpu time=6 sec,870 msec
Parent fib=63245986 , user time=6 sec,820 msec
Parent fib=63245986 , kernel time=0 sec,50 msec
大家可以试着运行一下,看看结果是不是如上所示。当然每个人得到的具体时间可能都
不同,这个要看具体机器的运算速度。

Linux 定时器应用【转】的更多相关文章

  1. linux定时器用法

    linux定时器  原文出自http://www.cnblogs.com/processakai/archive/2012/04/11/2442294.html 今天看书看到了关于alarm的一些用法 ...

  2. linux定时器crontab

    linux定时器crontab用法: 1.基本格式 : * * * * * command 分 时 日 月 周 命令 第1列表示分钟1-59 每分钟用*或者 */1表示 第2列表示小时1-23(0表示 ...

  3. 4412 Linux定时器

    一.Linux定时器基础知识 1.1 定时器的使用范围 延后执行某个操作,定时查询某个状态:前提是对时间要求不高的地方 1.2 内核时间概念 Hz:(系统时钟通过CONFIG_HZ来设置,范围是100 ...

  4. linux定时器(crontab)实例

    linux实验示例----实现每2分钟将“/etc”下面的文件打包存储到“/usr/lobal”目录下 ·Step1:编辑当前用户的crontab并保存终端输入:>crontab -u root ...

  5. Linux定时器相关源码分析

    Linux的定时器使用时间轮算法.数据结构不难理解,核心数据结构与散列表及其相似,甚至可以说,就是散列表.事实上,理解其散列表的本质,有助于对相关操作的理解. 数据结构 这里先列出一些宏,稍后解释: ...

  6. Smart210学习记录-----linux定时器

    1.内核定时器: Linux 内核所提供的用于操作定时器的数据结构和函数如下: (1) timer_list 在 Linux 内核中,timer_list 结构体的一个实例对应一个定时器 1 stru ...

  7. linux 定时器编程实例(完善中).....

    最近在写linux 下的定时器编程实验,测试发现 usleep函数在 x86 架构下的定时还是比较准确的,在arm9下 就不太准了. 今天用linux 下的setitimer()函数进行了定时 器的测 ...

  8. linux定时器HZ和Jiffies

    1.linux HZ Linux核心几个重要跟时间有关的名词或变数,以下将介绍HZ.tick与jiffies. HZ Linux核心每隔固定周期会发出timer interrupt (IRQ 0),H ...

  9. linux定时器

    我们常常有设置系统在某一时间执行相应动作的需求,比如设置电脑什么时候自动锁屏,什么时候自动关机,设置应用程序什么时候自动运行,什么时候自动退出.这些与时间相关的功能,都需要依靠操作系统中的定时器来实现 ...

随机推荐

  1. java入门--4111:判断游戏胜者-Who Is the Winner

    基础的题目 学习了StringBuilder, 通过delete来清空它 学了Map的简单用法 import java.util.*; public class Main { public stati ...

  2. style和getComputedStyle(ff)和currentStyle

    obj.style:这个方法只能JS只能获取写在html标签中的写在style属性中的值(style=”…”),而无法获取定义在<style type="text/css"& ...

  3. Photoshop一些常用的快捷键

    1.按住Alt键,点击图层上的小眼睛,只显示当前图层 2.新建纯色图层,抠图 3.Fn+ num 调整不透明度 4.Shift + num 调整流量 5.调整图层透明度,在移动工具状态下,输入数字:0 ...

  4. Linux命令(十六) 压缩或解压缩文件和目录 zip unzip

    目录 1.命令简介 2.常用参数介绍 3.实例 4.直达底部 命令简介 zip 是 Linux 系统下广泛使用的压缩程序,文件压缩后扩展名为 ".zip". zip 命令用来将文件 ...

  5. PGSQL 数据库备份练习

    截图先 慢慢说 1. 简单使用方法 先用 之前的setx 命令设置环境变量. set path=%PATH% ---其实第一步没必要..... 跟人学的 setx PATH "%path%& ...

  6. Kivy 中文教程 实例入门 简易画板 (Simple Paint App):0. 项目简介 & 成果展示

    本教程咪博士将带领大家学习创建自己的窗口部件 (widget).最终,我们完成的作品是一个简易的画板程序. 当用 kivy 创建应用时,我们需要仔细思考以下 3 个问题: 我们创建的应用需要处理什么数 ...

  7. 思维题练习专场-DP篇(附题表)

    转载请注明原文地址http://www.cnblogs.com/LadyLex/p/8536399.html 听说今年省选很可怕?刷题刷题刷题 省选已经结束了但是我们要继续刷题刷题刷题 目标是“有思维 ...

  8. MT【181】横穿四象限

    设函数$f(x)=\dfrac{1}{x-a}-\dfrac{\lambda}{x-2}$,其中$a,\lambda\in R$记$A_1=\{(x,y)|x>0,y>0\},A_2=\{ ...

  9. 【刷题】LOJ 2587 「APIO2018」铁人两项

    题目描述 比特镇的路网由 \(m\) 条双向道路连接的 \(n\) 个交叉路口组成. 最近,比特镇获得了一场铁人两项锦标赛的主办权.这场比赛共有两段赛程:选手先完成一段长跑赛程,然后骑自行车完成第二段 ...

  10. 【题解】 bzoj1923: [Sdoi2010]外星千足虫 (线性基/高斯消元)

    bzoj1923,戳我戳我 Solution: 这个高斯消元/线性基很好看出来,主要是判断在第K 次统计结束后就可以确定唯一解的地方和\(bitset\)的骚操作 (我用的线性基)判断位置,我们可以每 ...