Linux:信号及信号捕捉

kill、raise、abort函数

在这里插入图片描述
在这里插入图片描述

#include <stdio.h>
#include <string.h>

int main(){

    char *buf;

    strcpy(buf, "hello");


    return 0;
}
carey@ubuntu:~/Linux/lesson17_sig$ gcc core.c -g
carey@ubuntu:~/Linux/lesson17_sig$ ls
a.out  core.c
carey@ubuntu:~/Linux/lesson17_sig$ gdb a.out 
GNU gdb (Ubuntu 8.1-0ubuntu3.2) 8.1.0.20180409-git
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from a.out...done.
(gdb) start
Temporary breakpoint 1 at 0x5fe: file core.c, line 8.
Starting program: /home/carey/Linux/lesson17_sig/a.out 

Temporary breakpoint 1, main () at core.c:8
8	    strcpy(buf, "hello");
(gdb) s

//接收到信号
Program received signal SIGSEGV, Segmentation fault.
0x0000555555554602 in main () at core.c:8
8	    strcpy(buf, "hello");
(gdb) 

在这里插入图片描述

/*
#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);
    -功能:给某个进程pid发送某个信号sig
    -参数:
        -pid:进程id
            >0 : 将信号发送给指定进程
            =0 :将信号发型给当前的进程组
            <0 : 将信号发送给每一个有权限接收这个信号的进程
            <-1 : 这个pid=某个进程组的ID取反

        -sig:信号(宏或者编号)
            0 :不发送任何信号
    eg:
        kill(getppid(), 9);//给当前进程的父进程发送9号信号


NAME:
    raise - send a signal to the caller

SYNOPSIS:
    #include <signal.h>
    int raise(int sig);

    -功能:给当前进程发送信号
    -参数:
        -sig: 信号
    -返回值:
        0:成功
        -1: 非0
    等价于:kill(getpid, sig);
    

void abort(void);
    -功能:发送SIGABRT信号给当前的进程,杀死当前进程
    等价于:kill(getpid(),SIGABRT);

*/

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>

int main(){

    int pid = fork();

    if(pid > 0){
        //P
        printf("P\n");
        sleep(2);
        printf("kill C process\n");
        kill(pid, 9);


    }else if(pid == 0){
        //C
        for(int i=1; i<=15; i++){
            printf("C %d\n",i);
            sleep(1);
        }

    }else{
        perror("fork");
        return -1;
    }


    return 0;
}
carey@ubuntu:~/Linux/lesson17_sig$ gcc kill.c -o k
carey@ubuntu:~/Linux/lesson17_sig$ ./k
P
C 1
C 2
kill C process
carey@ubuntu:~/Linux/lesson17_sig$ ./k
P
C 1
C 2
kill C process
//运气不错,第三次就看到这个了 这是正常的 因为在第二秒的时候子进程抢到了时间片又执行了一擦
carey@ubuntu:~/Linux/lesson17_sig$ ./k
P
C 1
C 2
kill C process
C 3

alarm()

定时器与进程的状态无关(自然定时法),不管进程处于什么状态,alarm都会计时。

/*
#include <unistd.h>
unsigned int alarm(unsigned int seconds);
    功能:设置定时器(闹钟)。函数调用,开始倒计时,当倒计时为0的时候,函数会给当前的进程发送一个信号:SIGALARM

    参数:
        -seconds: 倒计时时长,0表示定时器无效。
            可以通过alarm(0)取消定时器
    返回值:
        -之前没有定时器: 返回0
        -之前有定时器: 返回之前的定时器剩余的时间

    -SIGALARM:默认终止当前进程,每一个进程都有且仅有一个计时器。
        alarm(10); 
        一秒后:返回0
        alarm(5);//返回9
*/

#include <stdio.h>
#include <unistd.h>

int main(){

    int sec = alarm(10);

    printf("sec = %d\n", sec);

    sleep(2);
    
    for(int i=1; i<6; i++){
        printf("j = %d \n", i);
        sleep(1);
    }

    sec = alarm(10);
    printf("sec = %d\n", sec);

    for(int i=1; i<100; i++){
        printf("i = %d \n", i);
        sleep(1);
    }

    return 0;
}
//第一个闹钟设置5
carey@ubuntu:~/Linux/lesson17_sig$ ./ala 
sec = 0
j = 1 
j = 2 
j = 3 
Alarm clock
carey@ubuntu:~/Linux/lesson17_sig$ gcc alarm.c -o ala

//第一个闹钟设置10
carey@ubuntu:~/Linux/lesson17_sig$ gcc alarm.c -o ala
carey@ubuntu:~/Linux/lesson17_sig$ ./ala 
sec = 0
j = 1 
j = 2 
j = 3 
j = 4 
j = 5 
sec = 3
i = 1 
i = 2 
i = 3 
i = 4 
i = 5 
i = 6 
i = 7 
i = 8 
i = 9 
i = 10 
Alarm clock


小例子

#include <stdio.h>
#include <unistd.h>

//1秒钟计算机能数多少个数
/*
实际的时间=内核时间+用户时间+消耗的时间
进行文件IO操作的时候比较浪费时间
*/

int main(){
    alarm(1);
    
    int i=1;
    while(1){
        i++;
        printf("i = %d \n", i);
    }
    
}
//可以用重定向查看 
gcc _.c -o a
./a >> a.txt

setitimer函数

在这里插入图片描述

/*
#include <sys/time.h>
int setitimer(int which, const struct itimerval *new_value,struct itimerval *old_value);
    功能:设置计时器(闹钟),可以替代alarm,而且精确性更高(us).并且可以定义周期性的闹钟。
    参数:
        -which:定时器以什么时间定时
            -ITIMER_REAL:真实时间,时间到达发送 SIGALRM信号。 常用
            -ITIMER_VIRTUAL: 用户时间, 用户到达发送SIGVTALRM信号。
            -ITIMER_PROF: 以该进程在用户态和内核态下所消耗的时间来计算,时间到达发送SIGPROF信号
        -new_value:设置定时器的属性
            Timer values are defined by the following structures:

           struct itimerval {//定时器
               struct timeval it_interval; // Interval for periodic timer 间隔时间
               struct timeval it_value;    // Time until next expiration  延迟时间
           };

           struct timeval { //时间
               time_t      tv_sec;         // seconds 
               suseconds_t tv_usec;        // microseconds 
           };

        -old_value:记录上一次定时的时间的参数,一般不使用,NULL

    返回值:
        -成功: 0
        -失败: -1 并设置错误号


*/
#include <stdio.h>
#include <sys/time.h>

//五秒后每隔三秒定时
 int main(){

    struct itimerval new_value;
    
    //设置间隔时间
    new_value.it_interval.tv_sec = 3;//间隔时间
    new_value.it_interval.tv_usec = 0;

    //设置延迟时间
    new_value.it_value.tv_sec = 5;//第一次定时也会发送信号
    new_value.it_value.tv_usec = 0;



    int ret = setitimer(ITIMER_REAL, &new_value, NULL);//非阻塞

    if(ret == -1){
        perror("setitimer");
        return -1;
    }

    int i = 1;
    while(1){
        printf("i = %d \n", i++);
        sleep(1);
    }

     return 0;
 }

在这里插入图片描述

/*
#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
-功能:设置某个信号的捕捉行为
-参数:
    -signum:要捕捉的信号
    -handler:如何处理
        -SIG_IGN:忽略信号
        -SIG_DFL:使用默认的信号,无作为
        -回调函数:内核调用

    -返回值:
        -成功:返回上一次注册信号处理的地址,第一次调用返回NULL
        -失败:返回SIG_ERR,设置错误号

SIGKILL 和 SIGSTOP 不能被捕捉和hulue

*/

//上一个代码改进

#include <stdio.h>
#include <sys/time.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>


void myalarm(int num){
    printf("捕捉到了信号:%d \n", num);
    printf("*************\n");
}


//3秒后每隔2秒定时
 int main(){

    //注册捕捉信号
    //signal(SIGALRM, SIG_IGN);//捕捉之后忽略信号
    //signal(SIGALRM, SIG_DFL);//捕捉不作处理,只是捕捉了一下
    signal(SIGALRM, myalarm);



    struct itimerval new_value;
    
    //设置间隔时间
    new_value.it_interval.tv_sec = 2;//间隔时间
    new_value.it_interval.tv_usec = 0;

    //设置延迟时间
    new_value.it_value.tv_sec = 3;//第一次定时也会发送信号
    new_value.it_value.tv_usec = 0;



    int ret = setitimer(ITIMER_REAL, &new_value, NULL);//非阻塞

    if(ret == -1){
        perror("setitimer");
        return -1;
    }

    int i = 1;
    while(1){

        printf("i = %d \n", i++);
        sleep(1);
    }

     return 0;
 }
carey@ubuntu:~/Linux/lesson17_sig$ ./signal 
i = 1 
i = 2 
i = 3 
捕捉到了信号:14 
*************
i = 4 
i = 5 
捕捉到了信号:14 
*************
i = 6 
i = 7 
捕捉到了信号:14 
*************
i = 8 
i = 9 
捕捉到了信号:14 
*************
i = 10 
i = 11 
捕捉到了信号:14 
*************

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值