ipc通信二——信号

进程间通信:信号

信号是进程间通信一种方式,这个种方式没有传输数据。只是在内核中传一个信号(整数),信号的表示是一个整数,不同信号值,代表不同含义,当然用户可以自定义信号,以及自定义信号的含义解释权 归用户所有。

一些信号举例:

Signal Value Action Comment
──────────────────────────────────────────────────────────────────────
SIGHUP 1 Term Hangup detected on controlling terminalor death of
controlling process
/*
控制终端的挂起操作,或者是控制进程死亡时,控制终端上的所有
进程都会收到SIGHUP信号
*/
SIGINT 2 Term Interrupt from keyboard
/*
从键盘接收一个中断信号,如:ctrl + c
*/
SIGQUIT 3 Core Quit from keyboard
/*
Core:输出信息,然后中止
如:
ctrl + z
ctrl + d
*/
SIGILL 4 Core Illegal Instruction
/*
非法指令
*/
SIGABRT 6 Core Abort signal from abort(3)
/*
调用abort函数时候,进程会收到SIGABRT这个信号。
*/
SIGFPE 8 Core Floating-point exception
/*
浮点运算异常的时候,产生SIGFPE信号
*/
SIGKILL 9 Term Kill signal
/*
杀死信号,中止
*/
SIGSEGV 11 Core Invalid memory reference
/*
非法内存引用的时候,会收到SIGSEGV信号
*/
SIGPIPE 13 Term Broken pipe: write to pipe with noreaders; see
pipe(7)
/*
当往一个管道中写入数据的时候,没有读端进程的时候就会产生
SIGPIPE信号
*/
SIGALRM 14 Term Timer signal from alarm(2)
/*
定时信号,进程在调用alarm的时候,会在超时的时候产生
SIGALRM信号
*/
SIGTERM 15 Term Termination signal
SIGUSR1 30,10,16 Term User-defined signal 1
/*
用户自定义信号1
*/
SIGUSR2 31,12,17 Term User-defined signal 2
/*
用户自定义信号2
*/
SIGCHLD 20,17,18 Ign Child stopped or terminated
/*
当子进程停止或者中止的时候,父进程会收到SIGCHLD信号。
*/
SIGCONT 19,18,25 Cont Continue if stopped
SIGSTOP 17,19,23 Stop Stop process
SIGTSTP 18,20,24 Stop Stop typed at terminal
SIGTTIN 21,21,26 Stop Terminal input for background process
SIGTTOU 22,22,27 Stop Terminal output for background process

进程在收到一个信号的时候,通常会有三种处理方式:
捕捉信号:
把一个信号 与 用户自定义的信号处理函数关联起来
那么在收到该信号的时候,就会自动调用该函数处理
默认行为:
收到一个信号的时候,采用操作系统默认的行为
大部分信号的默认行为,是会直接干掉进程。
只有一个信号 SIGCHLD 是被忽略的。
忽略该信号

信号的处理过程

通过 “ 软件中断/软中断 ” 来实现,信号处理函数起始在 “ 中断上下文 ” 执行,信号处理函数----->" 软中 断函数 "
进程上下文: 进程在大环境下 , “ 时间片轮转 ” 一个进程的执行状态又分为:
用户态:执行用户自己的代码的时候
内核态:进入操作系统执行内核代码的时候 在状态切换的时候,要保存用户自己代码的运行到的位置,保存的这个玩意就是上下文

# linux下信号相关的API

发送信号

KILL(2) Linux Programmer's
Manual KILL(2)
NAME
kill - send signal to a process
SYNOPSIS
#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);
/*
@描述:
给指定的进程发送一个指定的信号
@pid:
指定信号接收者(可能是多个进程)
pid > 0 :pid 表示接收者进程 一对一发送
pid = 0 :发送信号给与调用者同组的所有进程 一对同组多个
pid =-1 :发送信号给所有进程(有权限发送的所有进程) 一对所有
pid <-1 :发送信号给组id等于pid绝对值的所有进程。 一对指定组多个
@sig:
要发送的信号
@return:
成功返回0,(表示至少有一个进程成功接收到了信号)
失败返回-1,同时errno被设置
*/

设置闹钟信号

#include <unistd.h>
unsigned int alarm(unsigned int seconds);
/*
作用:
设置一个闹钟信号,在多少秒之后发送一个闹钟信号
@seconds:
多少秒之后,发送一个闹钟信号
@return:
返回上一个闹钟的剩余秒数
如:
alarm(5);
int r = alarm(10); // 10秒之后接收一个 闹钟信号
// 前面的闹钟会被替换/取消 r就是表示上一个闹钟的剩余秒数
....
alarm(0); // 取消闹钟
*/

alarm :定时发送一个闹钟信号给本进程,“ 闹钟 ” 每一个进程都有一个属于自己的 “ 闹钟 ”。闹钟的时间到了,进程就会收到一个 SIGALRM 的信号,但是同一时刻一个进程只有一个 “ 闹钟 ”生效。
大部分的信号的默认行为,是把收到信号的进程Kill掉。
那么如果要改变接收到信号之后的行为:捕获信号。

捕获信号

#include <signal.h>
typedef void (*sighandler_t)(int);
/*
类型重定义语句
将指向一个无返回值,带有一个int类型参数的函数指针类型重定义成新类型,类型名为:
sighandler_t
*/
sighandler_t signal(int signum, sighandler_t handler);
/*
作用:
捕获一个信号,执行用户自定义的处理函数
等待信号
pause:让进程停在那里等待一个信号的到来
@signum:
要捕获那个信号值
@handler:
信号的处理方式,(用户捕获到那个信号之后,应该要执行的函数)
1)自定义函数
void my_handler_function(int sig)
{
// 写你想干的事情
}
2)SIG_IGN
忽略该信号
3)SIG_DEL:default
采用系统默认的处理方式
@return:
成功返回该信号的上一次处理方式(函数指针)
失败返回SIG_ERR,同时errno被设置
*/

等待信号

#include <unistd.h>
int pause(void);
/*
作用:
等待一个信号的到来
@return:
成功返回信号标号,失败返回-1。
*/

代码示例

#include <iostream>
#include <fstream>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <cstdlib>

// 全局变量用于计数子进程数
int child_count = 0;
int alarm_count = 0;

void alarm_handler(int signum) {
    // 创建子进程
    pid_t pid = fork();

    if (pid < 0) {
        std::cerr << "创建子进程失败。" << std::endl;
        exit(1);
    }
    else if (pid == 0) {
        // 子进程中打开文件并写入当前子进程数
        std::ofstream outfile("child_count.txt", std::ios::app);
        if (!outfile) {
            std::cerr << "无法打开文件。" << std::endl;
            exit(1);
        }
        outfile << "子进程编号: " << ++child_count << std::endl;
        outfile.close();

        // 当子进程数达到100时结束程序
        if (child_count >= 100) {
            exit(0);
        }
        exit(0);  // 子进程结束
    } 
    else {
        // 在父进程中,等待子进程结束
        wait(NULL);
        
        // 增加发送的信号计数
        alarm_count++;
        if (alarm_count >= 100) {
            // 如果发送的信号数量达到100,取消闹钟定时器
            alarm(0);
        }
    }
}

int main() {
    // 设置闹钟信号处理函数
    signal(SIGALRM, alarm_handler);

    // 设置闹钟定时器,每隔1秒发送一次SIGALRM信号
        alarm(1);


    // 等待信号处理函数运行
    while (1) {
        sleep(1);  // 主进程等待信号处理
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值