一 . 信号

1. 信号:是内核发送给某一进程的一种消息 。

2. 信号机制:是Linux系统中用于进程之间相互通信或操作的一种机制。

3. 信号的来源:信号来源于内核

4. 产生原因: (1)用户通过终端输入 (2)进程执行(3)一个进程调用kill向另一个进程发送信号

5. 信号分类:1)同步信号    异步信号

2)可靠信号 : 信号被递送多次  不可靠信号: 只被递送一次的信号

6. 信号处理方式

A.  按系统默认方式处理 ——每个信号都有一个默认动作,典型的默认动作是终止进程。 man signal 7 列出系统对各信号的默认处理 。

B.  忽略信号——接收信号,但是不做任何操作 。

C.  捕捉信号——程序提前告诉内核,当信号到来时应该调用哪个函数。

二. 信号相关函数

1.  简单的信号处理

函数原型: sighandler_t signal(int signum, sighandler_t handler);

参    数:signum ——要响应的信号,handler  ——信号发生时要执行的操作。

返回值:非-1    执行成功,返回以前的信号处理函数指针

-1        遇到错误

//捕捉信号

#include

#include

#include

#include

void capture(int signum){

printf("SIGINT is capture!\n");

}

int main(int argc, char *argv[]){

int i=10;

if(signal(SIGINT,capture) == SIG_ERR){

printf("Can't catch SIGINT");

exit(1);

}

printf("waiting for signal...\n");

while(i > 0){

printf("Now i=%d \n",i);

sleep(1);

i--;

}

return 0;

}

//忽略信号

#include

#include

#include

int main(int argc,char *argv[]){

int i=10;

signal(SIGINT,SIG_IGN);

printf("waiting for signal ...\n");

while(i > 0){

sleep(1);

i--;

printf("Now i = %d,but you can't stop this program by Ctrl + C\n",i);

}

return 0;

}

//恢复信号的默认处理

#include

#include

void capthensfl(int signum){

printf("SIGINT is capture !\n");

signal(SIGINT,SIG_DFL);

printf("SIGINT now is defaulted !\n");

}

int main(int argc,char *argv[]){

int i=10;

signal(SIGINT,capthensfl);

printf("waiting for signal...\n");

while(i > 0){

sleep(1);

printf("Now i = %d\n",i);

i--;

}

return 0;

}

2. 信号处理函数:指定一个信号的处理函数

函数原型:int sigaction(int signum, struct sigaction *action, struct sigaction *oldaction);

参    数:signum  ,要处理的信号

action        要安装的信号处理操作的结构

oldaction   之前的信号处理操作的结构

返回值:0    成功     -1,失败

说    明:oldaction不为NULL,则用其来存储以前设置的与此信号关联的操作。

action不为NULL: 则指定信号关联的操作为此参数指向的结构 否则,信号处理保持不变。(此方式用来查询当前对指定信号的处理方式)

sigaction的结构:

struct sigaction{

union{         __sighandler_t _sa_handler;

void(*_sa_sigaction)(int , struct siginfo *, void *);

} __u;

sigset_t sa_mask;

unsigned long sa_flags;

};

sa_sigaction的说明: void (*sa_sigaction)(int, struct siginfo *,void *);

第一个参数:要响应的信号 。

第二个参数:记录导致产生信号的原因、类型等 。

第三个参数:信号发生时被中断的上下文环境 信号能传递简单的信息。

//使用sa_sigaction类型函数

#include

#include

#include

#include

void fun(int signo, siginfo_t *info, void *context){

printf("Test for sa_sigaction !\n");

}

int main(int argc,char *argv[]){

struct sigaction action,oldaction;

sigemptyset(&action.sa_mask);

action.sa_flags=SA_SIGINFO;

action.sa_sigaction=fun;

sigaction(SIGINT,&action,&oldaction);

printf("waiting for signal...\n");

while(1){

pause();

}

return 0;

}

3. 初始化信号集

函数原型:int sigemptyset(sigset_t  *set);

int sigfillset(sigset_t  *set);

参    数:set  待初始化的信号集

返回值:0   成功     -1,失败

4. 添加、删除信号

函数原型:int sigaddset(sigset_t *set, int signo);

int sigdelset(sigset_t *set, int signo);

参    数:set  待初始化的信号集 .  signo  待添加/删除的信号编号

返回值:0  成功     -1,失败

5. 修改屏蔽信号集

函数原型:int sigprocmask(int how,sigset_t *set, sigset_t * oldset);

参    数:how   如何修改信号掩码

set 要使用的信号集

oldset   之前的信号集

返回值:0  成功     -1,失败

对参数how的说明:    SIG_BLOCK:信号集中增加set中的信号

SIG_UNBLOCK:信号集中删除set中的信号

SIG_SETMASK:信号集被设置为set信号集

三.  系统调用函数

1. kill  —— 向进程发送一个信号

函数原型:int kill(pid_t pid, int sig);

参    数:pid 目标进程id, sig  要发送的信号

返回值:0  成功     -1,失败

说    明:     pid>0      目标进程的进程号为pid

pid=0      将信号发送给和当前进程在同一进程租的所有进程

pid=-1     将信号发送给系统内的所有进程

pid<0      将信号发送给进程组号PGID为pid绝对值的所有进程

一个进程可使用kill函数将信号发送给另一进程或进程组。

要求:发送信号的进程的用户ID和目标进程的用户ID相同,或发送信号的进程的owner是一个超级用户。

//kill 使用示例

#include

#include

#include

void fun(int signo){

printf("Process capture SIGINT");

signal(SIGINT,SIG_DFL);

}

int main(int argc,char *argv[]){

int pid;

if((pid=fork()) == -1){

perror("fork");

exit(EXIT_FAILURE);

}

else if( pid == 0){

signal(SIGINT,fun);

printf("Child %d waiting for parent %d send signal\n",getpid(),getppid());

pause();

pause();

}

else{

sleep(1);

printf("Parent %d will send signal to child %d \n",getppid(),getpid());

kill(pid,SIGINT);

wait(NULL);

}

return 0;

}

2. raise —— 自举一个信号

函数原型:int raise(int signo);

参    数:signo      待发送的信号

返回值:0  成功     -1,失败

说   明:raise(signo)=kill(getpid(),signo)

3. alarm —— 设置计时器

函数原型:int alarm(int seconds);

参    数:seconds  计时的秒数

返回值:      0    之前未调用过alarm

>0   之前调用alarm设置的闹钟时间的余留秒数

4. pause —— 挂起调用进程

函数原型:int pause(void);

返回值:-1       并将errno设置为EINTR

四. 信号集合操作应用示例

/*  信号的应用示例:

父进程执行文件复制操作,如果收到SIGUSR1信号,就打印出当前的复制进度

子进程每隔一个固定时间向父进程发送SIGUSR1信号

*/

#include

#include

#include

#include

#include

#include

int count;  //当前复制大小

int file_size; //文件的大小

//父进程对SIGUSR1信号的处理函数

void sig_usr(int signum){

float i;

//求出复制进程

i = (float)count/(float)file_size;

printf("current over : %0.0f%%\n",i*100);

}

//子进程对SIGUSR1信号的处理,即向父进程发送SIGUSR1信号

void sig_alarm(int signo){

kill(getppid(),SIGUSR1);

}

//主函数

int main(int argc ,char *argv[]){

pid_t pid;

int i;

int fd_src,fd_des;

char buf[128];

if(argc != 3){

printf("the format must be : command src_file des_file \n");

return -1;

}

//以只读方式打开源文件

if((fd_src = open(argv[1],O_RDONLY)) == -1){

perror("open fd_src");

exit(EXIT_FAILURE);

}

//获取源文件大小

file_size = lseek(fd_src,0,SEEK_END);

//重新设置读写位置为文件头

lseek(fd_src,0,SEEK_SET);

//以读写方式打开目标文件,如果不存在就创建

if((fd_des = open(argv[2],O_RDWR|O_CREAT,0644)) == -1){

perror("open fd_des");

exit(EXIT_FAILURE);

}

//进程创建失败

if((pid = fork() == -1)){

perror("fork");

exit(EXIT_FAILURE);

}

//父进程

else if(pid > 0){

//安装信号

signal(SIGUSR1,sig_usr);

do{

memset(buf,'\0',128);

//复制数据

if((i = read(fd_src,buf,1)) == -1){

perror("read");

exit(EXIT_FAILURE);

}

//如果复制完成,向子进程发送SIGINT信号,终止

else if(i == 0){

kill(pid,SIGINT);

break;

}

else{

//执行复制操作

if(write(fd_des,buf,i) == -1){

perror("write");

exit(EXIT_FAILURE);

}

count += i; //更新已经复制的文件的大小

}

}while(i != 0);

//等待子进程退出

wait(pid,NULL,0);

exit(EXIT_SUCCESS);

}

//子进程

else if(pid == 0){

usleep(1);

signal(SIGALRM,sig_alarm);

ualarm(1,1);

while(i){

;

}

exit(EXIT_SUCCESS);

}

return 0;

}

linux信号值头文件位置,Linux C 信号处理机制相关推荐

  1. linux中的crontab文件位置,linux crontab 文件位置和日志位置

    一.文件位置 位置一般在/var/spool/cron/下,如果你是root用户,那下面有个root文件,建议日常备份,避免误删除导致crontab 文件丢失: 二.日志文件位置 默认情况下,cron ...

  2. pcap头文件位置 Linux,pcap文件头的组织格式

    PCAP文件格式分析 一.基本格式: 文件头 数据包头 数据报 数据包头 数据报...... 二.文件头结构体: sturct pcap_file_header { DWORD magic; WORD ...

  3. Linux C try 头文件,linux c 头文件

    //1.Linux中一些头文件的作用: #include //ANSI C.提供断言,assert(表达式) #include //GCC.GTK,GNOME的基础库,提供很多有用的函数,如有数据结构 ...

  4. linux c 各头文件作用总结

    #include <linux/***.h> 是在linux-2.6.29/include/linux下面寻找源文件. #include <asm/***.h> 是在linux ...

  5. Linux中常用头文件的作用--转

    http://blog.sina.com.cn/s/blog_5c93b2ab0100q62k.html 1. Linux中一些头文件的作用: <assert.h>:ANSI C.提供断言 ...

  6. Linux常用的头文件及含义

    博文地址:http://blog.csdn.net/wubin1124/archive/2009/12/09/4971359.aspx 首先说明几点: 1 Linux内核所在目录为/usr/src/k ...

  7. [转]Linux C语言头文件搜索路径

    转自:http://hi.baidu.com/ilonng/blog/item/a0232435fbcfb90490ef390d.html/cmtid/68d4ab7bbb8026fb0ad187be ...

  8. vs2017 linux工程设置头文件,使用Visual Studio 2017作为Linux C++开发工具

    Visual Studio 2017 VS2017亮点很多,包括模块化安装.启动速度加快(第一次启动加快50%以上).github插件.启动页完善.增强代码提示功能,等等,更多参考:https://w ...

  9. 如何下载linux内核头文件,在Linux系统上安装Linux内核头文件的教程

    当你在编译一个设备驱动模块时,你需要在系统中安装内核头文件.内核头文件同样在你编译与内核直接链接的用户空间程序时需要.当你在这些情况下安装内核头文件时,你必须确保内核头文件精确地与你当前内核版本匹配( ...

最新文章

  1. java numberutil_NumberUtil
  2. 手机端实现点击复制功能
  3. 第10章 图与网络优化
  4. oracle11g安装到第7步,centos7安装oracle11g到这一步卡在了?也没有安装界面
  5. 李宏毅机器学习(五)Transformer
  6. oracle监听系统账号,linux 下 Oracle 监控sysdba用户登陆
  7. 【Java】区分BigDecimal的toString()和toPlainString()
  8. linux设备模型的主要功能,第 14 章 Linux 设备模型
  9. Nginx之升级和构建后添加新的模块
  10. 鞍山楷邦计算机学院,计算机专业和平面设计专业是一个专业不?
  11. 生成指定范围的随机数_JAVA 获取随机数的方式以及应用案例
  12. matlab按图像边缘抠图_不会抠图?保姆级抠图教程!手把手教你抠图(二)
  13. wps里的html怎么保存,WPS网页复制保存文档文字技巧
  14. Java stream().filter()筛选出符合条件的数据
  15. 腾讯互娱2021年游戏客户端开发工程师暑期实习生面试经历
  16. 我的感悟:一切都是最好的安排
  17. 美团综合业务推荐系统的质量模型与实践
  18. keycloak+gatekeeper(python) 搭建简单流程
  19. jQuery快速入门(2)--操作 2021.11.20
  20. ORA-03113 end-of-file on communication channel 问题解决

热门文章

  1. cout输出数组_让程序从1开始一直执行++操作,10秒钟能输出最大的数是多少
  2. 文档上传到服务器上,将文件上传到服务器上
  3. linux安装mysql 5.6_linux 安装mysql5.6
  4. eclipse发布web不带项目名的url
  5. oracle数据库领域,菜鸟成长课程之《Oracle数据库职业直通车》,引领大家真正进入Oracle数据库领域...
  6. python与tensorflow的关系_python – 在TensorFlow,Session.run()和Tensor.eval()之间有什么区别?...
  7. ubuntu 远程桌面
  8. WINCE BSP中source文件中的宏定义
  9. ARMV4,ARMV4T,ARMV4I的意义
  10. 正确断开计算机和网络的方法是,网络管理与维护-题库