IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> Linux C: 信号及异常和捕捉函数原理 -> 正文阅读

[系统运维]Linux C: 信号及异常和捕捉函数原理

#define SIGHUP 1终端挂起或控制进程终止
#define SIGINT 2终端中断(Ctrl+C 组合键)
#define SIGQUIT 3终端退出(Ctrl+\组合键)
#define SIGILL 4非法指令
#define SIGTRAP 5debug 使用,有断点指令产生
#define SIGABRT 6由 abort(3)发出的退出指令
#define SIGIOT 6IOT 指令
#define SIGBUS 7总线错误
#define SIGFPE 8浮点运算错误
#define SIGKILL 9杀死、终止进程
#define SIGUSR1 10用户自定义信号 1
#define SIGSEGV 11段错误(无效的内存段)
#define SIGUSR2 12用户自定义信号 2
#define SIGPIPE 13向非读管道写入数据
#define SIGALRM 14闹钟
#define SIGTERM 15软件终止
#define SIGSTKFLT 16栈异常
#define SIGCHLD 17子进程结束
#define SIGCONT 18进程继续
#define SIGSTOP 19停止进程的执行,只是暂停
#define SIGTSTP 20停止进程的运行(Ctrl+Z 组合键)
#define SIGTTIN 21后台进程需要从终端读取数据
#define SIGTTOU 22后台进程需要向终端写数据
#define SIGURG 23有"紧急"数据
#define SIGXCPU 24超过 CPU 资源限制
#define SIGXFSZ 25文件大小超额
#define SIGVTALRM 26虚拟时钟信号
#define SIGPROF 27时钟信号描述
#define SIGWINCH 28窗口大小改变
#define SIGIO 29可以进行输入/输出操作
#define SIGPOLLSIGIO
#define SIGPWR 30断点重启
#define SIGSYS 31非法的系统调用
#define SIGUNUSED 32未使用信号

转载:「一只青木呀」的原创文章,原文链接:https://blog.csdn.net/weixin_45309916/article/details/111939072

一、信号和中断
?

? ? ? ?信号是进程间通信的重要内容之一。它可以来源于硬件,例如键盘的 Ctrl+C 组合键,间隔定时器,IO错误等硬件错误;也可以是来源于自己,例如自己的代码除0,指针越界等执行报错;其中最需要了解的是来自于其他进程例如 kill命令。信号可以被捕捉从而触发信号处理函数。信号处理函数可以被重写,信号也可以被屏蔽。

? ? ? ? 在进程结构体PROC 中,都有一个信号处理数组 int sig[32] ; 其中值为0 代表默认处理,1代表忽略,其他非零值表示用户模式下预先设定好的信号处理函数地址。除了信号处理数组每个PROC都有一个32位向量(信号位向量) 和Mask(屏蔽)位向量? 。 bits向量用来指明哪些信号被signal? , masks 用来指明哪些信号被Block 。当信号位为1时,且屏蔽位为0时,信号才会生效并传递给进程。如果进程发现了个未被阻塞的信号,则会将信号位清0。

二、信号的捕捉和捕捉函数的设置?

? ? ? ? 信号处理内容可以被修改,除了 SIGKILL(9)? 和 SIGSTOP(19)? 。 为了处理信号捕捉可能造成的死循环,这两个信号9和19作为终止进程的最后手段,规定了不能被修改。

? ? ? ?进程可以使用系统调用来修改捕捉到信号时的信号处理函数:

? ? ? int r = signal (int signal_number , void *handler) ;?

? ? ?但是signal 函数有几个个缺点:

? ? 1。如果信号触发频率过快,可能导致下一个信号和信号处理函数重新设置会出现竞态条件。相同的,signal是线程不安全的,可能不适用于多线程。

? ? 2.? signal不能阻塞其他信号,只能通过sigprocmask()来显示屏蔽或者接触屏蔽信号

? ? 3.signal 只能传输一个信号编号,不能够传输关于信号的其他信息?

因此,现在大多数都用sigaction()? 来代替 signal:

sigaction()? 的系统调用和 sigaction 结构体如下:

int sigaction(int sigid ,const struct sigaction *act , struct sigaction *oldact );

struct sigaction{
void (*sa_handler)(int);
void (*sa_sigaction)(int , siginfo_t *,void *);
sigset_t sa_mask;
int  sa_flags;
void (*sa_restorer)(int);
}

sa_handler : 指向处理函数的指针

sa_sigaction :另一种方法,指向处理函数的指针 , 外加上了两个额外的参数。其中siginfo_t 接收信号的更多信息。

sa_mask? ?: 在处理函数执行时,设置要阻塞的信号

sa_flags ;? ? 设置信号处理过程的行为,如果用sa_sigaction处理函数,sa_flags 需设置为 SA_SIGINFO.

sigaction:的示例:

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
void handler (int sig ,siginfo_t *siginfo , void * context){
    printf("handler:sig = %d from PID=%d  UID=%d \n",sig,siginfo->si_pid,siginfo->si_uid);
}

int main(int argc, char * argv[]){
    struct sigaction act ;
    memset(&act ,0 ,sizeof(act));
    act.sa_sigaction = &handler ;
    act.sa_flags =SA_SIGINFO ;
    sigaction(SIGTERM,&act ,NULL);
    printf("looping\n");
    printf("enter kill PID=%d to send SIGTERM signal to it \n" , getpid());
    while(1){
        sleep(10);
    }
}

上面的代码利用sigaction 重新设置SIGTERM (15) 信号,当收到 15信号时就会执行 handler内容。开启另一个会话对进程发出kill命令,则会有上面的输出结果。最后发出的8信号对应是浮点异常信号,虽然上述程序并不会出现浮点异常,但是由于程序收到了该信号,就执行默认的信号8处理函数了.

三、利用sigaction和管道实现消息IPC

Linux 管道和和文件描述符的相关内容:可看

https://blog.csdn.net/superSmart_Dong/article/details/118641774

/****sigaction*****/
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <signal.h>

#define LEN 64
int ppipe[2];    //管道-文件描述符
int pid ;
char line[LEN];
int parent(){
     printf("parent %d running \n",getpid());
     close(ppipe[0]);   //  关闭标准输入文件描述符
     while(1){
        printf("parent %d : input a line : \n" ,getpid());
        fgets(line ,LEN,stdin);  // line[LEN]得到标准输入
        line[strlen(line) -1 ] = 0 ;
        printf("parent %d write to pipe",getpid());
        write(ppipe[1],line,LEN);   //向管道写入内容
        printf("parent %d send signal 10 to %d",getpid(),pid);
        kill(pid,SIGUSR1);
     }
}
void chandler(int sig){
    printf ("\n child  %d got an interrupt sig=%d \n ",getpid(),sig);
    read(ppipe[0] ,line ,LEN);     //向管道读出内容 
    printf("child %d get a message = %s \n" ,getpid(),line);   
}
int child(){
     char msg[LEN];
     int parent  =getppid();
     printf("child %d running \n",getpid());
     close(ppipe[1]);
     signal(SIGUSR1,chandler);
    while(1);
}
int main(int argc, char * argv[]){
    pipe(ppipe);
    pid = fork();
    if (pid){
       parent();
    }else{
       child();
    }
}

?

?

?

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2021-08-19 12:28:08  更:2021-08-19 12:28:29 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 10:00:24-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码