1.信号
- /*****************************************
- 信号处理方式:
- (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,SIGUSR2);
- sleep(3);
- printf("\n");
-
- printf("屏蔽信号 SIGUSR1 和 SIGUSR2\n");
-
- sigprocmask(SIG_BLOCK,&oldmask);
- kill(getpid(),SIGUSR2);
-
- return 0;
- }
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",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,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,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,&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函数
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,&mask1,NULL);
-
- if (sigsuspend(&mask2) != -1)
- {
- printf("sigsuspend error\n");
- exit(0);
- }
-
- 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,&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,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,NULL) < 0)
- return -1;
- if (sigaction(SIGQUIT,&savequit,NULL) < 0)
- return -1;
- if (sigprocmask(SIG_SETMASK,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未休眠完时间长度
- 返回值:若休眠到要求的时间,返回-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",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函数
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;
- }