Linux线程信号(中)

目录

1.信号的保存

自定义捕捉

忽略信号

恢复处理动作

sigset_t

sigprocmask

sigpending

整合demo

1.2.3.


1.信号的保存

信号其他相关常见概念

•实际执行信号的处理动作称为信号递达(Delivery)

递达方式有三种:1.自定义 2.默认 3.忽略

•信号从产生到递达之间的状态,称为信号未决(Pending)。

信号在位图里,还没来得及处理!

•进程可以选择阻塞(Block)某个信号。

•被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作.

阻塞屏蔽信号

•注意,阻塞和忽略是不同的,只要信号被阻塞就不会递达,而忽略是在递达之后可选的⼀种处理动作。

这些概念在内核中的具体表现

三张表

pending--unsigned int pending--保存收到的新号的位图 未决表

未决表 比特位的位置:表示的是第几个信号
比特位的内容:是否收到!

比特位的位置:信号的编号(1-31)

比特位的内容:0 或 1
1:收到了这个信号(信号已产生,但还没被处理)
0:没有收到这个信号


block --unsigned int block---也是位图

阻塞表 比特位的位置:表示的是第几个信号
比特位的内容:是否阻塞!

比特位的位置:信号的编号(1-31)

比特位的内容:0 或 1
1:这个信号被阻塞(暂时不递达)
0:这个信号不被阻塞(可以递达)

pending & (-block) 剩下的结果就是可以直接被递达的


handler --sighandler_t handler31---函数指针数组,数组下标就是信号编号!

处理动作表

数组下标:信号的编号(1-31)

数组元素的值:

SIG_DFL:默认处理

SIG_IGN:忽略信号

用户自定义函数指针

typedef void (*sighandler_t)(int);

sighandler_t signal(int signum, sighandler_t handler);

注册进程,处理信号的方法本质就是修改handler表

三张表合起来共同支撑让进程识别信号

自定义捕捉

testSig.cc

复制代码
#include <iostream>
#include <vector>
#include <functional>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>

void handler(int sig)
{
    std::cout<<"hello sig:"<<sig<<std::endl;
}

int main()
{
    signal(2,handler);//自定义捕捉

    while(true)
    {
        sleep(1);
        std::cout<<"."<<std::endl;
    }
    return 0;
}
忽略信号
复制代码
#include <iostream>
#include <vector>
#include <functional>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>

void handler(int sig)
{
    std::cout<<"hello sig:"<<sig<<std::endl;
}

int main()
{
    //signal(2,handler);//自定义捕捉
    signal(2,SIG_IGN);//忽略信号

    while(true)
    {
        sleep(1);
        std::cout<<"."<<std::endl;
    }
    return 0;
}
恢复处理动作
复制代码
#include <iostream>
#include <vector>
#include <functional>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>

void handler(int sig)
{
    std::cout<<"hello sig:"<<sig<<std::endl;
    signal(2,SIG_DFL);
    std::cout<<"恢复处理动作"<<std::endl;
}

int main()
{
    signal(2,handler);//自定义捕捉
    //signal(2,SIG_IGN);//忽略信号

    while(true)
    {
        sleep(1);
        std::cout<<"."<<std::endl;
    }
    return 0;
}

所谓的SIG_DFL、SIG_IGN也是写成宏了

#define SIG_DFL ((__sighandler_t) 0) /* Default action. */

#define SIG_IGN ((__sighandler_t) 1) /* Ignore signal. */

把0值和1值强转成了这个类型

横着看,对于一号信号来讲,没有block、pending,处理动作是默认

像二号信号,pending位为1收到了二号信号但这个信号没有办法被递达,因为block位置1

三号信号,没有收到三号信号,block为1依旧保持阻塞着

• 每个信号都有两个标志位分别表示阻塞(block)和未决(pending),还有⼀个函数指针表⽰处理动作。信号产生时,内核在进程控制块中设置该信号的未决标志,直到信号递达才清除该标志。在上图的例子中,SIGHUP信号未阻塞也未产生过,当它递达时执行默认处理动作。

• SIGINT信号产生过,但正在被阻塞,所以暂时不能递达。虽然它的处理动作是忽略,但在没有解除阻塞之前不能忽略这个信号,因为进程仍有机会改变处理动作之后再解除阻塞。

• SIGQUIT信号未产生过,⼀旦产生SIGQUIT信号将被阻塞,它的处理动作是用户自定义函数sighandler。

block跟pending两者没有直接的约束关系

验证信号保存的话题:

Linux提供信号操作:

1.一定是围绕着三张表展开!

sigset_t

一个位图的操作类型

每个信号只有⼀个bit的未决标志,非0即1,不记录该信号产生了多少次,阻塞标志也是这样表示的。因此,未决和阻塞标志可以用相同的数据类型sigset_t来存储,sigset_t称为信号集 , 这个类型可以表示每个信号的"有效"或"无效"状态,在阻塞信号集中"有效"和"无效"的含义是该信号是否被阻塞,而在未决信号集中"有效"和"无效"的含义是该信号是否处于未决状态。阻塞信号集也叫做当前进程的信号屏蔽字(Signal Mask),这里的"屏蔽"应该理解为阻塞而不是忽略。

类似权限那里的umask

位图

struct bits

{

int bitmap10;//32*10=320

}

int index=39/32=1----bitmap1

int pos-39%32=7 ---bitmap1第7个比特位

信号集操作函数

#include <signal.h>

int sigemptyset(sigset_t *set); 把一个位图清空

int sigfillset(sigset_t *set); 把位图置1

int sigaddset(sigset_t *set, int signo); 一个信号添加到集合里,这个信号是几就把那个比特位置1

int sigdelset(sigset_t *set, int signo); 删掉,置0

int sigismember(const sigset_t *set, int signo); 判断是否在集合里,判断第几个信号是否为1

sigprocmask

调用这个函数就是用来设置,更新自己的block表

调用函数sigprocmask可以读取或更改进程的信号屏蔽字(阻塞信号集)。

#include <signal.h>

int sigprocmask(int how, const sigset_t *set, sigset_t *oset);

输入型参数 输出型参数

int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

下表说明了how参数的可选值。

|-------------|------------------------------------------------|
| SIG_BLOCK | set包含了我们希望添加到当前信号屏蔽字的信号,相当于mask=mask|set |
| SIG_UNBLOCK | set包含了我们希望从当前信号屏蔽字中解除阻塞的信号,相当于mask=mask&~set |
| SIG_SETMASK | 设置当前信号屏蔽字为set所指向的值,相当于mask=set |

RETURN VALUE

sigprocmask() returns 0 on success and -1 on error. In the event of an error, errno is set to indicate the cause.

返回值:若成功则为0,若出错则为-1

sigprocmask(SIG_SETMASK, &block, &oblock);

模式 含义
SIG_SETMASK 直接覆盖 。把内核的屏蔽字完全替换&block 的内容(你当前用的这个)。
SIG_BLOCK 追加阻塞 。将 &block 里的信号添加到当前的屏蔽字中(不覆盖其他已屏蔽信号)。
SIG_UNBLOCK 解除阻塞 。从当前的屏蔽字中移除 &block 里的信号。

sigpending

获取当前pending信号集

NAME

sigpending, rt_sigpending - examine pending signals

SYNOPSIS

#include <signal.h>

int sigpending(sigset_t *set);

输出型参数

修改pending位图

1.键盘 2.系统调用 3.系统命令 4.硬件异常 5.软件条件

整合demo

sigismember

int sigemptyset(sigset_t *set);//清空位图结构

int sigfillset(sigset_t *set);

int sigaddset(sigset_t *set, int signum);

int sigdelset(sigset_t *set, int signum);

int sigismember(const sigset_t *set, int signum);

复制代码
#include <iostream>
#include <vector>
#include <functional>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>

int main()
{
    //1.屏蔽2号信号
    sigset_t block;
    sigemptyset(&block);//清空位图

    sigaddset(&block,SIGINT);//将2号的SIGINT添加到block里
                             // 那么当前已经对2号信号进行屏蔽了吗?没有!
                             //这个sigset_t类型是在栈上开辟的,将SIGINT添加到block就只是把这个类型中的比特位置1了。
                             //并没有设到当前进程的block表里
}

必须使用 sigprocmask 系统调用

sigprocmask(SIG_SETMASK, &block, &oblock);

block 里的信号列表,直接覆盖为当前进程要屏蔽的信号列表,同时把旧的屏蔽列表保存到 oblock

1.
复制代码
#include <iostream>
#include <cstdio>
#include <vector>
#include <functional>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>

void PrintPending(sigset_t &pending)
{
    printf("我是一个进程(%d),pending:", getpid());
    for (int signo = 31; signo >= 1; signo--)
    {
        if (sigismember(&pending, signo))
        {
            std::cout << "1";
        }
        else
        {
            std::cout << "0";
        }
    }
    std::cout << std::endl;
}

int main()
{
    // 1.屏蔽2号信号
    sigset_t block, oblock;
    sigemptyset(&block);  // 清空位图
    sigemptyset(&oblock); // 清空位图

    sigaddset(&block, SIGINT); // 将2号的SIGINT添加到block里
                               //  那么当前已经对2号信号进行屏蔽了吗?没有!
                               // 这个sigset_t类型是在栈上开辟的,将SIGINT添加到block就只是把这个类型中的比特位置1了。
                               // 并没有设到当前进程的block表里
        
    int n = sigprocmask(SIG_SETMASK, &block, &oblock);
    (void)n;

    // 4.重复获取打印过程
    while (true)
    {
        // 2.获取pending信号集合
        sigset_t pending;
        int m = sigpending(&pending);

        // 3.打印
        PrintPending(pending);

        sleep(1);
    }

    return 0;
}

终端1

复制代码
root@iZ5waahoxw3q2bZ:~/linux-learning/linux/26-6-18.2# ./testsig
我是一个进程(123099),pending:0000000000000000000000000000000
我是一个进程(123099),pending:0000000000000000000000000000000
我是一个进程(123099),pending:0000000000000000000000000000000
我是一个进程(123099),pending:0000000000000000000000000000000
我是一个进程(123099),pending:0000000000000000000000000000000
我是一个进程(123099),pending:0000000000000000000000000000000
我是一个进程(123099),pending:0000000000000000000000000000000
我是一个进程(123099),pending:0000000000000000000000000000010
我是一个进程(123099),pending:0000000000000000000000000000010
^C我是一个进程(123099),pending:0000000000000000000000000000010
我是一个进程(123099),pending:0000000000000000000000000000010
^\Quit

终端2

复制代码
root@iZ5waahoxw3q2bZ:~/linux-learning/linux/26-6-18.2# kill -2 123099
2.

testSig.cc

复制代码
#include <iostream>
#include <cstdio>
#include <vector>
#include <functional>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>

void PrintPending(sigset_t &pending)
{
    printf("我是一个进程(%d),pending:", getpid());
    for (int signo = 31; signo >= 1; signo--)
    {
        if (sigismember(&pending, signo))
        {
            std::cout << "1";
        }
        else
        {
            std::cout << "0";
        }
    }
    std::cout << std::endl;
}

int main()
{
    // 1.屏蔽2号信号
    sigset_t block, oblock;
    sigemptyset(&block);  // 清空位图
    sigemptyset(&oblock); // 清空位图

    //sigaddset(&block, SIGINT); // 将2号的SIGINT添加到block里
                               //  那么当前已经对2号信号进行屏蔽了吗?没有!
                               // 这个sigset_t类型是在栈上开辟的,将SIGINT添加到block就只是把这个类型中的比特位置1了。
                               // 并没有设到当前进程的block表里
    for(int i = 1; i<32;i++)
        sigaddset(&block,i);
        
    int n = sigprocmask(SIG_SETMASK, &block, &oblock);
    (void)n;

    // 4.重复获取打印过程
    while (true)
    {
        // 2.获取pending信号集合
        sigset_t pending;
        int m = sigpending(&pending);

        // 3.打印
        PrintPending(pending);

        sleep(1);
    }

    return 0;
}

终端1

复制代码
root@iZ5waahoxw3q2bZ:~/linux-learning/linux/26-6-18.2# ./testsig
我是一个进程(122914),pending:0000000000000000000000000000000
我是一个进程(122914),pending:0000000000000000000000000000000
我是一个进程(122914),pending:0000000000000000000000000000000
我是一个进程(122914),pending:0000000000000000000000000000000
我是一个进程(122914),pending:0000000000000000000000000000000
我是一个进程(122914),pending:0000000000000000000000000000000
我是一个进程(122914),pending:0000000000000000000000000000010
我是一个进程(122914),pending:0000000000000000000000000000010
我是一个进程(122914),pending:0000000000000000000000000000010
我是一个进程(122914),pending:0000000000000000000000000000011
我是一个进程(122914),pending:0000000000000000000000000000011
我是一个进程(122914),pending:0000000000000000000000000000011
我是一个进程(122914),pending:0000000000000000000000000000011
我是一个进程(122914),pending:0000000000000000000000000000011
我是一个进程(122914),pending:0000000000000000000000000000011
我是一个进程(122914),pending:0000000000000000000000000000011
我是一个进程(122914),pending:0000000000000000000000010000011
我是一个进程(122914),pending:0000000000000000000000010000011
我是一个进程(122914),pending:0000000000000000000000010000011
我是一个进程(122914),pending:0000000000000000000000010000011
Killed

终端2

复制代码
root@iZ5waahoxw3q2bZ:~/linux-learning/linux/26-6-18.2# kill -2 122914
root@iZ5waahoxw3q2bZ:~/linux-learning/linux/26-6-18.2# kill -1 122914
root@iZ5waahoxw3q2bZ:~/linux-learning/linux/26-6-18.2# kill -8 122914
root@iZ5waahoxw3q2bZ:~/linux-learning/linux/26-6-18.2# kill -9 122914

9号、19号信号,不可被捕捉,不可被阻塞

3.

想看到pending位再由1变为0,加一个计数器

复制代码
#include <iostream>
#include <cstdio>
#include <vector>
#include <functional>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>

void PrintPending(sigset_t &pending)
{
    printf("我是一个进程(%d),pending:", getpid());
    for (int signo = 31; signo >= 1; signo--)
    {
        if (sigismember(&pending, signo))
        {
            std::cout << "1";
        }
        else
        {
            std::cout << "0";
        }
    }
    std::cout << std::endl;
}

int main()
{
    // 1.屏蔽2号信号
    sigset_t block, oblock;
    sigemptyset(&block);  // 清空位图
    sigemptyset(&oblock); // 清空位图

    sigaddset(&block, SIGINT); // 将2号的SIGINT添加到block里
                               //  那么当前已经对2号信号进行屏蔽了吗?没有!
                               // 这个sigset_t类型是在栈上开辟的,将SIGINT添加到block就只是把这个类型中的比特位置1了。
                               // 并没有设到当前进程的block表里
    // for(int i = 1; i<32;i++)
    //     sigaddset(&block,i);
        
    int n = sigprocmask(SIG_SETMASK, &block, &oblock);
    (void)n;

    // 4.重复获取打印过程
    int cnt = 0;
    while (true)
    {
        // 2.获取pending信号集合
        sigset_t pending;
        int m = sigpending(&pending);

        // 3.打印
        PrintPending(pending);
        if(cnt == 10)
        {
            //5.恢复对2号信号的block情况
            sigprocmask(SIG_SETMASK, &oblock,nullptr);
            std::cout<< "解除对2号的屏蔽"<<std::endl;
        }

        sleep(1);
        cnt++;
    }

    return 0;
}

root@iZ5waahoxw3q2bZ:~/linux-learning/linux/26-6-18.2# ./testsig
我是一个进程(123367),pending:0000000000000000000000000000000
我是一个进程(123367),pending:0000000000000000000000000000000
我是一个进程(123367),pending:0000000000000000000000000000000
^C我是一个进程(123367),pending:0000000000000000000000000000010
我是一个进程(123367),pending:0000000000000000000000000000010
我是一个进程(123367),pending:0000000000000000000000000000010
我是一个进程(123367),pending:0000000000000000000000000000010
我是一个进程(123367),pending:0000000000000000000000000000010
我是一个进程(123367),pending:0000000000000000000000000000010
我是一个进程(123367),pending:0000000000000000000000000000010
我是一个进程(123367),pending:0000000000000000000000000000010

root@iZ5waahoxw3q2bZ:~/linux-learning/linux/26-6-18.2# 

我们当前对2号是屏蔽的,对2号信号的默认动作是终止进程。当解除屏蔽,2号动作就立即被递达。

对2号信号做一下自定义捕捉

复制代码
#include <iostream>
#include <cstdio>
#include <vector>
#include <functional>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>

void PrintPending(sigset_t &pending)
{
    printf("我是一个进程(%d),pending:", getpid());
    for (int signo = 31; signo >= 1; signo--)
    {
        if (sigismember(&pending, signo))
        {
            std::cout << "1";
        }
        else
        {
            std::cout << "0";
        }
    }
    std::cout << std::endl;
}

void handler(int sig)
{
    std::cout<<"递达"<<sig<<"信号!"<<std::endl;
}

int main()
{
    signal(SIGINT,handler);
    // 1.屏蔽2号信号
    sigset_t block, oblock;
    sigemptyset(&block);  // 清空位图
    sigemptyset(&oblock); // 清空位图

    sigaddset(&block, SIGINT); // 将2号的SIGINT添加到block里
                               //  那么当前已经对2号信号进行屏蔽了吗?没有!
                               // 这个sigset_t类型是在栈上开辟的,将SIGINT添加到block就只是把这个类型中的比特位置1了。
                               // 并没有设到当前进程的block表里
    // for(int i = 1; i<32;i++)
    //     sigaddset(&block,i);
        
    int n = sigprocmask(SIG_SETMASK, &block, &oblock);
    (void)n;

    // 4.重复获取打印过程
    int cnt = 0;
    while (true)
    {
        // 2.获取pending信号集合
        sigset_t pending;
        int m = sigpending(&pending);

        // 3.打印
        PrintPending(pending);
        if(cnt == 10)
        {
            //5.恢复对2号信号的block情况
            std::cout<< "解除对2号的屏蔽"<<std::endl;
            sigprocmask(SIG_SETMASK, &oblock,nullptr);
        }

        sleep(1);
        cnt++;
    }

    return 0;
}

root@iZ5waahoxw3q2bZ:~/linux-learning/linux/26-6-18.2# ./testsig
我是一个进程(123526),pending:0000000000000000000000000000000
我是一个进程(123526),pending:0000000000000000000000000000000
我是一个进程(123526),pending:0000000000000000000000000000000
^C我是一个进程(123526),pending:0000000000000000000000000000010
我是一个进程(123526),pending:0000000000000000000000000000010
我是一个进程(123526),pending:0000000000000000000000000000010
我是一个进程(123526),pending:0000000000000000000000000000010
我是一个进程(123526),pending:0000000000000000000000000000010
我是一个进程(123526),pending:0000000000000000000000000000010
我是一个进程(123526),pending:0000000000000000000000000000010
我是一个进程(123526),pending:0000000000000000000000000000010
递达2信号!
解除对2号的屏蔽
我是一个进程(123526),pending:0000000000000000000000000000000
我是一个进程(123526),pending:0000000000000000000000000000000
我是一个进程(123526),pending:0000000000000000000000000000000
^C递达2信号!
我是一个进程(123526),pending:0000000000000000000000000000000
我是一个进程(123526),pending:0000000000000000000000000000000
我是一个进程(123526),pending:0000000000000000000000000000000
我是一个进程(123526),pending:0000000000000000000000000000000
^\Quit

一旦开始执行对pending的捕捉了,pending表中的1是在执行之前恢复为0还是在处理完了再恢复为0

复制代码
#include <iostream>
#include <cstdio>
#include <vector>
#include <functional>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>

void PrintPending(sigset_t &pending)
{
    printf("我是一个进程(%d),pending:", getpid());
    for (int signo = 31; signo >= 1; signo--)
    {
        if (sigismember(&pending, signo))
        {
            std::cout << "1";
        }
        else
        {
            std::cout << "0";
        }
    }
    std::cout << std::endl;
}

void handler(int sig)
{
    std::cout<<"#########################"<<std::endl;
    std::cout << "递达" << sig << "信号!" << std::endl;
    sigset_t pending;
    int m = sigpending(&pending);
    PrintPending(pending);//如果是0000 0010(处理完,2号才会被设置为0),如果是0000 0000(执行handler方法之前,2对应的pending已经被清理了)
    std::cout<<"#########################"<<std::endl;
}

int main()
{
    signal(SIGINT, handler);
    // 1.屏蔽2号信号
    sigset_t block, oblock;
    sigemptyset(&block);  // 清空位图
    sigemptyset(&oblock); // 清空位图

    sigaddset(&block, SIGINT); // 将2号的SIGINT添加到block里
                               //  那么当前已经对2号信号进行屏蔽了吗?没有!
                               // 这个sigset_t类型是在栈上开辟的,将SIGINT添加到block就只是把这个类型中的比特位置1了。
                               // 并没有设到当前进程的block表里
    // for(int i = 1; i<32;i++)
    //     sigaddset(&block,i);

    int n = sigprocmask(SIG_SETMASK, &block, &oblock);
    (void)n;

    // 4.重复获取打印过程
    int cnt = 0;
    while (true)
    {
        // 2.获取pending信号集合
        sigset_t pending;
        int m = sigpending(&pending);

        // 3.打印
        PrintPending(pending);
        if (cnt == 10)
        {
            // 5.恢复对2号信号的block情况
            std::cout << "解除对2号的屏蔽" << std::endl;
            sigprocmask(SIG_SETMASK, &oblock, nullptr);
        }

        sleep(1);
        cnt++;
    }

    return 0;
}

root@iZ5waahoxw3q2bZ:~/linux-learning/linux/26-6-18.2# ./testsig
我是一个进程(123729),pending:0000000000000000000000000000000
我是一个进程(123729),pending:0000000000000000000000000000000
我是一个进程(123729),pending:0000000000000000000000000000000
我是一个进程(123729),pending:0000000000000000000000000000000
我是一个进程(123729),pending:0000000000000000000000000000000
^C我是一个进程(123729),pending:0000000000000000000000000000010
我是一个进程(123729),pending:0000000000000000000000000000010
我是一个进程(123729),pending:0000000000000000000000000000010
我是一个进程(123729),pending:0000000000000000000000000000010
我是一个进程(123729),pending:0000000000000000000000000000010
我是一个进程(123729),pending:0000000000000000000000000000010
解除对2号的屏蔽
#########################
递达2信号!
我是一个进程(123729),pending:0000000000000000000000000000000
#########################
我是一个进程(123729),pending:0000000000000000000000000000000
我是一个进程(123729),pending:0000000000000000000000000000000
我是一个进程(123729),pending:0000000000000000000000000000000
我是一个进程(123729),pending:0000000000000000000000000000000
我是一个进程(123729),pending:0000000000000000000000000000000
^C#########################
递达2信号!
我是一个进程(123729),pending:0000000000000000000000000000000
#########################
我是一个进程(123729),pending:0000000000000000000000000000000
我是一个进程(123729),pending:0000000000000000000000000000000
^\Quit

当我们准备递达的时候,要首先清空pending信号集中对应的信号位图 1->0


细节1:

如果在进程解除对某信号的阻塞之前这种信号产生过多次,将如何处理?POSIX.1允许系统递送该信

号⼀次或多次。Linux是这样实现的:常规信号在递达之前产生多次只计⼀次,而实时信号在递达之前产生多次可以依次放在⼀个队列里。

细节2:Core Term

Core 核心

会在当前路径下形成一个文件,进程异常退出的时候。进程在内存中的核心数据,从内存拷贝到磁盘,形成一个文件--这种机制叫做核心转储 ---**支持debug调试,**然后进程退出

Term不做任何转储功能直接退出

为什么没见到过Core的?

云服务器上,core dump功能是被禁止掉的!

为什么禁止掉了?

磁盘空间耗尽:core 文件通常很大(与进程占用内存相当)

敏感信息泄露等

testSig.cc

复制代码
#include <iostream>

int main()
{
    printf("hello world!\n");
    printf("hello world!\n");
    printf("hello world!\n");
    printf("hello world!\n");
    int a = 10;
    a /= 0;
    printf("hello world!\n");
    printf("hello world!\n");
    printf("hello world!\n");
    printf("hello world!\n");
}

root@iZ5waahoxw3q2bZ:~/linux-learning/linux/26-6-18.3# ./testsig
hello world!
hello world!
hello world!
hello world!
Floating point exception

如何查看?如何临时打开?

复制代码
root@iZ5waahoxw3q2bZ:~/linux-learning/linux/26-6-18.3# ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 7226
max locked memory       (kbytes, -l) 65536
max memory size         (kbytes, -m) unlimited
open files                      (-n) 65535
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 7226
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

可以看到core file size为0,可以知道这个是被关掉的

打开

复制代码
root@iZ5waahoxw3q2bZ:~/linux-learning/linux/26-6-18.3# ulimit -c 40960
root@iZ5waahoxw3q2bZ:~/linux-learning/linux/26-6-18.3# ulimit -a
core file size          (blocks, -c) 40960
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 7226
max locked memory       (kbytes, -l) 65536
max memory size         (kbytes, -m) unlimited
open files                      (-n) 65535
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 7226
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

root@iZ5waahoxw3q2bZ:~/linux-learning/linux/26-6-18.3# ./testsig
hello world!
hello world!
hello world!
hello world!
Floating point exception (core dumped)

会发现多一个core文件

为什么会核心转储??

支持debug
开启core dump,直接运行崩溃,gdb,core-file core,直接帮助我们定位到出错行---事后调试!

低7位表示退出时的退出信号,signal = 0表示正常退出

低8位还有一个标志位是core dump标志,是否core dump

复制代码
root@iZ5waahoxw3q2bZ:~/linux-learning/linux/26-6-18.4# ulimit -c 40960
root@iZ5waahoxw3q2bZ:~/linux-learning/linux/26-6-18.4# ulimit -a
core file size          (blocks, -c) 40960
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 7226
max locked memory       (kbytes, -l) 65536
max memory size         (kbytes, -m) unlimited
open files                      (-n) 65535
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 7226
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited
root@iZ5waahoxw3q2bZ:~/linux-learning/linux/26-6-18.4# make
make: 'testsig' is up to date.
root@iZ5waahoxw3q2bZ:~/linux-learning/linux/26-6-18.4# ./testsig
hello world!
hello world!
hello world!
hello world!
signal:8,exit code:0,core dump:1
root@iZ5waahoxw3q2bZ:~/linux-learning/linux/26-6-18.4# ll
total 268
drwxr-xr-x  2 root root   4096 Jun 18 18:43 ./
drwxr-xr-x 43 root root   4096 Jun 18 17:23 ../
-rw-------  1 root root 499712 Jun 18 18:43 core
-rw-r--r--  1 root root     78 Jun 18 17:23 Makefile
-rwxr-xr-x  1 root root  17408 Jun 18 18:41 testsig*
-rw-r--r--  1 root root    731 Jun 18 18:41 testSig.cc

感谢你的观看,期待我们下次再见!