信号是异步进程间通信方式
进程对信号的响应方式:
<1> 忽略
SIGKILL 和 SIGSTOP 不能忽略
<2 > 捕捉
当进程收到信号, 此时执行的信号处理函数
<3 > 默认
SIGSTOP 改信号用于暂停一个进程, 且不能被阻塞, 忽略, 和处理, 默认操作为暂停进程
大部分信号对进程的默认操作方式都是杀死进程
子进程状态发生改变的时候, 操作系统向父进程发送 SIGCHLD, 默认对它处理方式是忽略
信号的发送与设置
1. 信号发送 kill() 与 raise()
int kill(pid_t pid, int sig);
参数:
pid: 可能选择有以下四种
1. pid 大于零时, 发送信号给进程号为 pid 的进程.
2. pid 等于零时, 信号将送往所有与调用 kill() 的那个进程属同一个使用组的进程.
3. pid 等于 - 1 时, 信号发送给所有的进程表中的进程, 除了进程 1(init).
4. pid 小于 - 1 时, 信号将送往以 - pid 为组标识的进程.
sig: 准备发送的信号代码, 假如其值为零则没有任何信号送出, 但是系统会执行错误检查, 通常会利用 sig 值为零来检验某个进程是否仍在执行.
返回值说明: 成功执行时, 返回 0. 失败返回 - 1
errno 被设为以下的某个值:
EINVAL: 指定的信号码无效 (参数 sig 不合法)
EPERM: 权限不够无法传送信号给指定进程
ESRCH: 参数 pid 所指定的进程或进程组不存在
int raise(int signo);
注意: raise 函数只允许进程向自身发送信号
实例如下:
- #include <stdio.h>
- #include <stdlib.h>
- #include <signal.h>
- #include <sys/types.h>
- #include <sys/wait.h>
- int main(int argc, const char *argv[])
- {
- pid_t pid;
- int ret;
- if((pid=fork())<0)
- {
- printf("Fork error\n");
- exit(EXIT_FAILURE);
- }
- if(pid==0)
- {
- printf("child(pid:%d) is waiting for any signal\n",getpid());
- raise(SIGSTOP);// 在子进程中使用 raise() 函数发出 SIGSTOP 信号, 使子进程暂停
- exit(EXIT_SUCCESS);
- }
- else
- {
- if(waitpid(pid,NULL,WNOHANG)==0)
- {
- sleep(10);
- kill(pid,SIGKILL);
- printf("parent kill child process %d\n",pid);
- }
- }
- waitpid(pid,NULL,0);
- return 0;
- }
- typedef void (*sighandler_t)(int);
- sighandler_t signal(int signum, sighandler_t handler);
功能: 设置进程对信号处理方式
参数:
@signum 信号的编号
@handler
SIG_IGN : 忽略信号
SIG_DFL : 使用默认处理方式
函数名 : 捕捉方式处理
返回值:
成功返回 handler, 失败返回 SIG_ERR
练习:
如何进行不阻塞, 不轮训方式回收僵尸态子进程
2. 在进程中设置一个定时器
unsigned int alarm(unsigned int seconds);
参数:
@seconds 定时的时间, 以秒为单位
注意:
一旦定时时间完成, 操作系统就会向进程发送 SIGALRM 信号
作业:
通过有名管道完成文件传输
./A file1 ------->fifo -------> ./B file2
A 进程:
读文件, 写管道
A 进程结束条件: 文件没有数据可读
B 进程:
读管道, 写文件
B 进程结束条件: 在写端关闭, 读端不阻塞, 如果管道中没有数据, 读管道会返回 0
来源: http://www.bubuko.com/infodetail-2680171.html