Understanding Unix/Linux Programming-时钟编程:Alarms

本文详细解析了Unix系统中sleep与alarm的工作原理及其内部机制,包括如何利用SIGALRM信号实现进程挂起,并介绍了计时器的不同类型及其应用场景。
  • sleep:添加时延
    • sleep(n)将当前的进程挂起n秒或者在此期间被一个不能忽略的信号的到达所唤醒
  • sleep是如何工作的
    • 系统中的每个进程都有一个私有的闹钟(alarm clock)。这个闹钟很像一个计时器,可以设置在一定秒数后闹铃。时间一到,时钟就发送一个信号SIGALRM到进程。除非SIGALRM设置了处理函数,否则信号将杀死这个进程。sleep函数由以下三个步骤组成:
      1. 为SIGALRM设置一个处理函数
      2. 调用alarm(num_seconds)
      3. 调用pause。
    • 系统调用pause挂起进程直到信号到达。任何信号都可以唤醒进程,而非仅仅等待SIGALRM。将以上想法总结为以下代码:

 

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <signal.h>
 4 
 5 void wakeup(int signum);
 6 
 7 int main()
 8 {
 9     printf("About to sleep for 4 seconds.\n" );
10     signal(SIGALRM , wakeup );
11     alarm(4);
12     pause();
13     printf("Morning so soon ? \n" );
14 }
15 
16 void wakeup(int signum)
17 {
18     printf("Alarm received from kernel.\n");
19 }
  • sleep的细节:
    • 返回值:
      • -1:出错
      • old : 计时器剩余的时间
    • alarm设置本进程的计时器到seconds秒后激发信号SIGALRM。当设定的时间过去之后,内核发送SIGALRM到这个进程。如果计时器已经被设置,alarm返回剩余的秒数。调用alarm(0)意味着关闭闹钟,这一点值得注意。
  • pause细节:
    • pause挂起一个进程直到一个信号到达。如果调用进程被这个信号终止,pause没有返回。如果调用进程用一个处理函数捕获,则在控制从处理函数处返回后pause返回。这种情况下,errno被设置为EINTR。
  • 计时器的另一个用途:
    • 在将来的某个时刻发生的动作同时做一些其他事情。调度一个将要发生的动作很简单,通过alarm来设置计时器,然后继续做别的事情。当计时器计到0,处理函数被调用。
    • Unix很早就有sleep和alarm,提供的计时精度为秒。后来一个更强大和使用广泛的计时系统被引用。新的计时系统使用“间隔计时器”的概念,精度更高。
    • 每个进程都有3个独立的计时器,而不是原来的一个。
      1. ITIMER_REAL,真实时间——SIGALRM
      2. ITIMER_VIRTUAL,进程时间:用户时间——SIGVTALRM
      3. ITIMER_PROF,实用时间:用户时间+系统时间——SIGPROF
    • 每个计时器都有两个设置:初始间隔和重复间隔设置。
      1. 初始间隔:一次延时
      2. 重复间隔:延时重复
      3. 举例:医生给你一些药,告诉你:过一小时吃第一粒,然后每隔4小时吃一粒。
    • 新的系统还支持alarm和sleep。
  • 用间隔计时器编程:
1-01 21:01:23.037168 2416 2416 D tcmd : waiting on events (-1ms) 01-01 21:01:23.040487 3218 3370 D face_aidl.Handler: treadLoop name=HealthMonitor 01-01 21:01:23.040577 3218 7133 D face_aidl.ImageReaderHelper: have wakeuped 01-01 21:01:23.040648 3218 7133 D face_aidl.ImageReaderHelper: wait wakeup 01-01 21:01:23.043501 3218 7132 D face_aidl.Handler: treadLoop name=AlgoEngine 01-01 21:01:23.045238 3623 4636 D AlarmManager: get result from waitForAlarm: result = 0x10008 01-01 21:01:23.045313 3623 4636 V AlarmManager: Checking for alarms... rtc=1735736483045, elapsed=1726287, nextNoWakeup = 2565320, PendingNonWakeupAlarmsSize = 0, result = 0x10008, hasPendingIdle = true 01-01 21:01:23.045389 3623 4661 I HidlSensorManager: hidl_ssvc_poll: spurious wake up, back to work 01-01 21:01:23.045430 3623 4666 I AidlSensorManager: aidl_ssvc_poll: spurious wake up, back to work 01-01 21:01:23.055264 14213 14214 E IHansComunication: HANS printMessageBody: RCV message: type = 1,port = 86870,caller_pid = 3623,caller_uid = 1000,target_pid = 6015,target_uid = 1001,pkg_cmd = -1,rpc = SYNC_BINDER_REPLY/-1 01-01 21:01:23.057167 7698 7738 I ostats_tpd: stats_write, records atomId:100100, event_id:868, cpu:4, values: 868-0-1-13558-(vbat)-3-0-1 01-01 21:01:23.057227 7698 7738 I ostats_tpd: stats_write, records atomId:100100, event_id:868, cpu:4, values: 868-0-1-13558-(vbat)-3-1-1 01-01 21:01:23.057238 7698 7738 I ostats_tpd: stats_write, records atomId:100100, event_id:868, cpu:4, values: 868-0-1-13558-(vbat)-3-2-1 01-01 21:01:23.057527 5942 6922 D PhoneInterfaceManager: QueryTelephonyChecker-getDataNetworkTypeForSubscriber: packageName = com.oplus.nhs, isGrant = true 01-01 21:01:23.058268 5942 6922 E PhoneInterfaceManager: getDataNetworkTypeForSubscriber: phone is null for sub -1 01-01 21:01:23.060747 6015 6618 D HoraeHelper: skinThermal:29.631 01-01 21:01:23.060903 6015 6618 I ModemAci: [CommonInfo] [LS, DA]:{ stamp=1502081 duration=1465 screenOnT=1689 wifiConnectT=0 power=94 dataNetworkType=0 signalStrength=0 batteryCapacity=4590 thermal[]=29.631 softAp=false charge=false simCount=0 defaultPhone=-1 networkType=null sim1Type=unknown sim2Type=unknown} 01-01 21:01:23.061205 3623 5170 V ActivityManager: Broadcast: Intent { act=oplus.intent.action.MDPWR_UPDATE_TRAFFIC_KERNEL_INFO pkg=null } ordered=false userid=-1 resultTo null 01-01 21:01:23.061301 3623 5170 V ActivityManager: broadcastIntentLocked callingPid: 6015 callingUid=1001 01-01 21:01:23.062557 2825 2825 D vendor.oplus.hardware.rpmh-V1-service: Calling uid is 1000. 01-01 21:01:23.062606 2825 2825 D vendor.oplus.hardware.rpmh-V1-service: vendor.oplus.rpmh.support: true 01-01 21:01:23.062609 2825 2825 D vendor.oplus.hardware.rpmh-V1-service: getPowerStateSubsystemSleepStateList() 01-01 21:01:23.062613 2825 2825 D vendor.oplus.hardware.rpmh-V1-service: last update:1501587 , 1726304 01-01 21:01:23.062672 2825 2825 D vendor.oplus.hardware.rpmh-V1-service: parseSubsystemSleepState at: ADSP | /sys/module/qcom_stats/rpmh_stats/oplus_rpmh_master_stats 01-01 21:01:23.062754 2825 2825 D vendor.oplus.hardware.rpmh-V1-service: reading line: modem:2c10:184e04 01-01 21:01:23.062758 2825 2825 D vendor.oplus.hardware.rpmh-V1-service: reading line: adsp:498:1a0832 01-01 21:01:23.062762 2825 2825 D vendor.oplus.hardware.rpmh-V1-service: match data: adsp 1176 1706034 01-01 21:01:23.062764 2825 2825 D vendor.oplus.hardware.rpmh-V1-service: data get success解析log
最新发布
08-20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值