alarm 和 sleep
http://blog.sina.com.cn/s/blog_6a1837e90100uhl3.html
alarm也称为闹钟函数,alarm()用来设置信号SIGALRM在经过参数seconds指定的秒数后传送给目前的进程。如果参数seconds为0,则之前设置的闹钟会被取消,并将剩下的时间返回。要注意的是,一个进程只能有一个闹钟时间,如果在调用alarm之前已设置过闹钟时间,则任何以前的闹钟时间都被新值所代替。
所需头文件
#include<unistd.h>
函数原型
unsigned int alarm(unsigned int seconds)
函数参数
seconds:指定秒数
函数返回值
成功:如果调用此alarm()前,进程已经设置了闹钟时间,则返回上一个闹钟时间的剩余时间,否则返回0。
出错:-1
代码
#include<unistd.h>
#include<signal.h>
void handler() {
printf("Hello\n");
signal(SIGALRM, handler); //让内核做好准备,一旦接受到SIGALARM信号,就执行 handler
alarm();
} void main()
{
int i;
handler();
for(i=;i<;i++) {
printf("sleep %d ...\n",i);
sleep();
}
}
结果:刚开始在main中执行一次,然后每隔5秒执行一次handler()
Hello
sleep 1 ...
sleep 2 ...
sleep 3 ...
sleep 4 ...
sleep 5 ...
Hello
sleep 6 ...
sleep 7 ...
sleep 8 ...
sleep 9 ...
sleep 10 ...
Hello
sleep 11 ...
sleep 12 ...
sleep 13 ...
sleep 14 ...
sleep 15 ...
Hello
sleep 16 ...
sleep 17 ...
sleep 18 ...
sleep 19 ...
sleep 20 ...
Hello
注意:alarm只设定一个闹钟,时间到达并执行其注册函数之后,闹钟便失效。如果想循环设置闹钟,需在其注册函数中在调用alarm函数。
再看下面这个程序
#include<unistd.h>
#include<signal.h>
void handler()
{
printf("Hello\n");
signal(SIGALRM, handler); //让内核做好准备,一旦接受到SIGALARM信号,就执行 handler
alarm();
} void main()
{
int i;
handler();
for(i=;i<;i++)
{
printf("sleep %d ...\n",i);
sleep();
}
}
输出为:
Hello
sleep ...
Hello
sleep ...
Hello
sleep ...
Hello
sleep ...
Hello
sleep ...
Hello
sleep ...
Hello
sleep ...
Hello
sleep ...
Hello
sleep ...
Hello
发现每次执行完handler函数后就打印了sleep*。这是为什么呢?
sleep函数将本进程至于休眠队列中,当进程受到信号后就进入了执行队列,所以进程继续执行,打出了sleep*的打印信息
注意,sleep是将进程至于可中断睡眠,其标志位是TASK_INTERRUPTIBLE ,可中断的睡眠状态的进程会睡眠直到某个条件变为真,比如说产生一个硬件中断、释放进程正在等待的系统资源或是传递一个信号都可以是唤醒进程的条件。
至于可中断睡眠和不可中断睡眠参加下面:
Linux系统进程状态:
PROCESS STATE CODES
Here are the different values that the s, stat and state output specifiers (header "STAT" or "S") will display to describe the state of a process.
D Uninterruptible sleep (usually IO)
R Running or runnable (on run queue)
S Interruptible sleep (waiting for an event to complete)
T Stopped, either by a job control signal or because it is being traced.
W paging (not valid since the 2.6.xx kernel)
X dead (should never be seen)
Z Defunct ("zombie") process, terminated but not reaped by its parent.
Linux 进程有两种睡眠状态,一种interruptible sleep,处在这种睡眠状态的进程是可以通过给它发信号来唤醒的,比如发 HUP 信号给 nginx 的 master 进程可以让 nginx 重新加载配置文件而不需要重新启动 nginx 进程;另外一种睡眠状态是 uninterruptible sleep,处在这种状态的进程不接受外来的任何信号,无论是kill,kill -9,还是kill -15,因为他们完全不受到这些信号的支配,ps 手册里描述的D 状态就是 uninterruptible sleep,可以使用ps命令查看:
[build@kbuild-john ~]$ ps -a -ubuild -o pid,ppid,stat,command
PID PPID STAT COMMAND
17009 1 Ds -bash
17065 1 D ls --color=tty -al
17577 1 D /usr/java/jdk1.5.0_17/bin/java -Xmx512m -classpath /usr/local/a
17629 1 D /usr/java/jdk1.5.0_17/bin/java -Xmx512m -classpath /usr/local/a
Unintelligible(D) VS intelligible(S)
运行:该进程此刻正在执行。
等待:进程能够运行,但没有得到许可,因为CPU分配给另一个进程。调度器可以在下一次任务切换时选择该进程。
睡眠:进程正在睡眠无法运行,因为它在等待一个外部事件。调度器无法在下一次任务切换时选择该进程。
Linux进程的睡眠状态有2种:
一种是可中断睡眠,其标志位是TASK_INTERRUPTIBLE ,可中断的睡眠状态的进程会睡眠直到某个条件变为真,比如说产生一个硬件中断、释放进程正在等待的系统资源或是传递一个信号都可以是唤醒进程的条件。比如你ctrl+c或者kill -9 ,能够立刻让进程响应这些信号(切换到TASK_RUNNING和再次进入就绪队列,执行注册的信号处理函数),不必要等待所需的资源满足后再响应这些信号。
一种睡眠是不可中断睡眠,其标志位是TASK_UNINTERRUPTIBLE ,把信号传递到这种睡眠状态的进程不能改变它的状态,也就是除非等待的资源得到满足,否则就是怎么kill,这个进程也不会变成TASK_RUNNING和进入就绪队列的。怎么都杀不死的。
TASK_UNINTERRUPTIBLE的意义
TASK_UNINTERRUPTIBLE存在的意义就在于,内核的某些处理流程是不能被打断的。如果响应异步信号,程序的执行流程中就会被插入一段用于处理异步信号的流程(这个插入的流程可能只存在于内核态,也可能延伸到用户态),于是原有的流程就被中断了。在对某些硬件进行操作时(比如进程调用read系统调用对某个设备文件进行读操作,而read系统调用最终执行到对应设备驱动的代码,并与对应的物理设备进行交互),可能需要TASK_UNINTERRUPTIBLE状态对进程进行保护,以避免进程与设备交互的过程被打断,造成设备陷入不可控的状态。
通常情况下TASK_UNINTERRUPTIBLE状态是非常短暂的,通过ps命令基本上不可能捕捉到。进程又是为什么会被置于 uninterruptible sleep 状态呢?处于 uninterruptible sleep 状态的进程通常是在等待 IO,比如磁盘 IO,网络 IO,其他外设 IO,如果进程正在等待的 IO 在较长的时间内都没有响应,很有可能有 IO 出了问题,可能是外设本身出了故障,也可能是比如挂载的远程文件系统NFS等已经不可访问了,那么就很会不幸地被 ps 看到进程状态位已经变成D。
正是因为得不到 IO 的相应,进程才进入了 uninterruptible sleep 状态,所以要想使进程从 uninterruptible sleep 状态恢复,就得使进程等待的 IO 恢复,比如如果是因为从远程挂载的 NFS 卷不可访问导致进程进入 D状态的,那么可以通过恢复该 NFS 卷的连接来使进程的 IO 请求得到满足,除此之外,要想干掉处在 D 状态进程就只能重启整个 Linux 系统了。如果为了想要杀掉 D 状态的进程,而去杀掉它的父进程(通常是shell,在shell下允许某进程,然后某进程转入D状态),就会出现这样的状态:他们的父进程被杀掉了,但是他们的父进程 PID 都变成了1,也就是 init 进程,D状态的进程会变成僵尸进程。
alarm 和 sleep的更多相关文章
- rtc关机闹钟2 Alarm manager
public void set(int type, long triggerAtMillis, long windowMillis, long intervalMillis, PendingInten ...
- setup notifier actions in aodh alarm
Aodh alarm NOTIFIER ==> alarm_actions URL: http://<host>/<action> NOTIFIER will resol ...
- Best Practices for Background Jobs_3 Managing Device Awake State之电源锁、Alarm、WakefulBroadcastReceiver
http://developer.android.com/training/scheduling/index.html 当静置一个设备的时候,先会屏幕变暗,然后关闭屏幕,最后关闭CPU,以省电.但有的 ...
- Linux 信号详解四(pause,alarm)
pause函数 --将进程置为可中断睡眠状态,然后它调用内核函数schedule(),使linux进程调度器找到另一个进程来运行. --pause使调用者进程挂起,知道一个信号被捕获. alarm函数 ...
- alarm
AlarmManager的使用机制有的称呼为全局定时器,有的称呼为闹钟.通过对它的使用,它的作用和Timer有点相似.都有两种相似的用法:(1)在指定时长后执行某项操作 (2)周期性的执行某项操作 在 ...
- 例子:Alarm Clock with voice Commands Sample
通过本例子学习: 如何使用自定义字体文件(.TTF) 如何播放声音 动画的使用 Speech 设置闹铃 应用 设置 数据存储到IsolatedStorage 如何使用自定义字体文件(.TTF) < ...
- alarm rtc
http://sharp2wing.iteye.com/blog/1329518 http://blog.csdn.net/sking002007/article/details/6593809 io ...
- linux alarm函数解除read write等函数的阻塞
看到apue的第十章,说到alarm,pause可以实现sleep,可以让某些一直阻塞的函数超时,例如read,write.代码如下: static void sig_alrm(int signo) ...
- Alarm(硬件时钟) init
http://blog.csdn.net/angle_birds/article/details/17302297 Alarm就是一个硬件时钟,前面我们已经知道它提供了一个定时器,用于把设备从睡眠状态 ...
- 第十一章 Android 内核驱动——Alarm
11.1 基本原理 Alarm 闹钟是 android 系统中在标准 RTC 驱动上开发的一个新的驱动,提供了一个定时器 用于把设备从睡眠状态唤醒,当然因为它是依赖 RTC 驱动的,所以它同时还可以 ...
随机推荐
- 【轮廓线DP】POJ2411-Mondriaan's Dream
今天美国的院士过来讲课XD以为会很无聊但是谜之好听,而且英语基本上都听懂了的样子♪(´▽`) 逃到图书馆来写解题报告 [题目大意] 给出一个m*n的方格,用2*1的骨牌覆盖有几种情况. [思路] 最基 ...
- CROC 2016 - Elimination Round (Rated Unofficial Edition) D. Robot Rapping Results Report 二分+拓扑排序
D. Robot Rapping Results Report 题目连接: http://www.codeforces.com/contest/655/problem/D Description Wh ...
- ruby 状态转移
0. 引言 昨天遇到一个问题,就是关于对象状态转移的问题,我姑且这样命名吧.简要描述一下就是:对于一个人,他有进食,帮助他人,恋爱等功能,但是这些功能是有先后顺序的,对于刚出生的人,他要先 ...
- 王者参考jar包
- wpf简单的绘图板
xaml: <Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft ...
- Ubuntu下gcc多版本共存和版本切换
https://my.oschina.net/u/2306127/blog/538139 摘要: Ubuntu系统使用的gcc版本随着发布版本的不同而不同,在编译android系统时不同的版本推荐用不 ...
- Appium+python自动化17-启动iOS模拟器APP源码案例
前言 上一篇已经可以启动iOS模拟器上的safari浏览器了,启动app比启动浏览器要复杂一点,本篇以github上的源码为案例详细介绍如何启动iOS模拟器的app 一.clone源码 1.githu ...
- 实验3 OpenGL几何变换
转自:http://www.cnblogs.com/opengl/archive/2012/10/30/2747130.html 1.实验目的: 理解掌握一个OpenGL程序平移.旋转.缩放变换的方法 ...
- 在Android 5.0中使用JobScheduler
在Android 5.0中使用JobScheduler 原文链接 : using-the-jobscheduler-api-on-android-lollipop 译者 : Mr.Simple 校对者 ...
- Latex作者单位的写法—AND 首页脚注
IEEE会议的模板 以四个作者为例 正常: 作者单位如果名字较短,可以直接写在作者对应的下面,邮箱可以对应写在再接下来的下面. 一 如果邮箱较长,可以用\thanks{ }命令将其变为脚注.例如: ~ ...