画布 1
信号
  信号状态
    kill -l可以列出信号类型
    接受后保存在进程的PCB中,内核首先读取这个，再觉得之后操作
      产生方式：软件超时; 硬件异常;终端接受键盘命令;kill;
  信号控制
    信号处理，和用户进程异步，不在同处理堆
    处理方式：忽略; 默认; sigaction返用户态，称 catch;
    阻塞
      取消阻塞后称递达
      阻塞前未决,信号产生未决标志位就会变为1表示信号正在被阻塞，后者依靠前者
        未决和阻塞标志可以用相同的数据类型sigset_t,
          #include <signal.h>
int sigpending(sigset_t *set);
            读取未决信号集,返回状态
  捕捉信号
    int sigaction(int signo, const struct sigaction *act, struct sigaction *oact);
      oact是旧结构体
    pause处理,挂起至信号抵达,信号处于忽略状态。继续挂起,只如果信号的处理动作是捕捉，则调用了信号处理函数之后pause返回-1，errno设置为EINTR,在程序中作用之所查看是否有其他中断信号
    进行下一步动作
  重入操作
    函数被不同的控制流程调用，有可能在第一次调用还没返回时就再次进入该函数，这称为重入
    大多不可重入的,调用了malloc或free，因为malloc也是用全局链表来管理堆的。
调用了标准I/O库函数。
  竞态条件
    int sigsuspend(const sigset_t *sigmask);errno
      挂起和解除屏蔽同时进行,信号屏蔽字由sigmask参数指定(蔽or不弊）,SIGALRM递达后suspend返回，自动恢复原来的屏蔽字,之后要手动还原
  signal
    #define SIG_ERR (void (*)())-1
    #define SIG_DFL (void (*)())0
    #define SIG_IGN (void (*)())1
  阻塞和未决（到达或忽略）标志位
  改变信号屏蔽字
    #include <signal.h>
    int sigprocmask(int how, const sigset_t *set, sigset_t *oset);
    信号操作集
      #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);
      set为需要设置的信号集，通过sigaddset加入，oset有指向就把原来的信号屏蔽字储存
  自由主题
    struct sigaction {
    void (*sa_handler)(int);可以为SIGIGN ，sigdef,也可以自己注册一个函数，被系统调用
    sigset_t sa_mask; 通过signadd自己添加的额外需要屏蔽的信号,捕捉的信号处理完可以恢复元屏蔽位
    int sa_flags; /* signal options, Figure 10.16 */
    void (*sa_sigaction)(int, siginfo_t *, void *);
  原子操作，防止错乱
    volatile sig_atomic_t
      多流程控制时，编译器优化单一流程没有改变a值，就不需要重复读取（不知道外部还有），因此原子操作时应该加上volatile,防止优化
    一此步骤完成，原子操作。
    序要求严格
  购买xmind pro
https://item.jd.com/17816155687.html
    购买xmind pro