linux signal函数_Linux系统编程:信号 (二)

    上一节,我们讨论了信号的基本概念,信号的机制,与信号相关的事件与状态以及信号的四要素。那么有关信号还有一些基础知识需要学习,我们一起来看一下吧。主要包括信号的产生,信号集相关的函数,信号的捕捉,信号的传参等。

e565bd5745a46bdb8a4dfcf9001c7417.png

1 信号的产生

终端按键产生信号

    Ctrl + c → 2) SIGINT(终止/中断)   "INT"----Interrupt

    Ctrl + z → 20) SIGTSTP(暂停/停止)  "T" ----Terminal 终端。

    Ctrl + \ → 3) SIGQUIT(退出)

硬件异常产生信号

    除0操作   → 8) SIGFPE (浮点数例外)       "F" -----float 浮点数。

    非法访问内存  → 11) SIGSEGV (段错误)

    总线错误  → 7) SIGBUS      

kill函数/命令产生信号

kill命令产生信号:kill -SIGKILLpid

kill函数:给指定进程发送指定信号(不一定杀死)

    int kill(pid_t pid, int sig);   成功:0;失败:-1 (ID非法,信号非法,普通用户杀init进程等权级问题),设置errno

    sig:不推荐直接使用数字,应使用宏名,因为不同操作系统信号编号可能不同,但名称一致。

    pid > 0: 发送信号给指定的进程。

         pid = 0:  发送信号给 与调用kill函数进程属于同一进程组的所有进程。

         pid < 0:  取|pid|发给对应进程组。

         pid = -1:发送给进程有权限发送的系统中所有进程。

    进程组:每个进程都属于一个进程组,进程组是一个或多个进程集合,他们相互关联,共同完成一个实体任务,每个进程组都有一个进程组长,默认进程组ID与进程组长ID相同。

权限保护:super用户(root)可以发送信号给任意用户,普通用户是不能向系统用户发送信号的。 kill -9 (root用户的pid)  是不可以的。同样,普通用户也不能向其他普通用户发送信号,终止其进程。只能向自己创建的进程发送信号。普通用户基本规则是:发送者实际或有效用户ID == 接收者实际或有效用户ID

  循环创建5个子进程,任一子进程用kill函数终止其父进程。     【kill.c】

raiseabort函数

         raise函数:给当前进程发送指定信号(自己给自己发)    raise(signo) ==kill(getpid(), signo);

             intraise(int sig); 成功:0,失败非0值

         abort 函数:给自己发送异常终止信号 6) SIGABRT 信号,终止并产生core文件

             voidabort(void); 该函数无返回

软件条件产生信号 

alarm函数   

设置定时器(闹钟)。在指定seconds后,内核会给当前进程发送14)SIGALRM信号。进程收到该信号,默认动作终止。

每个进程都有且只有唯一个定时器。

unsigned intalarm(unsigned int seconds); 返回0或剩余的秒数,无失败。

         常用:取消定时器alarm(0),返回旧闹钟余下秒数。

         例:alarm(5) → 3sec → alarm(4) → 5sec → alarm(5) → alarm(0)

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

练习:编写程序,测试你使用的计算机1秒钟能数多少个数。                                              使用time命令查看程序执行的时间。       

程序运行的瓶颈在于IO,优化程序,首选优化IO。

         实际执行时间 = 系统时间 + 用户时间 + 等待时间

#include
#include
int main(void)
{
    int i;
    alarm(1);
    for(i = 0; ; i++)
        printf("%d\n", i);
    return 0;
}

setitimer函数

     设置定时器(闹钟)。可代替alarm函数。精度微秒us,可以实现周期定时。

    int setitimer(int which, const structitimerval *new_value, struct itimerval *old_value);     成功:0;失败:-1,设置errno

         参数:which:指定定时方式

     ①自然定时:ITIMER_REAL → 14 )SIGLARM                                             计算自然时间

    ②虚拟空间计时(用户空间):ITIMER_VIRTUAL → 26)SIGVTALRM             只计算进程占用cpu的时间

   ③运行时计时(用户+内核):ITIMER_PROF → 27)SIGPROF            计算占用cpu及执行系统调用的时间

使用setitimer函数实现alarm函数,重复计算机1秒数数程序。                

#include
#include
#include
/*
 * struct itimerval  {
        struct timeval{
            it_value.tv_sec;
            it_value.tv_usec;
        } it_interval;
        struct timeval {
            it_value.tv_sec;
            it_value.tv_usec;
        } it_value;
    } it, oldit;
*/
unsigned int my_alarm(unsigned int sec)
{
    struct itimerval it, oldit;
    int ret;
    it.it_value.tv_sec = sec;
    it.it_value.tv_usec = 0;
    it.it_interval.tv_sec = 0;
    it.it_interval.tv_usec = 0;
    ret = setitimer(ITIMER_REAL, &it, &oldit);
    if (ret == -1) {
        perror("setitimer");
        exit(1);
    }
    return oldit.it_value.tv_sec;
}
int main(void)
{
    int i;
    my_alarm(1);  //alarm(sec);
    for(i = 0; ; i++)
        printf("%d\n", i);
    return 0;
}

拓展,结合man page编写程序,测试it_interval、it_value这两个参数的作用。                

提示:     it_interval:用来设定两次定时任务之间间隔的时间。 it_value:定时的时长                              

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值