接下来对程序进程测试。
编译,需要加多两个库:-lpthread -lrt
ubuntu@ubuntu:~/test/timer_create$ gcc timer_test.c -o timer_test -lpthread -lrt
先执行测试一下,发现测试程序已经有提示了,按照提示来测试。
ubuntu@ubuntu:~/test/timer_create$ ./timer_test
please input eg: ./timer_test 1|2|31:userSIGALRM2:userSIGUSR13:user thread
首先,测试setitimer函数,它在程序中会产生SIGALRM信号
ubuntu@ubuntu:~/test/timer_create$ ./timer_test 1func:main ,process id is 7186func:vPthreadInit
pthread func:vSleepProc
pthread func:vTimerProc
signal_func:1s-----> take 535951046 ms,signo=SIGALRM(14)
main:sleep5s take 1000 ms
signal_func:1s-----> take 1000 ms,signo=SIGALRM(14)
main:sleep5s take 1000 ms
signal_func:1s-----> take 1000 ms,signo=SIGALRM(14)
main:sleep5s take 1000 ms
signal_func:1s-----> take 1000 ms,signo=SIGALRM(14)
main:sleep5s take 1000 ms
signal_func:1s-----> take 1000 ms,signo=SIGALRM(14)
main:sleep5s take 1000 ms
vSleepProc:sleep5s take 5001 ms
vTimerProc:sleep5s take 5000 ms
signal_func:1s-----> take 1000 ms,signo=SIGALRM(14)
main:sleep5s take 1000 ms
signal_func:1s-----> take 1000 ms,signo=SIGALRM(14)
main:sleep5s take 1000 ms
^C
从以上的测试结果看出,在main函数使用sleep 5秒,但是打印main:sleep 5s take 1000 ms,也就是睡眠5秒,结果1秒就被打断。这是因为线程发出的SIGALRM信号被sleep函数接收了。如果想知道具体是什么终止了sleep函数,可以去看看它的实现。在测试程序中,我是把注册信号的函数放在了主线程。其实在测试的时候,我有把初始化信号函数vTimerInit放在线程vTimerProc中测试,结果也是一样的。这就可以证明结论二。而子线程vSleepProc和子线程vTimerProc中调用sleep函数并没有被终止就可以证明结论一。
结论一:默认情况下,信号将由主进程接收处理,就算信号处理函数是由子线程注册的。
结论二:对信号的处理是进程中所有的线程共享的。
接着再测试timer_create函数,注册信号是SIGUSR1。
ubuntu@ubuntu:~/test/timer_create$ ./timer_test 2func:main ,process id is 7189func:vPthreadInit
pthread func:vSleepProc
pthread func:vTimerProc
signal_func:1s-----> take 535963773 ms,signo=SIGUSR1(10)
main:sleep5s take 1001 ms
signal_func:1s-----> take 1000 ms,signo=SIGUSR1(10)
main:sleep5s take 1000 ms
signal_func:1s-----> take 1000 ms,signo=SIGUSR1(10)
main:sleep5s take 1000 ms
signal_func:1s-----> take 999 ms,signo=SIGUSR1(10)
main:sleep5s take 999 ms
signal_func:1s-----> take 1000 ms,signo=SIGUSR1(10)
main:sleep5s take 1000 ms
vSleepProc:sleep5s take 5000 ms
vTimerProc:sleep5s take 5000 ms
signal_func:1s-----> take 1000 ms,signo=SIGUSR1(10)
main:sleep5s take 1000 ms
signal_func:1s-----> take 1000 ms,signo=SIGUSR1(10)
main:sleep5s take 1000 ms
signal_func:1s-----> take 1000 ms,signo=SIGUSR1(10)
main:sleep5s take 1000 ms
^C
结果竟然和上一个结果是一样的。说明使用信号SIGUSR1还是会中断main函数的sleep函数。目前来说,我并不清楚为什么会影响到。
最后,测试不采用信号通知的方式,直接通知线程的方式:
ubuntu@ubuntu:~/test/timer_create$ ./timer_test 3func:main ,process id is 7192func:vPthreadInit
pthread func:vSleepProc
pthread func:vTimerProc
timer_thread:1s-----> take 535974740 ms, v.sival_int = 1111timer_thread:1s-----> take 1000 ms, v.sival_int = 1111timer_thread:1s-----> take 1000 ms, v.sival_int = 1111timer_thread:1s-----> take 1000 ms, v.sival_int = 1111main:sleep5s take 5001 ms
timer_thread:1s-----> take 1000 ms, v.sival_int = 1111vSleepProc:sleep5s take 5001 ms
vTimerProc:sleep5s take 5001 ms
timer_thread:1s-----> take 1000 ms, v.sival_int = 1111timer_thread:1s-----> take 1000 ms, v.sival_int = 1111timer_thread:1s-----> take 1000 ms, v.sival_int = 1111timer_thread:1s-----> take 999 ms, v.sival_int = 1111main:sleep5s take 5000 ms
timer_thread:1s-----> take 1001 ms, v.sival_int = 1111vSleepProc:sleep5s take 5000 ms
vTimerProc:sleep5s take 5000 ms
timer_thread:1s-----> take 999 ms, v.sival_int = 1111timer_thread:1s-----> take 1001 ms, v.sival_int = 1111
^C
从以上结果看,使用这种方式,并没有使sleep函数终止,无论是主线程还是两个子线程,说明在应用层使用这种方式是可行的。
最后的最后,由于项目中的嵌入式linux系统中的时钟被设置为10ms,所以在应用层只能产生最高100hz的脉冲,这对步进电机来说还是有点慢,所以,没办法还是得用硬件定时中断,实现linux设备驱动。不过,对于I2C这种时钟要求不高的情况,或许可以一试。还有,提醒一点:usleep函数在应用层中是相当不精准的,select函数实现延时效果较好,但还是误差挺大的,所以才需要软件定时器。