信号屏蔽

信号忽略:系统仍然传递该信号,只是相应的进程不做任何处理

信号屏蔽:进程不捕获信号,信号处于未决状态,当不再屏蔽信号时可以捕获之前被屏蔽的信号。

信号集数据结构定义:

typedef __sigset_t sigset_t;
#define _SIGSET_NWORDS (1024 / (8 * sizeof(unsigned long int)))
typedef struct
{
//此结构体占据32 * 32 = 1024 bit 每bit对应一个信号 val[0]0-31位对应常用1-31信号
unsigned long int __val[_SIGSET_NWORDS];
}__sigset_t;

int sigprocmask (int __how, __const sigset_t *__restrict __set, sigset_t * __restrict __oset) :设置屏蔽信号集。成功0,否则-1.

第一个参数:更改该集的方式

  • SIG_BLOCK : 将第2个参数描述的集合添加到当前进程屏蔽的信号集中
  • SIG_UNBLOCK : 将第2个参数描述的集合从到当前进程屏蔽的信号集中删除
  • SIG_SETMASK : 无论之前屏蔽了哪些信号,设置当前屏蔽集为第2个参数描述的对象。

如果set是空指针,则how没有意义,不会更改屏蔽信号集,因此可以查询当前屏蔽的信号集合。

int sigpending (sigset_t * __set) :获取当前未决的信号。成功0,否则-1.

int sigemptyset (sigset_t * __set) :  清空信号集

int sigfillset (sigset_t * __set) :将set的所有位都置为1.

int sigaddset (sigset_t *__set, int __signo) : 添加信号到信号集set

int sigdelset (sigset_t * __set, int __signo) : 从set中删除信号

int sigismember (__const sigset_t *__set, int __signo) : 检测信号是否在信号集,是返回1,否则返回0

int sigisemptyset (__const sigset_t * __set) : 检测信号集是否为空信号集

int sigandset (sigset_t *__set, __const sigset_t *__left, __const sigset_t *__right) : 用逻辑与的方式将两个信号合并

int sigorset (sigset_t *__set, __const sigset_t *__left, __const sigset_t *__right) : 用逻辑或的方式将两个信号合并

当一个信号在处理的过程中,相同的信号会暂时屏蔽,防止信号处理嵌套。

等待信号

int pause (void) :等待除了当前屏蔽信号集合外的任意信号

int sigsuspend (__const sigset_t * __set) :将当前进程屏蔽的信号集替换为其参数所指定的信号集合,直到收到非指定集合中的信号才继续执行

注意 不能屏蔽SIGKILL和SIGSTOP

信号应用例子

功能是复制文件,父进程执行复制操作,如果收到SIGUSR1信号则打印当前复制进度;子进程每隔固定时间向父进程发送SIGUSR1信号,通过SIGALARM

#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<signal.h>
#include<stdlib.h>
int count; //当前复制大小
int file_size; //文件大小
void sig_alarm(int arg); //处理alarm信号
void sig_usr(int sig); //处理普通信号SIGUSR1
int main(int argc, char *argv[])
{
pid_t pid;
int i;
int fd_src, fd_des;
char buf[]; //复制操作临时空间
if(argc != )
{
printf("check the format:comm src_file des_file\n");
return -;
}
if((fd_src = open(argv[], O_RDONLY)) == -)
{
perror("open file src");
exit(EXIT_FAILURE);
}
file_size = lseek(fd_src, , SEEK_END); //获取资源文件大小
lseek(fd_src, , SEEK_SET); //重新设置读写位置为文件头
if((fd_des = open(argv[], O_RDWR|O_CREAT, )) == -)
{
perror("open fd_fdes");
exit(EXIT_FAILURE);
}
if((pid = fork()) == -)
{
perror("fork");
exit(EXIT_FAILURE);
}
else if(pid > )
{
signal(SIGUSR1, sig_usr); //安装信号SIGUSR1
do
{
memset(buf, '\0', );
if((i = read(fd_src, buf, )) == -)
{
perror("read");
exit(EXIT_FAILURE);
}
else if(i == ) //如果复制完毕,向子进程发送SIGINT信号,终止子进程
{
kill(pid, SIGINT);
break;
}
else
{
if(write(fd_des, buf, i) == -)
{
perror("write");
exit(EXIT_FAILURE);
}
count += i; //更新已经复制的大小
}
}while(i != );
wait(pid, NULL, ); //等待子进程退出
exit(EXIT_SUCCESS);
}
else if(pid == )
{
usleep();
signal(SIGALRM, sig_alarm); //安装SIGALRM信号
ualarm(, );
while();
exit(EXIT_SUCCESS);
}
} void sig_alarm(int arg)
{
kill(getppid(), SIGUSR1); //向父进程发送SIGUSR1信号
}
void sig_usr(int sig)
{
float i;
i = (float)count/(float)file_size;
printf("current over : %0.0f%%\n", i *);
}

功能可以实现,但是奇怪的是ualarm中的数字,即使我改成很大,比如ualarm(100,1000) 信息输出的还是很密集,感觉跟 ualarm(1,1)的没有区别??按理说时间间隔应该变长啊?

【linux高级程序设计】(第十章)Linux异步信号处理机制 3的更多相关文章

  1. 【linux高级程序设计】(第十二章)Linux多线程编程 4

    读写锁 书上有读者写者的代码,我实在是懒得实现一遍了.跟之前的代码差不多. 多线程异步信号处理 int pthread_kill (pthread_t __threadid, int __signo) ...

  2. Linux程序设计学习笔记——异步信号处理机制

    转载请注明出处: http://blog.csdn.net/suool/article/details/38453333 Linux常见信号与处理 基本概念 Linux的信号是一种进程间异步的通信机制 ...

  3. 【linux高级程序设计】(第十六章)网络服务器应用设计

    xinetd服务介绍 xinetd是Linux下的一个网络守候进程,用来统一管理网络负载不大的一组小型网路服务. 一些小型的网络服务,比如时间,telnet服务,不以守候进程出现,而是让xinetd服 ...

  4. 【linux高级程序设计】(第十五章)UDP网络编程应用 4

    socket信号驱动 为了使一个套接字能够使用信号驱动I/O,至少需要以下3步操作. 1.安装SIGIO信号 2.套接字的拥有者设定为当前进程.因为SIGIO信号只会送到socket拥有者进程. 通过 ...

  5. 【linux高级程序设计】(第十二章)Linux多线程编程

    线程与进程对比 1.用户空间对比 2.内核空间资源对比 在创建线程时,Linux内核仍然创建一个新的PCB来标识这个线程.内核并不认为进程与线程有差别. 进程是操作系统管理资源的基本单元,线程时Lin ...

  6. 【linux高级程序设计】(第十一章)System V进程间通信 2

    消息队列 消息队列是消息的链式队列,模型如下: 包括两种数据结构: msqid_ds消息队列数据结构 msg消息队列数据结构 struct msg_msg{ struct list_head m_li ...

  7. 【linux高级程序设计】(第十一章)System V进程间通信 1

    System V, 曾经也被称为 AT&T System V,是Unix操作系统众多版本中的一支. 传统上,System V 被看作是两种UNIX"风味"之一(另一个是 B ...

  8. 【linux高级程序设计】(第九章)进程间通信-管道 1

    Linux操作系统所支持的主要进程间的通信机制. 无名管道 PIPE cat test.txt| grep hello 上面这种管道,将一个命令的输出作为另一个命令的输入,而这种管道是临时的,命令执行 ...

  9. 【视频】 Linux高级程序设计01.2开发平台及Linux环境限制

    [课程笔记] Linux环境限制 遵循规范,使用现有资源,明确系统限制,增量开发. (1)规范问题 编码的规范,让程序更易读.Linux编码规范. “见着如意”:变量,函数命名等能够让人看到名称就知道 ...

随机推荐

  1. 十二、mysql之视图,触发器,事务等

    一.视图 视图是一个虚拟表(非真实存在),其本质是[根据SQL语句获取动态的数据集,并为其命名],用户使用时只需使用[名称]即可获取结果集,可以将该结果集当做表来使用. 使用视图我们可以把查询过程中的 ...

  2. MVC WebAPI 的基本使用

    1.什么是WebAPI Web API是网络应用程序接口.包含了广泛的功能,网络应用通过API接口,可以实现存储服务.消息服务.计算服务等能力,利用这些能力可以进行开发出强大功能的web应用. 它可以 ...

  3. laravel - ReflectionException in Container.php, Class not found?

    SIGN UPSIGN IN CATALOG SERIES PODCAST DISCUSSIONS ReflectionException in Container.php, Class not fo ...

  4. laravel5.5容器

    目录 1. 比较典型的例子就是 cache 缓存 2. 容器顾名思义,其实就是完成存取过程 2.1 绑定过程 简单绑定 绑定单例 绑定实例 绑定初始数据 2.2 解析过程 容器主要是为了实现控制反转, ...

  5. Unicode字符图标

    http://unicode-table.com/cn/#control-character

  6. B树、B-树、B+树、B*树 红黑树

    转载自:http://blog.csdn.net/quitepig/article/details/8041308 B树 即二叉搜索树: 1.所有非叶子结点至多拥有两个儿子(Left和Right): ...

  7. save?commit

    数据库的隐式提交 先看一段SQL,最后一条SQL的输出你认为是什么? 1 2 3 4 5 6 7 SET AUTOCOMMIT = 1; BEGIN; INSERT INTO t1 VALUES (1 ...

  8. NBA投篮

    D 辅助插件:原生 游戏制作难度系数:初级 游戏教程网址:http://www.raywenderlich.com/20333/beginning-unity-3d-for-ios-part-1 1. ...

  9. excel模板解析—桥接模式:分离解析模板和业务校验

    在做excel模板解析的时候,其实会有两个部分,第一,将模板读取出来,校验一些必录项等. 但除了这些,在数据真正被业务线使用的时候,还会有一些其他的校验,比如说:根据业务,年龄是不能超过多少岁的,包括 ...

  10. Servlet中文件上传

    利用getReader()和getInputstream()上传 package control; import javax.servlet.ServletException; import java ...