≡菜单

Linux3d捕鱼达人–示例C程序来捕获3d捕鱼达人(SIGINT,SIGKILL,SIGSTOP等)

In the part 1 of the Linux3d捕鱼达人series, we learned about the fundamental concepts behind Linux 3d捕鱼达人s.

Building 上 the previous part, in 这个 article we will learn about how to catch 3d捕鱼达人s in a process. We will present the practical aspect of 3d捕鱼达人 handling using C program code snippets.

捕捉3d捕鱼达人

As already discussed in the previous article, If a process wishes to handle certain 3d捕鱼达人s then in the code, the process has to register a 3d捕鱼达人 handling function to the kernel.

The following is the prototype of a 3d捕鱼达人 handling function :

void <signal handler func name> (int sig)

The 3d捕鱼达人 handler function has void return type and accepts a 3d捕鱼达人 number corresponding to the 3d捕鱼达人 that needs to be handled.

To get the 3d捕鱼达人 handler function registered to the kernel, the 3d捕鱼达人 handler function pointer is passed as second argument to the ‘signal’ function. The prototype of the 3d捕鱼达人 function is :

void (*signal(int signo, void (*func )(int)))(int);

这似乎是一个复杂的声明。如果我们尝试对其进行解码:

  • 该函数需要两个参数。
  • The first argument is an 整型eger (signo) depicting the 3d捕鱼达人 number or 3d捕鱼达人 value.
  • The second argument is a pointer to the 3d捕鱼达人 handler function that accepts an 整型eger as argument and returns nothing (void).
  • 而‘signal’函数本身返回函数指针,其返回类型为void。

好吧,为了使事情变得简单,让我们使用typedef:

typedef void 西格芬奇(int)

所以,在这里我们做了一个新的类型‘sigfunc’.  Now using 这个 typedef, if we redesign the prototype of the 3d捕鱼达人 handler :

西格芬奇 *signal(int, 西格芬奇*);

Now we see that its easier to comprehend that the 3d捕鱼达人 handler function accepts an 整型eger and a 西格芬奇 type function pointer while it returns a 西格芬奇 type function pointer.

示例C程序来捕获3d捕鱼达人

大多数Linux用户使用组合键Ctr + C终止Linux中的进程。

Have you ever thought of what goes behind 这个. Well, whenever ctrl+c is pressed, a 3d捕鱼达人 SIGINT is sent to the process. The default action of 这个 3d捕鱼达人 is to terminate the process. But 这个 3d捕鱼达人 can also be handled. The following code demonstrates 这个 :

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

void sig_handler(int signo)
{
  如果(signo == SIGINT)
    打印 ("received SIGINT\n");
}

int main(void)
{
  if (signal(SIGINT, sig_handler) == SIG_ERR)
  打印 ("\ncan't catch SIGINT\n");
  // A long long wait so that we can easily issue a 3d捕鱼达人 to 这个 process
  while(1) 
    sleep(1);
  return 0;
}

在上面的代码中,我们使用无限while循环模拟了一个长时间运行的过程。

A function sig_handler is used a s a 3d捕鱼达人 handler. This function is registered to the kernel 通过 passing it as the second argument of the system call ‘signal’在main()函数中。该函数的第一个参数‘signal’ is the 3d捕鱼达人 we 整型end the 3d捕鱼达人 handler to handle which is SIGINT in 这个 case.

附带说明一下,使用函数sleep(1)有一个原因。该函数已在while循环中使用,因此while循环会在一段时间后执行(在这种情况下为一秒钟)。这很重要,因为否则,无限期的while循环会疯狂运行,可能会消耗大量CPU,从而使计算机非常缓慢。

无论如何,返回,当进程运行时,我们尝试使用Ctrl + C终止进程:

$ ./sigfunc
^Creceived SIGINT
^Creceived SIGINT
^Creceived SIGINT
^Creceived SIGINT
^Creceived SIGINT
^Creceived SIGINT
^Creceived SIGINT

我们在上面的输出中看到,我们多次尝试了组合键ctrl + c,但是每次该过程’t terminate. This is because the 3d捕鱼达人 was handled in the code and 这个 was confirmed from the print we got 上 each line.

SIGKILL,SIGSTOP和用户定义的3d捕鱼达人

Apart from handling the standard 3d捕鱼达人s(like INT, TERM etc) that are available. We can also have user defined 3d捕鱼达人s that can be sent and handled. Following is the code handling a user defined 3d捕鱼达人 USR1 :

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

void sig_handler(int signo)
{
    if (signo == SIGUSR1)
        打印 ("received SIGUSR1\n");
    else if (signo == SIGKILL)
        打印 ("received SIGKILL\n");
    else if (signo == SIGSTOP)
        打印 ("received SIGSTOP\n");
}

int main(void)
{
    if (signal(SIGUSR1, sig_handler) == SIG_ERR)
        打印 ("\ncan't catch SIGUSR1\n");
    if (signal(SIGKILL, sig_handler) == SIG_ERR)
        打印 ("\ncan't catch SIGKILL\n");
    if (signal(SIGSTOP, sig_handler) == SIG_ERR)
        打印 ("\ncan't catch SIGSTOP\n");
    // A long long wait so that we can easily issue a 3d捕鱼达人 to 这个 process
    while(1) 
        sleep(1);
    return 0;
}

We see that in the above code, we have tried to handle a user defined 3d捕鱼达人 USR1. Also, as we know that two 3d捕鱼达人s KILL and STOP cannot be handled. So we have also tried to handle these two 3d捕鱼达人s so as to see how the ‘signal’在这种情况下,系统调用会响应。

当我们运行上面的代码时:

$ ./sigfunc

can't catch SIGKILL

can't catch SIGSTOP

所以上面的输出清楚地表明,只要系统调用‘signal’ tries to register handler for KILL and STOP 3d捕鱼达人s, the 3d捕鱼达人 function fails indicating that these two 3d捕鱼达人s cannot be caught.

Now we try to pass the 3d捕鱼达人 USR1 to 这个 process using the 杀死命令:

$ kill -USR1 2678

在运行上述程序的终端上,我们看到:

$ ./sigfunc

can't catch SIGKILL

can't catch SIGSTOP
received SIGUSR1

So we see that the user defined 3d捕鱼达人 USR1 was received in the process and was handled properly.

如果您喜欢这篇文章,您可能还会喜欢..

  1. 50个Linux Sysadmin教程
  2. 50个最常用的Linux命令(包括示例)
  3. 排名前25位的最佳Linux性能监视和调试工具
  4. 妈妈,我找到了! – 15个实用的Linux Find命令示例
  5. Linux 101 Hacks第二版电子书 Linux 101黑客手册

Bash 101 Hacks书 Sed和Awk 101黑客手册 Nagios Core 3书 Vim 101黑客手册

{ 21 评论… 加一 }

  • 安德森·文图里尼(Anderson Venturini) 2012年3月9日,上午6:34

    谢谢!很棒的帖子!相当讲究和客观。恭喜! --

  • 贾拉尔·哈吉霍拉玛利 2012年3月9日,上午11:15

    你好

    非常感谢,非常好的文章。

    再次感谢..

  • 尼玛 2012年3月10日,上午6:28

    嗨,我编辑了代码以显示按下ctrl + c的次数:

    void sig_handler(int signo){
    static 整型 counter=1;
    如果(signo == SIGINT)
    计数器++;
    打印 (“已收到SIGINT%s次\ n”, counter);
    }

    但是当我按Ctrl + c时,它说:“分段故障(核心已转储)”
    为什么?

  • Himanshu 2012年3月10日,晚上11:40

    @尼玛
    可能是以下几行导致崩溃:
    打印 (“已收到SIGINT%s次\ n”, counter);

    由于计数器是类型‘int’因此您需要在上一行中使用%d而不是%s。
    让我知道这是否解决了您的问题…

  • 尼玛 2012年3月10日,晚上11:56

    谢谢。一世 didn’认为问题是如此简单。

  • Himanshu Arora 2012年3月12日,上午3:31

    @尼玛
    别客气 -

  • 加内什 2012年4月27日,上午12:01

    @尼玛
    您已经声明
    static 整型 counter=1;
    每当您按下Ctrl + c键时,
    计数器值初始化为1,并且它是静态的,因此您应该将static声明为全局变量。’t在sig_handler函数中声明,在main之上声明,希望它将起作用…….

  • 赛义德 2012年8月29日,上午5:48

    @ganesh

    bhai不要给任何误解………只是去阅读abt静态变量,然后使cmnt okey….both are wrking….static n global…。我的意思是您的xplanation很错…..

  • 冠军 2012年9月27日,上午9:49

    非常感谢这篇文章,

    它确实帮助我了解了自己的课程并进行了实际工作。

    来自法国的问候!

  • 基兰 2012年12月16日,上午3:31

    请帮助我在Unix中找到一些程序来区分fork和vfork

  • 排骨 2013年1月9日,上午11:51

    谢谢。一世’您已经从此页面以及您网站上的许多其他页面中学到了很多。非常丰富。

  • 弗拉德 2013年1月15日,上午7:48

    Please consider __not__ writing a 3d捕鱼达人 handler like that. This is obsolete and may trigger an undefined behavior. 3d捕鱼达人() does not work well in multi-threaded environment and 打印 () function is not reentrant. See 这个 更多细节。

  • Arjun Pakrashi 2013年12月4日,下午12:52

    的行为‘signal’ is different in different platforms. Some may reset the handler to SIG_IGN immediately after it enters the handler, therefore inorder to handle another occurrence of the 3d捕鱼达人, you need to call the ‘signal’ function again to set the 3d捕鱼达人 disposition. This is the original Unix behaviour. BSD implementation will not set the disposition, but block that 3d捕鱼达人 while inside the handler, so the handler will not get called recursively.

    最好是用‘sigaction’ to set 3d捕鱼达人s and define the precise behaviour. This is defined 通过 POSIX and the behaviour is defined in POSIX complaint systems.

    另外要注意的是‘printf’ is not an async-signal safe function, therefore it is not safe to call 打印 within a 3d捕鱼达人 handler. For demo, it is fine, but worth mentioning.

  • 拉姆韦尔 2014年3月8日,上午4:43

    嗨,请问我能告诉我您在项目中开发RRC-LTE层时遇到的问题吗?UE方面请帮助我,因为我没有在这一层工作,但我正在给我的面试官和面试官询问
    –>您的工作是什么,我以程序员的身份提及您所面临的问题
    –>how u was handling 3d捕鱼达人 error in yur code
    –>什么是Scrum,jira

  • 拉杜 2014年3月15日,上午10:17

    根据Linux手册,将sleep()与alarm()混合是一个坏主意,因为它们都共享相同的计时器:对一个调用将干扰其他计时器的使用

    无论如何,我喜欢你的东西!

  • hu 2014年5月29日,上午12:51

    感谢您的帮助文章!
    In the 3d捕鱼达人 handler function I didn’t see the code to reinitialize 3d捕鱼达人 handler itself, so why could handler function be executed at the second time of Ctrl-C was clicked?
    Deitel的书在其实现中放了一行函数处理程序。

  • 人体模型vs 2014年7月2日,上午3:03

    what is the use of 3d捕鱼达人(SIGINT,);

  • 尼克·H 2015年9月17日,上午4:50

    Calling pause() blocks until a 3d捕鱼达人 is received. This is even more efficient than while(1) { sleep(1); }

  • schezel2000 2015年12月17日,下午3:27

    I would be careful using 打印 inside a 3d捕鱼达人 handler because it is not 3d捕鱼达人 save. You should use write instead. I learned 这个 the hard way.

  • 拉胡尔 2016年4月30日,上午10:51

    3d捕鱼达人(2,);
    Or 3d捕鱼达人(SIGINT,); will generate error of too few arguments in 3d捕鱼达人 function.

  • 安德鲁·努 二月6,2019,7:18下午

    嗨Ramesh,
    Thanks for writing 这个 tutorial. I noticed that you are using 打印 () function inside the 3d捕鱼达人 handler function (sig_handler) . Please note that you should not use 打印 () in any 3d捕鱼达人 handling function,because it is not an async-signal-safe function, and could potentially destabilize the system.
    请看一下: http://man7.org/linux/man-pages/man7/signal-safety.7.html

    谢谢,
    安德罗

发表评论