Sleep
#include ?// 返回:seconds left to sleepunsigned int sleep(unsigned int secs);?// 让调用函数休眠 , 直到收到一个信号// 返回:-1int pause(void);Loading and Running Programs
execve函数在当前进程的上下文中加载并运行一个新的程序 , 覆盖当前进程的地址空间 , 但并没有创建一个新进程 , 进程PID没有改变 。
#include // 返回:成功=不返回;出错=-1int execve(const char *filename, const char *argv[], const char *envp[]);// 程序主入口:int main(int argc, char **argv, char **envp);int main(int argc, char *argv[], char *envp[]);Signal
文章插图
[ Linux Signal(`man 7 signal`) ]
信号传递到目的进程包括两个步骤:1)发送;2)接收 。
- 一个发出却没被接收的信号叫做待处理信号(Pending Signal) 。
- 一个进程有一个类型为k的待处理信号 , 后面发送到这个进程的k信号都会被丢弃 。
- 也可以选择性阻塞接收某个信号 , 信号被阻塞时仍可以发送 , 但产生的待处理信号不会被接收 , 直到进程取消对这种信号的阻塞 。
- 一个待处理信号最多只能被接收一次 , 内核为每个进程在pending位向量中维护待处理信号集合 , 而在blocked位向量中维护被阻塞的信号集合 。
- 只有接收了k信号 , 内核才会清除pending中的k位 。
Sending Signal
- 每个进程都只属于一个进程组 , 进程组ID标识 。 unix所有发送信号的机制都是基于进程组(process group)/
#include ?// 返回:调用进程的进程组IDpid_t getpgrp(void);// 返回:成功=1 , 错误=-1int setpgid(pid_t pid, pid_t pgid);- 用/bin/kill程序发送信号
- 发送信号9到进程15213
- /bin/kill -9 15213
- 发送信号9到进程组15213中的每个进程 。
- /bin/kill -9 -15213
- 从键盘发送信号
- unix使用作业(job)表示对每一个命令行执行而创建的进程 , 至多一个前台作业和0个或多个后台作业 。 通过|unix管道连接起多个进程 。
- shell位每个作业创建一个独立的进程组 。 进程组ID是取自job中父进程中的一个 。
- Ctrl + C发送SIGINT信号到前台进程组中的每一个进程 , 终止前台作业 。
文章插图
[ 前台进程子进程和父进程具有相同的进程组ID 。 ]
#include // 输入参数pid:// pid>0:发送SIGKILL给进程pid// pid<0:发送SIGKILL给进程组abs(pid)// 返回:成功=0 , 失败=-1int kill(pid_t pid, int sig);#include // 发送SIGALRM给调用进程 , 如果secs位0 , 则不会调度alarm 。 任何情况 , 对alarm调用都将取消任何pending alarm , 并返回pending alarm在被发送前还剩下的秒数 。 // 返回:前一次alarm剩余的秒数 , 0=以前没有设定alarmunsigned int alarm(unsigned int secs);??/* 定时1s触发alarm handler , 5s结束 */#include #include #include ??void handler(int sig) { static int beeps = 0; printf("BEEP\n"); if (++beeps < 5) { alarm(1); } else { printf("BOOM!\n"); exit(0); }}??int main() { signal(SIGALRM, handler); alarm(1); for(;;); exit(0);}Receiving Signals
wtf:当异常处理程序返回时 , 准备转移控制权给进程p时 , 会检查非被阻塞的待处理信号的集合(pending// 输入函数sighandler_t:// handler=SIG_IGN , 忽略类型为signum的信号;// handler=SIG_DFL , 重置类型为signum信号的行为 。 //// 返回:成功=指向前次处理程序指针 , 出错=SIG_ERR(不设置errno)sighandler_t signal(int signum, sighandler_t handler); // installing the handler????/* ctrl-c中断sleep , 并打印睡眠时间 */#include #include #include #include ??void handler(int sig) {} // 改变SIGINT处理函数??int snooze(unsigned int sec) { int left_sleep_sec = sleep(sec); printf("Slept for %d of %d secs.\tUser hits ctrl-c after %d seconds\n", left_sleep_sec, sec, sec-left_sleep_sec);}??int main(int argc, char *argv[]) { if (SIG_ERR == signal(SIGINT, handler)) { exit(-1); }?? unsigned int sleep_sec = 0; if (argc > 1) { sleep_sec = atoi(argv[1]); } else { exit(0); } printf("sleep for %d seconds\n", sleep_sec); snooze(sleep_sec); exit(0);}