APUE第十章学习笔记
2017-09-25 22:14
309 查看
1.信号
vi 10.1.c
vi 10.2.c
2.可重入函数
vi 10.3.c
函数 kill 和 raise
vi 10.4.c
vi 10.5.c
vi 10.5.1.c
3.信号集
vi 10.6.c
vi 10.7.c
4.sigaction函数
vi 10.8.c
vi 10.9.c
4.sigsetjmp 和 siglongjmp函数
5.sigsuspend函数
6.函数system
vi 10.12.c
7.nanosleep
vi 10.13.c
vi 10.14.c
8.sigqueue函数
vi 10.15.c
/***************************************** 信号处理方式: (1):忽略此信号。(SIGKILL 和 SIGSTOP信号不能被忽略) (2):捕捉信号 (3):执行系统默认动作 *****************************************/ /***************************************** 包含头文件 #include <signal.h> 函数原型: void (*signal(int signo,void(*func)(int)))(int); 函数说明:signo是信号名,func的值是常量 SIG_IGN(忽略) SIG_DEL(系统默认动作) 或 当接到此信号后要调用的函数地址 返回值:若成功,返回以前的信号处理配置,若出错,返回SIG_ERR *****************************************/ /**************************************** exec函数将原先设置为要捕捉的信号都更改为默认动作,其他信号的状态则不变(一个进程原先要捕捉的信号,当其执行一个新程序后,就不能再不捕捉了) 子进程会继承父进程信号处理方式 *****************************************/
vi 10.1.c
#include <stdio.h> #include <stdlib.h> #include <signal.h> #include <unistd.h> static void sig_usr(int); int main() { if (signal(SIGUSR1,sig_usr) == SIG_ERR) { printf("signal error\n"); exit(0); } if (signal(SIGUSR2,sig_usr) == SIG_ERR) { printf("signal error\n"); exit(0); } for (; ;) pause(); return 0; } static void sig_usr(int signo) { if (signo == SIGUSR1) printf("received SIGUSR1\n"); else if (signo == SIGUSR2) printf("received SIGUSR2\n"); else { printf("received signal %d\n",signo); exit(0); } }
vi 10.2.c
include <stdio.h> #include <stdlib.h> #include <signal.h> #include <unistd.h> static void sig_usr(int); int main() { if (signal(SIGUSR1,sig_usr) == SIG_ERR) { printf("1: signal error\n"); exit(0); } if (signal(SIGUSR2,sig_usr) == SIG_ERR) { printf("2: signal error\n"); exit(0); } pid_t pid; if ((pid = fork()) < 0) { printf("fork error\n"); exit(0); } else if (pid == 0) { printf("子进程 ID: %d\n",getpid()); for (; ;) pause(); } else { printf("父进程 ID: %d\n",getpid()); for (; ;) pause(); } return 0; } static void sig_usr(int signo) { if (signo == SIGUSR1) printf("reveived SIGUSR1\n"); else if (signo == SIGUSR2) printf("received SIGUSR2\n"); else { printf("received signo %d\n",signo); exit(0);
2.可重入函数
/***************************************** 可重入函数: 在信号处理程序中保证调用安全的函数,这些函数是可重入的并称为异步信号安全的 不可重入函数一般有以下性质: (1):已知它们使用静态数据结构 (2):它们调用malloc和free (3):它们是标准I / O函数 *****************************************/ /***************************************** 当一个信号产生时,内核在进程表以某种形式设置一个标志,此时为向进程递送一个信号,在信号产生和递送之间的时间间隔内,称信号是未决的 如果进程产生了一个阻塞的信号,而且对该信号的动作是系统默认动作或捕捉该信号,则为该进程将此信号保持为未决状态,直到该进程对此信号解除了阻塞,或者将对此信号动作改成忽略 *****************************************/
vi 10.3.c
#include <stdio.h> #include <stdlib.h> #include <signal.h> #include <pwd.h> #include <string.h> #include <unistd.h> static void my_alarm(int signo) { struct passwd* rootptr; printf("in signal handler\n"); if ((rootptr = getpwnam("root")) == NULL) { printf("getpwname(root) error\n"); exit(0); } alarm(1); } int main() { struct passwd* ptr; signal(SIGALRM,my_alarm); alarm(1); for (; ;) { if ((ptr = getpwnam("marco")) == NULL) { printf("getpwnam error\n"); exit(0); } if (strcmp(ptr->pw_name,"marco") != 0) { printf("return value corrupted!,pw_name = %s\n",ptr->pw_name); } } return 0; }
函数 kill 和 raise
/******************************************************** 包含头文件: #include <signal.h> 函数原型: int kill(pid_t pid,int signo); int raise(int signo); 函数说明: kill将信号发送给进程或进程组 raise函数则允许进程自身发送信号 kill: (1):若pid > 0,则发送signo至进程pid (2): 若pid == 0,则发送至同一进程组的所有进程(不包括实现的系统进程集) (3): 若 pid < 0,将该信号发送给进程组等于pid绝对值的所有进程(不包括实现的系统进程集) (4): 若pid == -1,将该信号发送给发送进程有权限发送的所有进程(不包括实现的系统进程集) raise: 允许进程向自身发送信号 返回值:若成功,返回0,若出错,返回-1 ***********************************************************/
vi 10.4.c
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> static void sig_usr(int signo) { if (signo == SIGUSR1) printf("进程 %d 收到信号 SIGUSR1\n",getpid()); else if (signo == SIGUSR2) printf("进程 %d 收到信号 SIGUSR2\n",getpid()); else printf("进程 %d 收到信号 %d\n",getpid(),signo); } int main() { if (signal(SIGUSR1,sig_usr) == SIG_ERR) { printf("1: signal error\n"); exit(0); } if (signal(SIGUSR2,sig_usr) == SIG_ERR) { printf("2: signal error\n"); exit(0); } pid_t pid; if ((pid = fork()) < 0) { printf("fork error\n"); exit(0); } else if (pid == 0) { printf("子进程组ID: %d\n",getpgrp()); pid_t pid2; if ((pid2 = fork()) < 0) { printf("child fork error\n"); exit(0); } else if (pid2 == 0) { printf("子进程子进程组ID: %d\n",getpgrp()); pause(); pause(); exit(0); } sleep(4); pause(); pause(); exit(0); } sleep(6); printf("父进程进程组ID: %d\n",getpgrp()); kill(0,SIGUSR1); kill(0,SIGUSR2); return 0; }
/******************************************************* 包含头文件: #include <unistd.h> 函数原型: unsigned int alarm(usigned int seconds); 函数说明: 参数seconds的值是产生信号SIGALRM需要经过时钟秒数 每个进程只能有一个闹钟时间.如果在调用alarm时,之前已为该进程注册的闹钟时间还没有超时,则将该闹钟时间的余留值作为本次alarm函数调用的值返回,以前 注册的闹钟被新值代替 返回值: 0 或 以前设置的闹钟时间的余留秒数 ********************************************************/ /******************************************************* 包含头文件: #include <unistd.h> 函数原型: int pause(void); 函数说明:使调用进程挂起直至捕捉到一个信号 返回值: -1,errno设置为 EINTR ********************************************************/
vi 10.5.c
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> static void sig_alarm(int signo) { } unsigned int sleep1(unsigned int seconds) { if (signal(SIGALRM,sig_alarm) == SIG_ERR) return seconds; alarm(seconds); pause(); return alarm(0); } int main() { sleep1(5); return 0; }
vi 10.5.1.c
#include <stdio.h> #include <stdlib.h> #include <setjmp.h> #include <signal.h> #include <unistd.h> static jmp_buf env_alrm; static void sig_alarm() { longjmp(env_alrm,1); } unsigned int sleep2(unsigned int seconds) { if (signal(SIGALRM,sig_alarm) == SIG_ERR) return seconds; if (setjmp(env_alrm) == 0) { alarm(seconds); pause(); } return (alarm(0)); } int main() { sleep2(5); return 0; }
3.信号集
/******************************************************* 包含头文件: #include <signal.h> 函数原型: int sigemptyset(sigset_t *set); int sigfillset(sigset_t *set); int sigaddset(sigset_t *set,int signo); int sigdelset(sigset_t *set,int signo); int sigismember(const sigset_t *set,int signo); 函数说明: sigemptyset 清除所有信号 sigfillset 初始化所有信号 sigaddset 增加特定信号 sigdelset 删除特定信号 sigismember 判断特定信号是否存在于信号集 返回值: sigemptyset sigfillset sigaddset sigdelset 若成功,返回0,若出错,返回-1 sigismember 返回值: 若真,返回 1,若假,返回0 *******************************************************/ /********************************************************** 包含头文件: #include <signal.h> 函数原型: int sigprocmask(int how,const sigset_t* restrict set,sigset_t *restrict oset); 函数说明:若set为空,则进程信号屏蔽字则通过oset返回 若set非空,则通过how来指示如何修改当前信号屏蔽字 how: SIG_BLOCK 取set 和 oset并集作为当前信号屏蔽字 SIG_UNBLOCK 取set 和 oset并集并解除set作为当前信号屏蔽字 SIG_SETMASK 将set值作为当前信号屏蔽字 注:在调用sigprocmask后如果有任何未决的,不再阻塞的信号,则在sigprocmask返回前,至少将其中之一递送给该进程 ***************************************************/
vi 10.6.c
#include <stdio.h> #include <stdlib.h> #include <signal.h> #include <unistd.h> void sig_usr(int signo) { if (signo == SIGUSR1) printf("收到信号 SIGUSR1\n"); else if (signo == SIGUSR2) printf("收到信号 SIGUSR2\n"); else printf("收到信号 %d\n",signo); } int main() { if (signal(SIGUSR1,sig_usr) == SIG_ERR) { printf("signal error\n"); exit(0); } if (signal(SIGUSR2,sig_usr) == SIG_ERR) { printf("signal error\n"); exit(0); } sigset_t oldmask,newmask; if (sigemptyset(&oldmask) < 0 || sigemptyset(&newmask)) { printf("sigemptyset error\n"); exit(0); } sigaddset(&oldmask,SIGUSR1); printf("屏蔽信号 SIGUSR1\n"); sigprocmask(SIG_SETMASK,&oldmask,NULL); kill(getpid(),SIGUSR1); kill(getpid(),SIGUSR2); sleep(3); printf("\n"); printf("屏蔽信号 SIGUSR2\n"); sigaddset(&newmask,SIGUSR2); sigprocmask(SIG_SETMASK,&newmask,NULL); kill(getpid(),SIGUSR1); kill(getpid(),SIGUSR2); sleep(3); printf("\n"); printf("屏蔽信号 SIGUSR1 和 SIGUSR2\n"); sigprocmask(SIG_BLOCK,&newmask,&oldmask); kill(getpid(),SIGUSR1); kill(getpid(),SIGUSR2); return 0; }
/***************************************** 包含头文件: #include <signal.h> 函数原型: int sigpending(sigset_t *set); 函数说明: 返回信号集,对于调用进程而言,其中的信号是阻塞不能递送的,因而也一定是当前未决的. 返回值: 若成功,返回0,若出错,返回-1 *****************************************/
vi 10.7.c
#include <stdio.h> #include <stdlib.h> #include <signal.h> #include <unistd.h> void sig_usr(int signo) { if (signo == SIGUSR1) printf("收到信号 SIGUSR1\n"); else if (signo == SIGUSR2) printf("收到信号 SIGUSR2\n"); else printf("收到信号 %d\n",signo); } int main() { if (signal(SIGUSR1,sig_usr) == SIG_ERR) { printf("signal error\n"); exit(0); } if (signal(SIGUSR2,sig_usr) == SIG_ERR) { printf("signal error\n"); exit(0); } sigset_t mask,oldmask; sigemptyset(&mask); sigaddset(&mask,SIGUSR1); //得到row 信号集 sigprocmask(SIG_BLOCK,NULL,&oldmask); //屏蔽信号 SIGUSR1 sigprocmask(SIG_SETMASK,&mask,NULL); //发送信号 SIGUSR1 kill(getpid(),SIGUSR1); // 信号SIGUSR1 阻塞未决 sigset_t getmask; sigemptyset(&getmask); sigpending(&getmask); if (sigismember(&getmask,SIGUSR1)) printf("SIGUSR1 is mask\n"); // 解除屏蔽信号 SIGUSR1 sigprocmask(SIG_SETMASK,&oldmask,NULL); return 0; }
4.sigaction函数
/***************************************** 包含头文件: #include <signal.h> 函数原型: int sigaction(int signo,const struct sigaction *restrict act,struct sigaction * restrict oact); 函数说明:参数signo是要检测或修改其具体动作的信号编号,若act非空,则修改其动作,如果oact非空,则系统由oact返回该信号的上一个动作 返回值:若成功,返回0,若失败,返回-1 strcut sigaction { void (*sa_handler)(int) ; //信号处理函数的地址 sigset_t sa_mask; //增加需要阻塞的信号 int sa_flags; //可选标志 void (*sa_sigaction)(int,siginfo_t *,void *); //可替代信号处理程序 } struct siginfo { int si_signo; //信号编号 int si_errno; //错误标志 int si_code; //可添加的代码 pid_t si_pid; //传送进程ID uid_t si_uid; //传送进程实际用户ID void *si_addr; //造成错误的地址 int si_status; //退出值或信号值 union sigval si_value; //应用程序特殊值 /* ………….. */ }; union sigval { int sival_int; void* sival_ptr; }; *****************************************/
vi 10.8.c
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> void sig_usr(int signo) { if (signo == SIGUSR1) printf("收到信号 SIGUSR1\n"); else if (signo == SIGUSR2) printf("收到信号 SIGUSR2\n"); else printf("收到信号 %d\n",signo); } int main() { struct sigaction act; act.sa_handler = sig_usr; if (sigaction(SIGUSR1,&act,NULL) < 0) { printf("sigaction error\n"); exit(0); } if (sigaction(SIGUSR2,&act,NULL) < 0) { printf("sigaction error\n"); exit(0); } kill(getpid(),SIGUSR1); kill(getpid(),SIGUSR2); return 0; }
vi 10.9.c
#include <stdio.h> #include <stdlib.h> #include <signal.h> #include <unistd.h> typedef void Sigfunc(int); Sigfunc * signal2(int signo,Sigfunc *func) { struct sigaction act,oact; act.sa_handler = func; sigemptyset(&act.sa_mask); act.sa_flags = 0; if (signo == SIGALRM) { #ifdef SA_INTERRUPT act.sa_flags |= SA_INTERRUPT; #endif } else { act.sa_flags |= SA_RESTART; } if (sigaction(signo,&act,&oact) < 0) return (SIG_ERR); return (oact.sa_handler); } void sig_usr(int signo) { if (signo == SIGUSR1) printf("接收到信号 SIGUSR1\n"); else printf("接收到信号 %d\n",signo); } int main() { if (signal2(SIGUSR1,sig_usr) == SIG_ERR) { printf("signal2 error\n"); exit(0); } kill(getpid(),SIGUSR1); return 0; }
4.sigsetjmp 和 siglongjmp函数
/********************************************************** 包含头文件: #include <setjmp.h> 函数原型: int sigsetjmp(sigjmp_buf env,int savemask); 函数说明: 进行非局部转移并恢复所保存信号屏蔽字 返回值:若直接调用,返回0;若从siglongjmp调用返回,则返回非0 void siglongjmp(sigjmp_buf env,int val); *********************************************************/
5.sigsuspend函数
#include <stdio.h> #include <stdlib.h> #include <signal.h> #include <unistd.h> void sig_usr1(int signo) { printf("接收到信号 SIGUSR1\n"); } void sig_usr2(int signo) { printf("接收到信号 SIGUSR2\n"); } int main() { if (signal(SIGUSR1,sig_usr1) == SIG_ERR) { printf("signal SIGUSR1 error\n"); exit(0); } if (signal(SIGUSR2,sig_usr2) == SIG_ERR) { printf("signal SIGUSR2 error\n"); exit(0); } sigset_t mask1,mask2; sigemptyset(&mask1); sigemptyset(&mask2); sigaddset(&mask1,SIGUSR1); sigaddset(&mask2,SIGUSR2); sigprocmask(SIG_SETMASK,&mask1,NULL); if (sigsuspend(&mask2) != -1) { printf("sigsuspend error\n"); exit(0); } kill(getpid(),SIGUSR1); kill(getpid(),SIGUSR2); return 0; }
6.函数system
vi 10.12.c
#include <stdio.h> #include <stdlib.h> #include <signal.h> #include <unistd.h> #include <errno.h> #include <sys/wait.h> int system1(const char* cmdstring) { if (cmdstring == NULL) return 1; struct sigaction ignore,saveintr,savequit; sigset_t chldmask,savemask; ignore.sa_handler = SIG_IGN; sigemptyset(&ignore.sa_mask); ignore.sa_flags = 0; if (sigaction(SIGINT,&ignore,&saveintr) < 0) { return -1; } if (sigaction(SIGQUIT,&ignore,&savequit) < 0) { return -1; } sigemptyset(&chldmask); sigaddset(&chldmask,SIGCHLD); if (sigprocmask(SIG_BLOCK,&chldmask,&savemask) < 0) return -1; pid_t pid; int status; if ((pid = fork()) < 0) status = -1; else if (pid == 0) { sigaction(SIGINT,&saveintr,NULL); sigaction(SIGQUIT,&saveintr,NULL); sigprocmask(SIG_SETMASK,&savemask,NULL); execl("/bin/sh","sh","-c",cmdstring,(char*)0); _exit(127); } else { while (waitpid(pid,&status,0) < 0) if (errno == EINTR) { status = -1; break; } } if (sigaction(SIGINT,&saveintr,NULL) < 0) return -1; if (sigaction(SIGQUIT,&savequit,NULL) < 0) return -1; if (sigprocmask(SIG_SETMASK,&savemask,NULL) < 0) return -1; return status; } int main() { system1("date"); return 0; }
7.nanosleep
/********************************************************** 包含头文件: #include <time.h> 函数原型: int nanosleep(const struct timespec *reqtp,struct timespec *remtp); 函数说明:挂起调用进程,直到要求时间超时或某个信号中断了该函数,reqtp指向休眠长度,remtp未休眠完时间长度 返回值:若休眠到要求的时间,返回0,若出错,返回-1 **********************************************************/ /*********************************************************** 包含头文件: #include <time.h> 函数原型: int clock_nanosleep(clockid_t clock_id, int flags,const struct timespec* reqtp,struct timespec* remtp); 函数说明: flags为0表示休眠时间是相对的,表示休眠reqtp时间,flags为 TIMER_ABSTIME,表示休眠时间是绝对的,表示休眠到reqtp **********************************************************/
vi 10.13.c
#include <time.h> #include <stdio.h> #include <stdlib.h> #include <signal.h> struct timespec* rest = NULL; void sig_usr(int signo) { if (rest != NULL) { printf("剩于未休眠时间 秒数: %ld 纳秒数: %ld\n",rest->tv_sec,rest->tv_nsec); } } int main() { if (signal(SIGUSR1,sig_usr) == SIG_ERR) { printf("signal SIGUSR1 error\n"); exit(0); } if (signal(SIGUSR2,sig_usr) == SIG_ERR) { printf("signal SIOGUSR2 error\n"); exit(0); } struct timespec set; set.tv_sec = 20; set.tv_nsec = 0; rest = (struct timespec*)(malloc(sizeof(struct timespec))); nanosleep(&set,rest); return 0; }
vi 10.14.c
#include <stdio.h> #include <stdlib.h> #include <signal.h> #include <time.h> struct timespec* rest = NULL; void sig_usr(int signo) { if (rest != NULL) { printf("休眠剩余时间: 秒数: %ld 纳秒数: %ld\n",rest->tv_sec,rest->tv_nsec); } } int main() { if (signal(SIGUSR1,sig_usr) == SIG_ERR) { printf("signal SIGUSR1 error\n"); exit(0); } if (signal(SIGUSR2,sig_usr) == SIG_ERR) { printf("signal SIGUSR2 error\n"); exit(0); } struct timespec set; clock_gettime(CLOCK_REALTIME,&set); set.tv_sec += 40; rest = (struct timespec *)malloc(sizeof(struct timespec)); clock_nanosleep(CLOCK_REALTIME,TIMER_ABSTIME,&set,rest); return 0; }
8.sigqueue函数
/*********************************************************** 包含头文件: #include <signal.h> 函数原型: int sigqueue(pid_t pid,int signo,const union sigval value); 函数说明:将信号发给单个进程,并附带value所传递值 ***********************************************************/
vi 10.15.c
#include <stdio.h> #include <stdlib.h> #include <signal.h> #include <unistd.h> void usr1_handler(int signo,siginfo_t *siginfo,void* context) { printf("接收到信号 SIGUSR1\n"); printf("接收到附加信息是 %s\n",(char*)(siginfo->si_value.sival_ptr)); } int main() { struct sigaction usr1act; usr1act.sa_sigaction = usr1_handler; usr1act.sa_flags = SA_SIGINFO; sigemptyset(&usr1act.sa_mask); if (sigaction(SIGUSR1,&usr1act,NULL) < 0) { printf("sigaction SIGUSR1 error\n"); exit(0); } union sigval value; value.sival_ptr = "SIGUSR1 的附加信息\n"; if (sigqueue(getpid(),SIGUSR1,value) < 0) { printf("sigqueue error\n"); exit(0); } return 0; }
相关文章推荐
- Objective-C学习笔记第十章对象初始化
- 《APUE》chapter 18 Terminal I/O 学习笔记(加上自己的代码)
- APUE第十四章.第十五章学习笔记
- 关联容器 - 1【C++ Primer 学习笔记 - 第十章】
- 【学习笔记】第十章 内部类
- [学习笔记—Objective-C]《Objective-C-基础教程 第2版》第十章 对象初始化
- 《APUE》chapter 13 Deamon Process 学习笔记(加上自己的代码)
- C++primer第五版第十章学习笔记
- 第十章(3)-异步调用中的异常与任务同步-学习笔记
- Unix环境编程学习笔记-------通读APUE第一遍后的疑问???????
- LINUX基础第十章笔记_VIM学习
- 《COM原理及应用》学习笔记之第十章
- apue-第十章 信号 笔记
- Java学习笔记―第十章 数据输入与输出
- C++学习笔记【第二部分第十章:泛型算法】
- 鸟哥Linux私房菜_基础篇(第二版)_第十章学习笔记
- c++ primer 学习笔记-第十章
- 【C++ Primer】【学习笔记】【第十章】关联容器之:multimap和multiset类型
- android:第十章,后台的默默劳动者——服务,学习笔记
- APUE学习笔记之文件和目录(中)(6)