信号完结
This commit is contained in:
@@ -15,6 +15,9 @@
|
||||
> 信号是软件中断。
|
||||
信号的响应依赖于中断。
|
||||
|
||||
信号的处理函数应该尽量短小,注意是否可重入问题。
|
||||
使用系统调用,不能轻易使用IO。
|
||||
|
||||
```bash
|
||||
kill -l # 查看信号列表
|
||||
```
|
||||
@@ -31,8 +34,8 @@ typedef void (*sighandler_t)(int);
|
||||
|
||||
/**
|
||||
* signal - 设置信号处理函数
|
||||
* @signum: 信号编号
|
||||
* @handler: 信号处理函数
|
||||
* @param: signum 信号编号
|
||||
* @param: handler 信号处理函数
|
||||
*
|
||||
* 返回值:原信号处理函数
|
||||
*/
|
||||
@@ -91,6 +94,10 @@ M P
|
||||
有则重复,无则将M置1,回到常规状态。
|
||||
1 0
|
||||
|
||||
不能从信号处理函数中随意的往外跳。(setjmp, longjmp)
|
||||
这样错过了将M置1的机会。
|
||||
标准:sigsetjmp, siglongjmp, 推出这俩来保存掩码情况。
|
||||
|
||||
### 常用函数
|
||||
|
||||
```c
|
||||
@@ -119,7 +126,7 @@ int kill(pid_t pid, int sig);
|
||||
|
||||
/**
|
||||
* raise - 发送信号给当前进程
|
||||
* @sig: 信号编号
|
||||
* @param: sig 信号编号
|
||||
*
|
||||
* 返回值:成功返回0,失败返回非零
|
||||
*/
|
||||
@@ -168,22 +175,88 @@ void abort(void);
|
||||
*/
|
||||
int system(const char *command);
|
||||
|
||||
sleep();
|
||||
|
||||
/**
|
||||
* sleep - 休眠进程
|
||||
* @param: seconds: 休眠时间,单位为秒
|
||||
*
|
||||
* @note: 休眠当前进程,直到指定的时间段结束
|
||||
*
|
||||
* @return: 剩余时间,单位为秒
|
||||
*/
|
||||
unsigned int sleep(unsigned int seconds);
|
||||
// 可以封装出sleep函数
|
||||
int nanosleep(const struct timespec *req, struct timespec *rem);
|
||||
int usleep(useconds_t usec);
|
||||
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
|
||||
```
|
||||
|
||||
### 信号集
|
||||
|
||||
```c
|
||||
struct sigset_t; // 信号集类型
|
||||
int sigemptyset(sigset_t *set);
|
||||
int sigfillset(sigset_t *set);
|
||||
int sigaddset(sigset_t *set, int signum);
|
||||
int sigdelset(sigset_t *set, int signum);
|
||||
int sigismember(const sigset_t *set, int signum);
|
||||
```
|
||||
|
||||
### 信号屏蔽字/`pending`的处理
|
||||
|
||||
```c
|
||||
/**
|
||||
* sigprocmask - 设置信号掩码
|
||||
* @param: how: 掩码操作类型
|
||||
* @param: set: 信号集指针
|
||||
* @param: oldset: 旧的信号集指针
|
||||
*/
|
||||
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
|
||||
|
||||
/**
|
||||
* sigpending - 获取未决信号集
|
||||
* @param: set: 信号集指针
|
||||
* @note: 该函数获取当前进程的未决信号集
|
||||
* 该函数会清空pending信号集,并将其复制到set指向的信号集中。
|
||||
* 该函数不修改信号掩码。
|
||||
*
|
||||
* !!!: 没有使用场景,不推荐使用
|
||||
* 取到的信号是响应之前的信号,等取到的时候,情况可能已经变化。
|
||||
*/
|
||||
int sigpending(sigset_t *set);
|
||||
```
|
||||
|
||||
### 扩展
|
||||
|
||||
```c
|
||||
sigsuspend();
|
||||
sigaction();
|
||||
/**
|
||||
* sigwait - 等待信号
|
||||
*/
|
||||
int sigsuspend(const sigset_t *mask);
|
||||
|
||||
/**
|
||||
* setitimer - 设置定时器
|
||||
* sigaction - 设置信号处理函数,替代signal
|
||||
* @param: signum: 信号编号
|
||||
* @param: act: 信号处理函数
|
||||
* @param: oldact: 旧的信号处理函数
|
||||
*
|
||||
* @note: signal无法区分信号来自user还是kernel
|
||||
* sigaction可以区分
|
||||
* 看siginfo_t.si_code可以区分
|
||||
*/
|
||||
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
|
||||
|
||||
struct sigaction {
|
||||
//!在某些结构, sa_handler和sa_sigaction只能有一个被设置
|
||||
//!因为他们是共用体
|
||||
void (*sa_handler)(int); /* 信号处理函数 */
|
||||
void (*sa_sigaction)(int, siginfo_t *, void *); /* 信号处理函数 */
|
||||
sigset_t sa_mask; /* 信号掩码 */
|
||||
int sa_flags; /* 信号标志 */
|
||||
void (*sa_restorer)(void); /* 信号状态恢复函数 */
|
||||
};
|
||||
|
||||
/**
|
||||
* setitimer - 设置定时器,替代alarm
|
||||
* @param: which: 定时器类型
|
||||
* ITIMER_REAL : 实时定时器
|
||||
* ITIMER_VIRTUAL : 虚拟定时器
|
||||
@@ -216,4 +289,14 @@ struct timeval {
|
||||
|
||||
### 实时信号
|
||||
|
||||
查看信号
|
||||
|
||||
- `kill -l`
|
||||
- `cat /usr/include/bits/signum-generic.h`
|
||||
|
||||
1. 排队
|
||||
2. 不丢失
|
||||
|
||||
此外都和标准信号一样
|
||||
|
||||
## 线程(强烈异步)
|
||||
|
||||
45
C16-并发/parallel/signal/block.c
Normal file
45
C16-并发/parallel/signal/block.c
Normal file
@@ -0,0 +1,45 @@
|
||||
#include <bits/types/sigset_t.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static void int_hander(int s)
|
||||
{
|
||||
write(1, "!", 1);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
sigset_t set;
|
||||
sigset_t oldset;
|
||||
sigset_t saveset;
|
||||
|
||||
//! 要考虑原来是否阻塞的
|
||||
signal(SIGINT, int_hander);
|
||||
sigemptyset(&set);
|
||||
sigaddset(&set, SIGINT);
|
||||
sigprocmask(SIG_UNBLOCK, &set, &saveset);
|
||||
|
||||
for (j = 0; j < 1000; j++)
|
||||
{
|
||||
sigprocmask(SIG_BLOCK, &set, &oldset);
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
write(1, "*", 1);
|
||||
sleep(1);
|
||||
}
|
||||
write(1, "\n", 1);
|
||||
|
||||
// sigprocmask(SIG_UNBLOCK, &set, NULL);
|
||||
sigprocmask(SIG_SETMASK, &oldset, NULL);
|
||||
}
|
||||
// ctrl+\ : quit信号快捷方式
|
||||
|
||||
//!!! 还原原来的阻塞状态
|
||||
sigprocmask(SIG_SETMASK, &saveset, NULL);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
112
C16-并发/parallel/signal/mydaemon.c
Normal file
112
C16-并发/parallel/signal/mydaemon.c
Normal file
@@ -0,0 +1,112 @@
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/syslog.h>
|
||||
#include <syslog.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define FNAME "/tmp/out"
|
||||
|
||||
static FILE* fp;
|
||||
|
||||
static int deamonize(void)
|
||||
{
|
||||
pid_t pid;
|
||||
int fd;
|
||||
|
||||
pid = fork( );
|
||||
if (pid < 0)
|
||||
return -1;
|
||||
|
||||
if (pid > 0) // parent process
|
||||
exit(0);
|
||||
|
||||
fd = open("/dev/null", O_RDWR);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
dup2(fd, 0);
|
||||
dup2(fd, 1);
|
||||
dup2(fd, 2);
|
||||
if (fd > 2)
|
||||
close(fd);
|
||||
|
||||
setsid( );
|
||||
|
||||
chdir("/"); // 防止一直占用某设备
|
||||
// umask(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void daemon_exit(int s)
|
||||
{
|
||||
// if(SIGINT == s) 可以进行区分处理
|
||||
|
||||
fclose(fp); // 当多个信号响应同一个函数,可能多次free
|
||||
closelog( );
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int i;
|
||||
struct sigaction sa;
|
||||
|
||||
sa.sa_handler = daemon_exit;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sigaddset(&sa.sa_mask, SIGQUIT);
|
||||
sigaddset(&sa.sa_mask, SIGTERM);
|
||||
sigaddset(&sa.sa_mask, SIGINT);
|
||||
sa.sa_flags = 0;
|
||||
// !! 为了防止重入,对其中一个信号注册时要阻塞另外两个信号
|
||||
// 干脆就三个一起阻塞
|
||||
|
||||
sigaction(SIGINT, &sa, NULL);
|
||||
sigaction(SIGQUIT, &sa, NULL);
|
||||
sigaction(SIGTERM, &sa, NULL);
|
||||
|
||||
// signal(SIGINT, daemon_exit);
|
||||
// signal(SIGQUIT, daemon_exit);
|
||||
// signal(SIGTERM, daemon_exit);
|
||||
|
||||
openlog("mydaemon", LOG_PID, LOG_DAEMON);
|
||||
|
||||
if (deamonize( ))
|
||||
{
|
||||
syslog(LOG_ERR, "daemonize() failed!");
|
||||
exit(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
syslog(LOG_INFO, "daemonize() success!");
|
||||
}
|
||||
|
||||
fp = fopen(FNAME, "w");
|
||||
if (fp == NULL)
|
||||
{
|
||||
syslog(LOG_ERR, "fopen() failed!: %s", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
syslog(LOG_INFO, "%s was opened successfully!", FNAME);
|
||||
|
||||
for (i = 0;; i++)
|
||||
{
|
||||
fprintf(fp, "%d\n", i);
|
||||
fflush(fp); //! 刷新缓冲区
|
||||
syslog(LOG_DEBUG, "%d is printed", i);
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
// 目前守护进程只能异常终止,下面其实无法执行到
|
||||
// fclose(fp);
|
||||
// closelog( );
|
||||
|
||||
exit(0);
|
||||
}
|
||||
35
C16-并发/parallel/signal/mytbf_sa/Makefile
Normal file
35
C16-并发/parallel/signal/mytbf_sa/Makefile
Normal file
@@ -0,0 +1,35 @@
|
||||
# 方便起见一般都会先定义编译器链接器
|
||||
CC = gcc
|
||||
LD = gcc
|
||||
|
||||
# 正则表达式表示目录下所有.c文件,相当于:SRCS = main.c a.c b.c
|
||||
SRCS = $(wildcard *.c)
|
||||
|
||||
# OBJS表示SRCS中把列表中的.c全部替换为.o,相当于:OBJS = main.o a.o b.o
|
||||
OBJS = $(patsubst %c, %o, $(SRCS))
|
||||
|
||||
# 可执行文件的名字
|
||||
TARGET = main
|
||||
|
||||
# .PHONE伪目标,具体含义百度一下一大堆介绍
|
||||
.PHONY:all clean
|
||||
|
||||
# 要生成的目标文件
|
||||
all: $(TARGET)
|
||||
|
||||
LDFLAGS=-L/usr/local/lib
|
||||
|
||||
# LDLIBS=-lqueue -lllist
|
||||
|
||||
# 第一行依赖关系:冒号后面为依赖的文件,相当于Hello: main.o a.o b.o
|
||||
# 第二行规则:$@表示目标文件,$^表示所有依赖文件,$<表示第一个依赖文件
|
||||
$(TARGET): $(OBJS)
|
||||
$(LD) $(LDFLAGS) -o $@ $^ $(LDLIBS)
|
||||
|
||||
# 上一句目标文件依赖一大堆.o文件,这句表示所有.o都由相应名字的.c文件自动生成
|
||||
%.o:%.c
|
||||
$(CC) -c $^
|
||||
|
||||
# make clean删除所有.o和目标文件
|
||||
clean:
|
||||
rm -f $(OBJS) $(TARGET)
|
||||
99
C16-并发/parallel/signal/mytbf_sa/main.c
Normal file
99
C16-并发/parallel/signal/mytbf_sa/main.c
Normal file
@@ -0,0 +1,99 @@
|
||||
#include "mytbf.h"
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define CPS 10
|
||||
#define BUFSIZE 1024
|
||||
#define BURST 100 //!! token上限
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int sfd, dfd = 1;
|
||||
char buf[BUFSIZE];
|
||||
int len, ret, pos;
|
||||
int size;
|
||||
mytbf_t* tbf;
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s <src>\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
tbf = mytbf_init(CPS, BURST);
|
||||
if (NULL == tbf)
|
||||
{
|
||||
fprintf(stderr, "mytbf_init failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
do //!!!
|
||||
{
|
||||
sfd = open(argv[1], O_RDONLY);
|
||||
if (sfd < 0)
|
||||
{
|
||||
//!!!
|
||||
if (errno != EINTR)
|
||||
{
|
||||
perror("open");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
} while (sfd < 0);
|
||||
|
||||
while (1)
|
||||
{
|
||||
size = mytbf_fetchtoken(tbf, BUFSIZE);
|
||||
if (size < 0)
|
||||
{
|
||||
fprintf(stderr, "mytbf_fetchtoken failed: %s\n", strerror(errno));
|
||||
}
|
||||
|
||||
//* 阻塞在这里的时候,token会自增
|
||||
while ((len = read(sfd, buf, size)) < 0)
|
||||
{
|
||||
//!!!
|
||||
if (EINTR == errno)
|
||||
continue;
|
||||
|
||||
perror("read");
|
||||
break;
|
||||
}
|
||||
if (len == 0)
|
||||
break;
|
||||
|
||||
if (size - len > 0)
|
||||
mytbf_returntoken(tbf, size - len);
|
||||
|
||||
pos = 0;
|
||||
while (len > 0)
|
||||
{
|
||||
/* 可能没写完被别的中断打断 */
|
||||
ret = write(dfd, buf + pos, len);
|
||||
if (ret < 0)
|
||||
{
|
||||
//!!!
|
||||
if (EINTR == errno)
|
||||
continue;
|
||||
perror("write");
|
||||
exit(1);
|
||||
}
|
||||
pos += ret;
|
||||
len -= ret;
|
||||
}
|
||||
|
||||
// sleep(1); //! 能实现,但是移植性不好
|
||||
}
|
||||
|
||||
close(sfd);
|
||||
mytbf_destroy(tbf);
|
||||
exit(0);
|
||||
}
|
||||
201
C16-并发/parallel/signal/mytbf_sa/mytbf.c
Normal file
201
C16-并发/parallel/signal/mytbf_sa/mytbf.c
Normal file
@@ -0,0 +1,201 @@
|
||||
/***********************************************************************
|
||||
* @file mytbf.c
|
||||
* @brief
|
||||
* 令牌桶库实现
|
||||
*
|
||||
* @author lzy (lllzzzyyy@buaa.edu.cn)
|
||||
* @url https://lzyyyyyy.fun
|
||||
*
|
||||
* @date 2024-05-26
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
#include "mytbf.h"
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
struct mytbf_st
|
||||
{
|
||||
int cps;
|
||||
int burst;
|
||||
int token;
|
||||
int pos;
|
||||
};
|
||||
|
||||
static struct mytbf_st* job[MYTBF_MAX];
|
||||
static int inited = 0;
|
||||
static struct sigaction sa, alrm_sa_save;
|
||||
|
||||
|
||||
static int get_free_pos( )
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MYTBF_MAX; i++)
|
||||
{
|
||||
if (NULL == job[i])
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void alrm_action(int s, siginfo_t* infop, void* unused)
|
||||
{
|
||||
int i;
|
||||
|
||||
//* 判断信号来源
|
||||
if (SI_KERNEL != infop->si_code)
|
||||
return;
|
||||
|
||||
for (i = 0; i < MYTBF_MAX; i++)
|
||||
{
|
||||
if (NULL != job[i])
|
||||
{
|
||||
job[i]->token += job[i]->cps;
|
||||
if (job[i]->token > job[i]->burst)
|
||||
job[i]->token = job[i]->burst;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void module_unload( )
|
||||
{
|
||||
int i;
|
||||
struct itimerval itv;
|
||||
|
||||
sigaction(SIGALRM, &alrm_sa_save, NULL);
|
||||
if (errno != 0)
|
||||
{
|
||||
perror("sigaction");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
itv.it_interval.tv_sec = 0;
|
||||
itv.it_interval.tv_usec = 0;
|
||||
itv.it_value.tv_sec = 0;
|
||||
itv.it_value.tv_usec = 0;
|
||||
|
||||
setitimer(ITIMER_REAL, &itv, NULL);
|
||||
if (errno != 0)
|
||||
{
|
||||
perror("setitimer");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (i = 0; i < MYTBF_MAX; i++)
|
||||
free(job[i]);
|
||||
}
|
||||
|
||||
static void module_load( )
|
||||
{
|
||||
struct sigaction sa;
|
||||
struct itimerval itv;
|
||||
|
||||
sa.sa_sigaction = alrm_action;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = SA_SIGINFO; // 表示使用sigaction三参数的形式
|
||||
|
||||
sigaction(SIGALRM, &sa, &alrm_sa_save);
|
||||
if (errno != 0)
|
||||
{
|
||||
perror("sigaction");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
itv.it_interval.tv_sec = 1;
|
||||
itv.it_interval.tv_usec = 0;
|
||||
itv.it_value.tv_sec = 1;
|
||||
itv.it_value.tv_usec = 0;
|
||||
|
||||
setitimer(ITIMER_REAL, &itv, NULL);
|
||||
if (errno != 0)
|
||||
{
|
||||
perror("setitimer");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
atexit(module_unload); //!!! atexit()
|
||||
}
|
||||
|
||||
mytbf_t* mytbf_init(int cps, int burst)
|
||||
{
|
||||
struct mytbf_st* me;
|
||||
int pos;
|
||||
|
||||
if (!inited)
|
||||
{
|
||||
module_load( );
|
||||
inited = 1;
|
||||
}
|
||||
|
||||
pos = get_free_pos( );
|
||||
if (pos < 0)
|
||||
return NULL;
|
||||
|
||||
me = malloc(sizeof(*me));
|
||||
if (NULL == me)
|
||||
return NULL;
|
||||
|
||||
me->cps = cps;
|
||||
me->burst = burst;
|
||||
me->token = 0;
|
||||
me->pos = pos;
|
||||
|
||||
job[pos] = me;
|
||||
|
||||
return me;
|
||||
}
|
||||
|
||||
static int min(int a, int b)
|
||||
{
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
int mytbf_fetchtoken(mytbf_t* ptr, int size)
|
||||
{
|
||||
if (size <= 0)
|
||||
return -EINVAL;
|
||||
|
||||
struct mytbf_st* me = ptr;
|
||||
int n;
|
||||
|
||||
while (me->token <= 0)
|
||||
pause( );
|
||||
|
||||
n = min(size, me->token);
|
||||
|
||||
me->token -= n;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
int mytbf_returntoken(mytbf_t* ptr, int size)
|
||||
{
|
||||
if (size <= 0)
|
||||
return -EINVAL;
|
||||
|
||||
struct mytbf_st* me = ptr;
|
||||
|
||||
me->token += size;
|
||||
if (me->token > me->burst)
|
||||
me->token = me->burst;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int mytbf_destroy(mytbf_t* ptr)
|
||||
{
|
||||
struct mytbf_st* me = ptr;
|
||||
|
||||
job[me->pos] = NULL;
|
||||
|
||||
free(ptr);
|
||||
return 0;
|
||||
}
|
||||
26
C16-并发/parallel/signal/mytbf_sa/mytbf.h
Normal file
26
C16-并发/parallel/signal/mytbf_sa/mytbf.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/***********************************************************************
|
||||
* @file mytbf.h
|
||||
* @brief
|
||||
* 令牌桶库
|
||||
*
|
||||
* @author lzy (lllzzzyyy@buaa.edu.cn)
|
||||
* @url https://lzyyyyyy.fun
|
||||
*
|
||||
* @date 2024-05-26
|
||||
*
|
||||
***********************************************************************/
|
||||
#ifndef __MYTBF__H__
|
||||
#define __MYTBF__H__
|
||||
|
||||
#define MYTBF_MAX 1024
|
||||
typedef void mytbf_t;
|
||||
|
||||
mytbf_t* mytbf_init(int cps, int burst);
|
||||
|
||||
int mytbf_fetchtoken(mytbf_t*, int);
|
||||
|
||||
int mytbf_returntoken(mytbf_t*, int);
|
||||
|
||||
int mytbf_destroy(mytbf_t*);
|
||||
|
||||
#endif //!__MYTBF__H__
|
||||
48
C16-并发/parallel/signal/susp.c
Normal file
48
C16-并发/parallel/signal/susp.c
Normal file
@@ -0,0 +1,48 @@
|
||||
#include <bits/types/sigset_t.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static void int_hander(int s)
|
||||
{
|
||||
write(1, "!", 1);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
sigset_t set;
|
||||
sigset_t oldset;
|
||||
sigset_t saveset;
|
||||
|
||||
//! 要考虑原来是否阻塞的
|
||||
signal(SIGINT, int_hander);
|
||||
sigemptyset(&set);
|
||||
sigaddset(&set, SIGINT);
|
||||
sigprocmask(SIG_UNBLOCK, &set, &saveset);
|
||||
sigprocmask(SIG_BLOCK, &set, &oldset);
|
||||
for (j = 0; j < 1000; j++)
|
||||
{
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
write(1, "*", 1);
|
||||
sleep(1);
|
||||
}
|
||||
write(1, "\n", 1);
|
||||
|
||||
sigsuspend(&oldset); // 相当于下面几句的原子操作
|
||||
#if 0
|
||||
sigset_t tmpset;
|
||||
sigprocmask(SIG_SETMASK, &oldset, &tmpset);
|
||||
pause( );
|
||||
sigprocmask(SIG_SETMASK, &tmpset, NULL);
|
||||
#endif
|
||||
}
|
||||
// ctrl+\ : quit信号快捷方式
|
||||
|
||||
//!!! 还原原来的阻塞状态
|
||||
sigprocmask(SIG_SETMASK, &saveset, NULL);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
46
C16-并发/parallel/signal/susp_rt.c
Normal file
46
C16-并发/parallel/signal/susp_rt.c
Normal file
@@ -0,0 +1,46 @@
|
||||
#include <bits/types/sigset_t.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// 编号40
|
||||
// kill -40 pid
|
||||
#define MYRTSIG (SIGRTMIN + 6)
|
||||
|
||||
static void mysig_hander(int s)
|
||||
{
|
||||
write(1, "!", 1);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
sigset_t set;
|
||||
sigset_t oldset;
|
||||
sigset_t saveset;
|
||||
|
||||
//! 要考虑原来是否阻塞的
|
||||
signal(MYRTSIG, mysig_hander);
|
||||
sigemptyset(&set);
|
||||
sigaddset(&set, MYRTSIG);
|
||||
sigprocmask(SIG_UNBLOCK, &set, &saveset);
|
||||
sigprocmask(SIG_BLOCK, &set, &oldset);
|
||||
for (j = 0; j < 1000; j++)
|
||||
{
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
write(1, "*", 1);
|
||||
sleep(1);
|
||||
}
|
||||
write(1, "\n", 1);
|
||||
|
||||
sigsuspend(&oldset); // 相当于下面几句的原子操作
|
||||
}
|
||||
// ctrl+\ : quit信号快捷方式
|
||||
|
||||
//!!! 还原原来的阻塞状态
|
||||
sigprocmask(SIG_SETMASK, &saveset, NULL);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
Reference in New Issue
Block a user