«Linux C 笔记:信号(Signal)和信号函数»
by pluvet on Jun 19, 2019

信号是什么,有什么用?

例子:今有进程A,B。他们两个负责下载两个不同的文件。A 下到一半了,给 B 发了一个通知:“我下了一半了”,于是 B 就知道,A 下了一半了。

(是什么)定义:信号是进程间异步通信的唯一机制,能够完成进程间消息传递的作用。

如果不清楚什么是异步:

同步:一定要等任务执行完了,得到结果,才执行下一个任务。
异步:不等任务执行完,直接执行下一个任务。
——《Linux C 编程实战》的要点总结

什么是异步通信

例子:异步就是 B 并不知道信号什么时候回来,它在做着自己的事情(下载)。突然来了一个 A 的信号,于是 B 直接处理 A 的信号,然后来了一连串的信号,然而 B 不用等第一个信号处理完了再处理下一个信号,他只管一个个收下来一个个处理。

是什么 定义:发送方发出数据后,不等接收方发回响应,接着发送下个数据包的通信方式。

信号怎么用

发信号有哪些方式?

发送信号的主要函数有:kill()、raise()、 sigqueue()、alarm()、setitimer()以及abort()。

kill 函数有什么用?

发送信号给指定的进程。适合已知 pid 的情况。这里的 kill 并不一定是要杀死进程。

raise 函数有什么用?

向进程本身发送信号。

sigqueue 函数有什么用?

支持信号带参数值。它可以把一个叫做 sigval 的结构体发过去。这个结构体里面可以存一个指针,因此就实现了发数据。

alarm 函数有什么用?

可以设置个定时器,一超时就给进程本身发数据。

setitimer 函数有什么用?

也能定时,但是更复杂。比如它支持三种类型的定时器。这里不赘述。

abort 函数有什么用?

如果目标进程设置了 SIGABRT(当调用abort函数或发生用户异常终止时,会发出 SIGABRT 信号),会解除 SIGABRT 的阻塞,然后向调用进程发送该信号。让其异常退出。

怎么接受和处理信号?

C 库函数 void (signal(int sig, void (func)(int)))(int) 设置一个函数来处理信号,即带有 sig 参数的信号处理程序。

这个函数原型看了就头大,我们拆开看看:

    void (
        *signal(
            int sig, 
            void (*func)(int)
            )
    )    
    (int)

我们一看其实并不复杂,第一个是你要收的信号,第二个是你要处理这个信号的函数,并且这个处理信号的函数有一个整数的参数。具体用法见:http://www.runoob.com/cprogramming/c-function-signal.html

那么我们来看看具体的例子:

    if(signal(SIGPIPE,SIG_IGN) == SIG_ERR) 
    {
        perror("can not catch signal:sigpipe\n");
        return -1;
    } 

这个 SIGPIPE 信号表示通信管道破裂(详见:http://www.veryitman.com/2018/04/15/%E4%B8%8D%E8%AE%A9-SIGPIPE-signal-%E5%A4%AA%E5%9A%A3%E5%BC%A0/

而这个 SIG_IGN 是 C 库自带的信号处理函数,表示忽略此信号。
最后这个 SIG_ERR 表示 signal 函数遇到错误。

所以这个例子的疑似就是:

  1. 忽视管道破裂函数。
  2. 如果忽视失败,就输出 can not catch signal:sigpipe,并返回 -1 。

参考文献

https://www.ibm.com/developerworks/cn/linux/l-ipc/part2/index1.html
kill - End a process or job, or send it a signal - IBM
[settimer()函数和alarm()函数]https://blog.csdn.net/seanyxie/article/details/5669104)
C 库函数 - signal()

Written with StackEdit.

添加新评论