Linux网络编程【信号】2

举报
xcc-2022 发表于 2022/10/24 20:57:11 2022/10/24
【摘要】 07. 信号产生函数 7.1 kill函数#include <sys/types.h>#include <signal.h>int kill(pid_t pid, int sig);功能:给指定进程发送指定信号(不一定杀死)参数: pid : 取值有 4 种情况 : pid > 0: 将信号传送给进程 ID 为pid的进程。 pid = 0 : 将信号...

07. 信号产生函数

7.1 kill函数

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

int kill(pid_t pid, int sig);
功能:给指定进程发送指定信号(不一定杀死)

参数:
    pid : 取值有 4 种情况 :
        pid > 0:  将信号传送给进程 ID 为pid的进程。
        pid = 0 :  将信号传送给当前进程所在进程组中的所有进程。
        pid = -1 : 将信号传送给系统内所有的进程。
        pid < -1 : 将信号传给指定进程组的所有进程。这个进程组号等于 pid 的绝对值。
    sig : 信号的编号,这里可以填数字编号,也可以填信号的宏定义,可以通过命令 kill - l("l" 为字母)进行相应查看。不推荐直接使用数字,应使用宏名,因为不同操作系统信号编号可能不同,但名称一致。

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

super用户(root)可以发送信号给任意用户,普通用户是不能向系统用户发送信号的。

kill -9 (root用户的pid) 是不可以的。同样,普通用户也不能向其他普通用户发送信号,终止其进程。 只能向自己创建的进程发送信号。

普通用户基本规则是:发送者实际或有效用户ID == 接收者实际或有效用户ID

程序示例:

  pid_t pid = -1;

    //创建子进程
    pid = fork();
    if(pid == -1){perror("fork");return 1;}

    if(pid == 0)
    {
        //子进程
        for(int i=0; i<5; i++)
        {
            printf("chile process do work...\n");
            sleep(1);
        }

        exit(0);//进程的退出
    }
    else
    {
        //父进程
        sleep(3);
        printf("子进程还在运行,该退出了\n");
        kill(pid,15);
        printf("父进程kill子进程完毕!\n");
    }
    return 0;

运行结果:

动画5

如果子进程想自杀,好;kill(getpid(),15);,要是看父进程不爽就kill("getppid()",15);

7.2 raise函数

#include <signal.h>

int raise(int sig);
功能:给当前进程发送指定信号(自己给自己发),等价于 kill(getpid(), sig)
参数:
    sig:信号编号
返回值:
    成功:0
    失败:非0

示例代码:

int i = 1;

    while(1)
    {
        printf("do working  %d\n",i);
        
        //自己给自己发送一个信号
        if(i == 4)
        {
            raise(SIGTERM);//等价于kill(getpid(),15);
        }
        i++;
        sleep(1);
    }

    return 0;

运行结果:

动画6

7.3 abort函数

#include <stdlib.h>

void abort(void);
功能:给自己发送异常终止信号 6) SIGABRT,并产生core文件,等价于kill(getpid(), SIGABRT);

参数:无
返回值:无

image-20220925114637159

动画7

7.4 alarm函数(闹钟)

#include <unistd.h>

unsigned int alarm(unsigned int seconds);
功能:
    设置定时器(闹钟)。在指定seconds后,内核会给当前进程发送14)SIGALRM信号。进程收到该信号,默认动作终止。每个进程都有且只有唯一的一个定时器。
    取消定时器alarm(0),返回旧闹钟余下秒数。
参数:
    seconds:指定的时间,以秒为单位
返回值:
    返回0或剩余的秒数

定时,与进程状态无关(自然定时法)!就绪、运行、挂起(阻塞、暂停)、终止、僵尸……无论进程处于何种状态,alarm都计时。

测试程序:

//测试alarm函数
int main()
{
    unsigned int ret = 0;
    //第一次设置脑中5秒之后就超时,发送对应的信号
    ret = alarm(5);
    printf("上一次闹钟剩下的时间是:%u\n",ret);

    sleep(2);
    //之前没有超时的闹钟被新闹钟覆盖
    ret = alarm(4);
    printf("上一次闹钟剩下的时间是:%u\n",ret);

    printf("按任意键继续...\n");
    getchar();

    return 0;
}

运行结果:

xcc@ubuntu:~/7th$ ./a.out
上一次闹钟剩下的时间是:0
上一次闹钟剩下的时间是:3
按任意键继续…
闹钟
xcc@ubuntu:~/7th$ ./a.out
上一次闹钟剩下的时间是:0

上一次闹钟剩下的时间是:3
按任意键继续…

7.5 setitimer函数(定时器)

#include <sys/time.h>

int setitimer(int which,  const struct itimerval *new_value, struct itimerval *old_value);
功能:
    设置定时器(闹钟)。 可代替alarm函数。精度微秒us,可以实现周期定时。
参数:
    which:指定定时方式
        a) 自然定时:ITIMER_REAL → 14)SIGALRM计算自然时间
        b) 虚拟空间计时(用户空间):ITIMER_VIRTUAL → 26)SIGVTALRM  只计算进程占用cpu的时间
        c) 运行时计时(用户 + 内核):ITIMER_PROF → 27)SIGPROF计算占用cpu及执行系统调用的时间
    new_value:struct itimerval, 负责设定timeout时间
        struct itimerval {
            struct timerval it_interval; // 闹钟触发周期
            struct timerval it_value;    // 闹钟触发时间
        };
        struct timeval {
            long tv_sec;            // 秒
            long tv_usec;           // 微秒
        }
        itimerval.it_value: 设定第一次执行function所延迟的秒数 
        itimerval.it_interval:  设定以后每几秒执行function

    old_value: 存放旧的timeout值,一般指定为NULL
返回值:
    成功:0
    失败:-1

示例代码:

void myfunc(int sig)
{
    printf("捕捉到信号:%d\n",sig);//14
}

int main()
{
    struct itimerval new_value;

    //定时周期
    new_value.it_interval.tv_sec = 1;
    new_value.it_interval.tv_usec = 0;

    //第一次触发的时间
    new_value.it_value.tv_sec = 2;
    new_value.it_value.tv_usec = 0;

    signal(SIGALRM, myfunc); //信号处理
    setitimer(ITIMER_REAL, &new_value, NULL); //定时器设置

    //进程收到闹钟超时信号之后就会终止该进程
    while (1);

    return 0;
}
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。