在Linux系统中 发送一个信号的函数是,Linux系统编程 | 信号的产生

139239348_1_20180723064942638本文字数:2108字阅读时间:6分钟

139239348_2_20180723064942716

作者

良许

一个热爱技术的程序猿

终端按键产生信号

ctrl + c

发送2号信号SIGINT,将中止当前进程。SIGINT的“INT”是interrupt的意思;

ctrl + z

发送20号信号SIGTSTP,暂停/停止当前进程。SIGTSTP中的“T”是terminal的意思。进程收到此信号后,将由当前转入后台,可用ps aux找到它。

比如说,我们使用vim编写代码时,需要在vim以外处理一些事情,但又不想退出vim,可用ctrl + z命令让vim进程进入后台,之后再用fg命令重新将vim进程唤回前台,继续编辑;

ctrl + \

发送 3号信号SIGQUIT给前台进程组中的所有进程,终止前台进程并生成 core 文件;

硬件异常产生信号

a. 除0操作

产生8号信号SIGFPE,终止进程并产生core文件。SIGFPE的“F”是float的意思;

b. 非法访问内存

产生11号信号SIGSEGV,段错误;

c. 总线错误

产生7号信号SIGBUS;

kill函数/命令产生信号

从字面上来看,kill是杀死的意思,但这个命令/函数真正的意思是向进程发送信号。真不知道当时设计这个命令/函数的人是怎么想的。

kill命令使用方法:

kill -信号编号/宏 进程号。比如:kill -SIGKILL 1893,表示发送SIGKILL信号给1893号进程,即杀死1893号进程。

kill函数的用法:

函数原型:

int kill(pid_t pid, int sig);

返回值:

成功:返回0;失败:返回-1,并设置errno。

参数说明:

sig:要发送的信号,最好写宏名,而不要写信号编号,因为各个平台信号的编号可能不一样,而宏名都是维一的;

pid:要发送的目标进程;

pid > 0:发送信号给进程号为pid的进程;

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

pid <>

pid = -1:发送给进程有权限发送的系统中所有进程。啥是“有权限发送”?比如你就不能给init进程发信号,因为你没权限。

例程:

循环创建5个进程,并杀死第三个子进程。1#include

2#include

3#include

4#include

5

6

7#define N 5

8

9int main()

10{

11        int i = 0;

12        pid_t pid, q;

13

14        for (i = 0; i <>

15                /* 循环创建N个子进程 */

16                pid = fork();

17                if (pid == -1)

18                        printf('ERROR: fork error!\n');

19                else if (pid == 0)

20                        break;

21

22                if (i == 2)

23                        q = pid;        // 保留第三个子进程的pid

24        }

25

26        if (i <>

27                while (1) {

28                        printf('I'm %dth child process, pid = %d\n', i, getpid());

29                        sleep(1);

30                }

31        } else if (i == N) {

32                sleep(1);

33                printf('I'm parent process\n');

34                kill(q, SIGKILL);

35                while (1);

36        }

37

38        return 0;

39}

raise和abort函数

rase函数:

int raise(int sig); 成功:返回0,失败:返回非0值。

给当前进程发送指定信号。简单一句话:自己给自己发信号。

abort函数:

void abort(void); 无返回值。

给自己发送异常终止信号SIGABRT,终止进程并产生core文件。

alarm函数

函数原型:

unsigned int alarm(unsigned int seconds);

返回值:

返回0或者上次闹钟剩余秒数,无失败情况;

函数作用:

设置定时器,在指定时间之后,内核给调用alarm的函数发送SIGALRM信号。进程收到该信号后,默认动作是终止当前进程。

每个进程有且只有一个定时器,并且与进程的状态无关。也就是说,不管进程处于就绪、运行、挂起(阻塞/暂停)、终止、僵尸、孤儿,alarm定时器一直都在计时。

常见用法:

alarm(5); --> 5秒后发送SIGALRM信号。如果在2秒后调用alarm(2),则alarm(2)返回值是3,并且在2秒后发送SIGALRM信号;

alarm(0); --> 取消定时器,并返回上次调用alarm剩下的秒数。

1#include

2#include

3

4int main()

5{

6        unsigned int t = 0;

7        printf('process start..\n');

8        alarm(10);

9        sleep(2);

10        t = alarm(2);

11        printf('time left: %d\n', t);

12        while (1);      // 进程停在此处,直到收到定时器信号SIGALRM将进程杀死

13

14        return 0;

15}

setitimer函数

与alarm类似,可设置定时器,但是,alarm函数定时精度只能到秒,而setitimer函数定时可达到微秒级,并且可以周期定时。

函数原型:

int setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value);

返回值:

成功:返回0;失败:返回-1,并设置errno。

参数说明:

参数which:指定定时方式:

a. 自然定时:ITIMER_REAL。计算程序运行自然时间,就是程序不管在内核态还是用户态,都计时。到达时间点后,发送SIGARM信号;

b. 用户空间定时:ITIMER_VIRTUAL。只计算进程战胜CPU的时间,即用户空间时间。到达时间点后,发送SIGVTALRM信号;

c. 运行时计时:ITIMER_PROF。计算占用cpu及执行系统调用的时间,也即用户空间时间及内核时间总和。到达时间点后,发送SIGPROF信号。

这三种定时方式,最常用的就是自然定时法,即参数为ITIMER_REAL的定时方式,而后两种方式不常用,有用到时再查手册。

结构体struct itimerval有两个成员,一个是it_value, 另一个是it_interval。他们俩都是可以精确到微秒的,以struct timeval来控制具体时间。it_value控制了多久之后第一次发送信号,之后会循环发送,间隔是it_interval。

参数new_value:设定的定时时间;

参数old_value:上次调用setitimer剩余的时间。

例程:

自己实现alarm函数:

1#include

2#include

3#include

4#include

5

6unsigned int my_alarm(unsigned int sec)

7{

8        struct itimerval new_value, old_value;

9        int ret = -1;

10

11        new_value.it_value.tv_sec = sec;

12        new_value.it_value.tv_usec = 0;

13        new_value.it_interval.tv_sec = 0;

14        new_value.it_interval.tv_usec = 0;

15

16        ret = setitimer(ITIMER_REAL, &new_value, &old_value);

17        if (ret == -1) {

18                printf('ERROR: setitimer error!\n');

19                exit(1);

20        }

21        return old_value.it_value.tv_sec;

22}

23

24int main()

25{

26        unsigned int t = 0;

27        printf('process start..\n');

28        alarm(10);

29        sleep(2);

30        t = alarm(2);

31        printf('time left: %d\n', t);

32        while (1);      // 进程停在此处,直到收到定时器信号SIGALRM将进程杀死

33

34        return 0;

35}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值